Git Product home page Git Product logo

graphql's Issues

bug: parse response from graph query failed(some success, some failed) and no error returns

question

when execute below query in thegraph for uniswap online explorer

all of them have result

but when invoke it from program, only first query (tokenDaydata query) have result, the second & thrid failed parse

program api endpoint: https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2

program code: https://github.com/huahuayu/graphql commitId: 1c05c8d0ac16f934d431b319f9b9ac666d1d90f3

the three queries

tokenDaydata query

		{
		 tokenDayDatas(orderBy: date, orderDirection: asc,
		  where: {
			token: "0x6b175474e89094c44da98b954eedeac495271d0f"
		  }
		 ) {
			id
			date
			priceUSD
			totalLiquidityToken
			totalLiquidityUSD
			totalLiquidityETH
			dailyVolumeETH
			dailyVolumeToken
			dailyVolumeUSD
			 }
			}

global stat query

{
uniswapFactory(id: "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"){
  totalVolumeUSD
  totalLiquidityUSD
  txCount
}
}

pair query data

{
 pair(id: "0xa478c2975ab1ea89e8196811f51a7b7ade33eb11"){
     token0 {
       id
       symbol
       name
       derivedETH
     }
     token1 {
       id
       symbol
       name
       derivedETH
     }
     reserve0
     reserve1
     reserveUSD
     trackedReserveETH
     token0Price
     token1Price
     volumeUSD
     txCount
 }
}

output of program

{0 0 0 1589328000 0x6b175474e89094c44da98b954eedeac495271d0f-18395 0 0 220 0} # first query
&{{{   {   }  {   }    }}} # second query
&{{{  }}} # third query

root cause

The parser of response have problem, the query is success but the second & third response is not parsed.

The res is not parsed correctly when it is a struct.

	if err := graphqlClient.Run(context.Background(), graphqlRequest, &res); err != nil {
		panic(err.Error())
	}

If it's a interface{} passed in as response, then it will be ok, but it's in map[string]interface{} format.

Getting Error :"Must Provide Query String"

A simple query request is working via the "GraphQL Playground" against our GraphQL server.
However, it's getting error "Must Provide Query String" while using your package to make the request.

Not sure if that's because of the ContentType (multipart/form-data vs application/json). That's definitely a blocker.

Get the status code in case of error

Hi !
I can't find a way to get the response status code when an HTTP error is returned.
My use case is that I want to check if it is a 401 (in which case I want to renew the client token).

Thanks !

Trouble deleting [uuid!]!

I'm sending a delete mutation in statement that requires an array of uuids. In graphiql it works to declare the variable and give it

"variable":["uuid1","uuid2"]
When I print the req.Vars() to the logs to see what is getting passed, the data works when I copy it into graphiql to test.

I get map[id_array:["18259036-f4f9-298f-7cf5-529977cd0254","d4b1141b-2d82-4b67-e523-6c0d55c8fc5b"]]

However when I use the machinebox client I get the following error graphql: invalid input syntax for type uuid: "["18259036-f4f9-298f-7cf5-529977cd0254","d4b1141b-2d82-4b67-e523-6c0d55c8fc5b"]"

It appears to be wrapping double quotes around the square brackets later in the request process.

Publish new version?

Hi there! I notice when I go get github.com/machinebox/graphql, the version I have is missing the response status code checks that landed in #19. Does something need to be published or a version updated for me to get the latest code? Thank you!

Empty response object

Hi, after a few hours investigating what is happening, I can't find the problem.

Here is my full code, I have used that website to convert a response in struct from a web interface response (playground).

https://mholt.github.io/json-to-go/

import (
        "fmt"
	"github.com/machinebox/graphql"
)

