func (p *ParseClass) resolvePointer(ctx context.Context, r resolver.Resolver, field *graphql.Field) (interface{}, error) { fieldName := field.Name fieldInfo := p.class.Fields[fieldName] pc, err := NewParseClass(p.client, fieldInfo.TargetClass, p.schema) if err != nil { return nil, err } // only resolve if we can obtain the objectId data, ok := p.Data[fieldName] if !ok { return nil, nil } asMap, ok := data.(map[string]interface{}) if !ok { return nil, nil } oid := asMap["objectId"] if oid == nil { return nil, nil } objectID, ok := oid.(string) if !ok { return nil, nil } if t, ok := tracer.FromContext(ctx); ok { t.IncQueries(1) } err = pc.client.GetClass(fieldInfo.TargetClass, objectID, &pc.Data) return pc, err }
// ServeHTTP provides an entrypoint into a graphql executor. It pulls the query from // the 'q' GET parameter. func (h *ExecutorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", r.Header.Get("Access-Control-Request-Headers")) if r.Method == "OPTIONS" { w.WriteHeader(200) return } decoder := json.NewDecoder(r.Body) var qreq Request err := decoder.Decode(&qreq) if err != nil { log.Println("error parsing:", err) writeErr(w, err) return } q := qreq.Query h.mutex.Lock() /* //TODO(tallstreet): reject non-GET/OPTIONS requests */ var doc graphql.Document if err := parser.New("graphql", strings.NewReader(q)).Decode(&doc); err != nil { h.mutex.Unlock() log.Println("error parsing graphql:", err.Error()) writeErr(w, err) return } h.mutex.Unlock() parser.InlineFragments(&doc) var result = Result{} for o := range doc.Operations { operation := doc.Operations[o] asjson, _ := json.MarshalIndent(operation, "", " ") log.Println(string(asjson)) // if err := h.validator.Validate(operation); err != nil { writeErr(w, err); return } ctx := context.Background() if r.Header.Get("X-Trace-ID") != "" { t, err := tracer.FromRequest(r) if err == nil { ctx = tracer.NewContext(ctx, t) } } ctx = context.WithValue(ctx, "http_request", r) ctx = context.WithValue(ctx, "variables", qreq.Variables) if r.Header.Get("X-GraphQL-Only-Parse") == "1" { writeJSONIndent(w, operation, " ") return } data, err := h.executor.HandleOperation(ctx, operation) if err != nil { w.WriteHeader(400) result.Error = &Error{Message: err.Error()} } else { result.Data = data } if t, ok := tracer.FromContext(ctx); ok { t.Done() result.Trace = t } } writeJSONIndent(w, result, " ") }
// ServeHTTP provides an entrypoint into a graphql executor. It pulls the query from // the 'q' GET parameter. func (h *ExecutorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", r.Header.Get("Access-Control-Request-Headers")) if r.Method == "OPTIONS" { w.WriteHeader(200) return } decoder := json.NewDecoder(r.Body) var qreq Request err := decoder.Decode(&qreq) if err != nil { log.Println("error parsing:", err) writeErr(w, err) return } q := qreq.Query /* //TODO(tallstreet): reject non-GET/OPTIONS requests q := r.URL.Query().Get("q") */ var doc graphql.Document if err := parser.New("graphql", strings.NewReader(q)).Decode(&doc); err != nil { log.Printf(err.Error()) } else { // fs, _ := os.Open("../tests/complex-as-possible.graphql") // e, _ := ioutil.ReadAll(fs) // log.Printf(string(e)) log.Printf(prettyprint.AsJSON(doc)) } /* log.Println("query:", q) operation, err := parser.ParseOperation([]byte(q)) if err != nil { log.Println("error parsing:", err) writeErr(w, err) return } */ operation := doc.Operations[0] asjson, _ := json.MarshalIndent(operation, "", " ") log.Println(string(asjson)) // if err := h.validator.Validate(operation); err != nil { writeErr(w, err); return } ctx := context.Background() if r.Header.Get("X-Trace-ID") != "" { t, err := tracer.FromRequest(r) if err == nil { ctx = tracer.NewContext(ctx, t) } } ctx = context.WithValue(ctx, "http_request", r) if r.Header.Get("X-GraphQL-Only-Parse") == "1" { writeJSONIndent(w, operation, " ") return } data, err := h.executor.HandleOperation(ctx, operation) result := Result{Data: data} if err != nil { w.WriteHeader(400) result.Error = &Error{Message: err.Error()} } if t, ok := tracer.FromContext(ctx); ok { t.Done() result.Trace = t } }
func (p *ParseClass) get(ctx context.Context, r resolver.Resolver, f *graphql.Field) (interface{}, error) { var results []map[string]interface{} // TODO(tallstreet): handle overlap between special fields and user defined fields on a class elegantly whereClause := make(map[string]interface{}) for _, a := range f.Arguments { // only populate where clause if the field isn't in out special field list if !specialFieldsSet[a.Name] { whereClause[a.Name] = a.Value } } if explicitWhere, ok := f.Arguments.Get("where"); ok { asMap, ok := explicitWhere.(map[string]interface{}) if !ok { return nil, fmt.Errorf("explicit where fields must be maps, got '%T'", explicitWhere) } whereClause = asMap } whereJSON, err := json.Marshal(whereClause) if err != nil { return nil, err } // limit limit := DefaultLimit if l, ok := f.Arguments.Get("limit"); ok { if lim, ok := l.(int); ok { limit = lim } else { return nil, fmt.Errorf("'limit' argument should be an integer. Got %#v", l) } } // order order := "" if o, ok := f.Arguments.Get("order"); ok { if orderStr, ok := o.(string); ok { order = orderStr } else { return nil, fmt.Errorf("'order' argument should be a string. Got %#v", o) } } spew.Dump("ORDER:", order, f.Arguments) query := &parse.QueryOptions{ Where: string(whereJSON), Limit: limit, Order: order, } if t, ok := tracer.FromContext(ctx); ok { t.IncQueries(1) } if err := p.client.QueryClass(p.class.ClassName, query, &results); err != nil { return nil, err } typedResults := make([]*ParseClass, 0, len(results)) for _, r := range results { pc, err := NewParseClass(p.client, p.class.ClassName, p.schema) if err != nil { return nil, err } pc.Data = r typedResults = append(typedResults, pc) } return typedResults, err }