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
}
Exemple #2
0
// 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, "  ")
}
Exemple #3
0
// 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
}