// StatsResponse structure to parse a stats response.
type StatsResponse struct {
	Data struct {
		Stats struct {
			Report struct {
				Edges []struct {
					Node struct {
						StatsData struct {
							Access struct {
								AccessData struct {
									Code     string `json:"code"`
									Name     string `json:"name"`
									Supplier struct {
										SupplierData struct {
											Code string `json:"code"`
											Name string `json:"name"`
										} `json:"supplierData"`
									} `json:"supplier"`
								} `json:"accessData"`
							} `json:"access"`
							Client struct {
								ClientData struct {
									Code string `json:"code"`
									Name string `json:"name"`
								} `json:"clientData"`
							} `json:"client"`
							Operations []struct {
								Operation struct {
									OperationData struct {
										Code  string   `json:"code"`
										Types []string `json:"types"`
										API   struct {
											Code string `json:"code"`
										} `json:"api"`
									} `json:"operationData"`
								} `json:"operation"`
								TotalHits    int    `json:"totalHits"`
								TrafficType  string `json:"trafficType"`
								DetailedHits []struct {
									Code string `json:"code"`
									Type string `json:"type"`
									Hits int    `json:"hits"`
									Time int    `json:"time"`
								} `json:"detailedHits"`
							} `json:"operations"`
						} `json:"statsData"`
						AdviseMessage []struct {
							Code        int    `json:"code"`
							Description string `json:"description"`
							Level       string `json:"level"`
							External    struct {
								Code    string `json:"code"`
								Message string `json:"message"`
							} `json:"external"`
						} `json:"adviseMessage"`
					} `json:"node"`
				} `json:"edges"`
			} `json:"report"`
		} `json:"stats"`
	} `json:"data"`
}

type filterInput struct {
	From        time.Time `json:"from"`
	To          time.Time `json:"to"`
	Mode        string    `json:"mode"`
	Owners      []string  `json:"owners"`
	Clients     []string  `json:"clients"`
	Suppliers   []string  `json:"suppliers"`
	ServiceApis []string  `json:"serviceApis"`
	Operation   []string  `json:"operation"`
	Groups      []string  `json:"groups"`
}

client := graphql.NewClient("https://api.xxxxxxx.com")

	req := graphql.NewRequest(`
	query QueryStatsDetails($filterInput: StatsFilterInput!) {
		stats {
			report(filter: $filterInput) {
				edges {
					node {
						statsData {
							access {
								accessData {
									code
									name
									supplier {
										supplierData {
											code
											name
										}
									}
								}
							}
							client {
								clientData {
									code
									name
								}
							}
							operations {
								operation {
									operationData {
										code
										types
										api {
											code
										}
									}
								}
								totalHits
								trafficType
								detailedHits {
									code
									type
									hits
									time
								}
							}
						}
						adviseMessage {
							code
							description
							level
							external {
								code
								message
							}
						}
					}
				}
			}
		}
	}	
	`)

	var filterInputBuyer = filterInput{
		From:	time.Date(2019, time.April, 30, 0, 0, 0, 0, time.UTC),
		To: time.Date(2019, time.April, 30, 23, 59, 59, 0, time.UTC),
		Mode:        "BUYER",
		Clients:     make([]string, 0, 1),
		ServiceApis: make([]string, 0, 8),
		Operation:   make([]string, 0, 4),
		Groups:      make([]string, 0, 1),
	}

	filterInputBuyer.Clients = append(filterInputBuyer.Clients, "cli8")
	filterInputBuyer.Groups = append(filterInputBuyer.Groups, "XXXXXX")
	filterInputBuyer.Operation = append(filterInputBuyer.Operation, "SEARCH", "QUOTE", "BOOKING", "OTHER")
	filterInputBuyer.ServiceApis = append(filterInputBuyer.ServiceApis, "ACTIVITIES", "CAR", "HOTEL", "PACKAGE", "PAYMENT", "TRANSFERS", "TRANSPORTATION", "VIRTUALACCOUNT")

	// Set authorization bearer
	req.Header.Add("Authorization", header)

	req.Var("filterInput", filterInputBuyer)

	var res StatsResponse
	ctx := context.Background()
	if err := client.Run(ctx, req, &res); err != nil {
		log.Fatal(err)
	}
	fmt.Println("response", res)

I'm always receiving an empty res object, and if I send it through playground works perfectly. What am I doing wrong? Someone can help me?

Many thanks!

does this library work for mutation?

query := mutation ($activeIp: String!) { registerActive(regReq:{ active: { ip:$active } }) { status } }

req := graphql.NewRequest(query)
req.Var("active", "1.1.1.1")

while sending I get:
graphql: name 'json' is not defined

Handle response status codes

I think there should be something like

if res.StatusCode != http.StatusOK {

after

res, err := c.httpClient.Do(r)

In case the server returns a 400 or a 500, the current code returns:

2018/01/17 17:44:37 << {"errors":[{}]}
graphql:

Abandoned?

Hi there,

Look like this project is no longer maintained?

Thanks.

Add support for top level extensions field.

The graphQL spec specifies an extensions field in the top level response. It's reserved for implementation specific data. However right now there is no way for a client to reach that data. Some endpoints return useful data about query cost. Perhaps a function like RunWithExtensions and convert Run to just pass nil to it for backwards compatibility and for anyone that doesn't care about them. I'd be willing to put together a PR if this is something that would be integrated.

Library struggles with non-200 status codes which have valid JSON bodies

We noticed an issue when using this library against AWS API Gateway with a WAF, although this issue is not limited to these technologies.

When hitting a WAF if you don't pass the rules you will get a 403 response with the body of {"message":"Forbidden"}. When graphql parses this it it chokes.

graphql/graphql.go

Lines 140 to 145 in 3a92531

if err := json.NewDecoder(&buf).Decode(&gr); err != nil {
if res.StatusCode != http.StatusOK {
return fmt.Errorf("graphql: server returned a non-200 status code: %v", res.StatusCode)
}
return errors.Wrap(err, "decoding response")
}

If you read the above code it attempts to decode the JSON body. Only if this fails does it check the status code. This causes bugs because the status code is 403, and a non-graphql layer is returning a JSON output.

This ends up with a graphql response that thinks it is successful, but in reality failed. The only sign that it failed is that the object that gets returned doesn't have any decoded data in it (unless it by chance has a "message" field).

My suggested fix would be to check the status code first, and error if it is a non-200. While this is not an official API definition APIs-guru points out this issue:

Note: For any non-2XX response, the client should not rely on the body to be in GraphQL format since the source of the response may not be the GraphQL server but instead some intermediary such as API gateways, firewalls, etc.

My concern would be that some non-compliant graphql instance would be returning 403 and similar error codes with valid graphql errors. In which case you encounter a new bug. Potentially we could do both, check if status code is non-200 and return an error. Then also parse the JSON?

Send query and variables in json body

I think the issues #7 and #11 are both related to the the client sending data and variables as FormDataContentType but most server implementations expect them as application json in body like

{
  "query":  `query here`,
  "variables": obj with variables here
}

HTTP rate limit errors are not propagated.

Github graphql errors.

We were running a lot of graphql queries using multiple coroutines, we were running into issues where data returned is null.
In this case, we assume there is no more data from Github and stop the iteration. Eventually, we realized that data that we have doesn't match up with that of Github. Further debugging we found that we were getting secondary rate limit errors which were not sent back to the client.

Function:
c.runWithJSON(ctx, req, resp)

	res, err := c.httpClient.Do(r)
	if err != nil {
		return err
	}
	defer res.Body.Close()

Does not propagate 403 rate limit errors , in which case if there is 403 library will try to read the data and pass it upstream.
Example error message:

"documentation_url": "https://docs.github.com/en/free-pro-team@latest/rest/overview/resources-in-the-rest-api#secondary-rate-limits",
  "message": "You have exceeded a secondary rate limit. Please wait a few minutes before you try again."

Sample fix:

if res.StatusCode != 200 {
return errors.Wrap(err, "status code error ")
}

Response header

How do i get "response header" like Content-Encoding ? I need to extract gzip response.

I've used code like this before for http

if resp.Header.Get("Content-Encoding") == "gzip" {
    // resp.Header.Del("Content-Length")
    zr, err := gzip.NewReader(resp.Body)
    if err != nil {
        return nil, err
    }
    resp.Body = gzreadCloser{zr, resp.Body}
}

Been getting following error `Post -url-: EOF`

Has anyone seen this kind of error before? I ran this client on a loop for the last 12 hours, and around once every hour i noticed this error. It did not return any other contextual information

More documents or examples for ResponseStruct may be helpful

For a query or mutation, we must use a wrapper struct as the response struct.
This is very counterintuitive and should be pointed out in the example.
For example, for the following query,
type Query {
lesson(id: ID!): Lesson!
}
We need the following wrapper struct as the response,
type RespData {
Lesson: Lesson json: "lesson"
}
Or we can do as following:
var respData map[string]interface{}
convertMapDataToLesson(respData)

Subscription supported ?

Anyone know if this supports subscriptions ? Could not see it.

Library looks great for wrapping grpc microservices. Am guessing that was the teams main use case ?

Promote Current Master to a Release

Hello,

When can we have this in a release, please?

return fmt.Errorf("graphql: server returned a non-200 status code: %v", res.StatusCode)

We need this check and it's not available in V2.2. Can master be promoted to a release sometime soon?

Thanks.

Question on mocking graphql.Newclient

Thank you for this excellent package! Made writing some scripts with Go and our GraphQL API (specifically this GraphQL API which has been amazing https://github.com/hasura/graphql-engine).

We are using Hasura with Lambda event functions, which takes a events.APIGatewayProxyRequest. Since we are using the "serverless" functionality we decided to use Go for Lambda and started writing unit tests against our Hasura API.

My question is to make sure I am on the right track, I have used some of your test code to get myself pretty far, so thank you, but I am stuck on one specific problem. Here are the steps I have taken so far:

  1. Create a new test server
  2. Write the example JSON response
  3. Pass srv.URL to graphql.NewClient(srv.URL)

Here is a sample of the test:

srv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    io.WriteString(w, `{
	"data": {
		"insert_bookings": {
		"returning": [
			{
			"id": "TX123456789",
			"created_at": "2019-06-19T00:08:16.547491+00:00",
			"updated_at": "2019-06-19T00:08:16.547491+00:00"
			}
		]
		},
		"insert_booking_events": {
		"returning": [
			{
			"id": "bdeee2fe-7318-46bd-9b16-6c47ba12129a",
			"vehicle_bookings_id": "TX123456789",
			"status": "completed",
			"created_at": "2019-06-19T00:08:16.547491+00:00",
			"updated_at": "2019-06-19T00:08:16.547491+00:00"
			}
		]
		}
	}
	}`)
}))
defer srv.Close()

However, when running the tests, I am getting an error with unsupported protocol scheme "" that is coming from:

if err := client.Run(context.Background(), req, &resp); err != nil {
	log.Fatal(err)
}

Any help or pointers would be greatly appreciated!

Missing features with VGO usage

The latest tagged version of the package doesn't include getters for the Request struct and some other part of the source code present on GitHub. When working with VGO it leads to using an outdated project compared to the actual sources.

Could you please create a new release for that purpose ?

Are you aware of another Go GraphQL client?

Hey @matryer!

I just discovered the existence of this Go GraphQL client via reddit.

I hope you don't mind this question, but I wanted to ask if https://github.com/shurcooL/graphql (and/or https://github.com/shurcooL/githubql) is on your radar already or not? It's an open source Go implementation of a GraphQL client. If you're interested, I can share some links with additional background information on its design and history, API design decisions and tradeoffs, etc.

Let me know if you're open to talking more about this and potentially working together to improve our projects. My goal is for Go users to have as nice a Go GraphQL client available to them as possible.

Thanks!

Dependency not satisfied: github.com/pkg/errors

Hello I am new to go programming. When I import github.com/machinebox/graphql in a go file, then run go mod tidy, the following stuff appears in console

github.com/my/project/server imports
        github.com/machinebox/graphql imports
        github.com/pkg/errors: module github.com/pkg/errors@latest found (v0.9.1), but does not contain package github.com/pkg/errors

It indicates that the dependency of pkg/errors is not satisfied. Go won't let me compile this file either, as same thing happens.

I guess it requires explicitly import at graphql.go Line42.

Like this?

"github.com/pkg/[email protected]"

Post body missing

Hi,

Sample code(Using default http client)

	 req := graphql.NewRequest(`
	 	query {
	 		getAccessTokenByAppSecret(
				clientId: $clientID,
				secret: $appSecret
			)
	 	}
	 `)

	req.Var("clientID", clientID)
	req.Var("appSecret", appSecret)

	ctx := context.Background()

	var responseData map[string]interface{}

	if err := c.userGraphqlClient.Run(ctx, req, &responseData); err != nil {
		log.Fatal(err)
	}

Log info

☆  examples  »go run main.go
2018/03/18 01:52:04 >> variables: {"appSecret":"5cf63e2b82f2d6b41bdcfec8b483b740","clientID":"5a48b6ae863b3b0001893bbc"}

2018/03/18 01:52:04 >> files: 0
2018/03/18 01:52:04 >> query:
		query {
			getAccessTokenByAppSecret(
				clientId: $clientID,
				secret: $appSecret
			)
		}

2018/03/18 01:52:04 >> headers: map[Content-Type:[multipart/form-data; boundary=f262269d26f9acbc6a727ad9e0becd29acbc33c1f0110691763f4cb54862] Accept:[application/json]]
2018/03/18 01:52:05 << POST body missing. Did you forget use body-parser middleware?
2018/03/18 01:52:05 decoding response: invalid character 'P' looking for beginning of value
exit status 1

Update client to pass response along rather than pulling out errors

With graphQL it's possible the response could be partially successful. With the way the client is currently configured, it's parsing the errors property and returning an error with the first error in the array if it's not empty.

Would you be open to a PR that instead passes the entire response? This would allow the caller to decide how it wants to handle the returned errors. We're also currently losing additional error context if more than one error is present.

D

D

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.