cli / go-gh

A Go module for interacting with gh and the GitHub API from the command line.
https://pkg.go.dev/github.com/cli/go-gh/v2
MIT License
322 stars 45 forks source link

RESTClient not accepting query string #20

Closed gennaro-tedesco closed 2 years ago

gennaro-tedesco commented 2 years ago

I have a use case where I need to search for repositories containing certain query criteria (say name or language): essentially reproducing the standard repository search. Using the gh CLI this can be achieved via:

gh api -X GET /search/repositories -f q='<name> in:name language: <lang>'

I am trying to reproduce the above with the RESTClient call, passing the query search somehow as header string; however, according to the docs this grammar is not accepted (namely there is no way to pass a query string to the RESTClient object). Practically speaking I am looking to do something along the lines of

opts := api.ClientOptions{
    ...
    Headers:  <insert grammar for query string>  <---- this bit must be filled correctly
    Log:       os.Stdout,
}
...
...
client, err := RESTClient(&opts) <--- the query string is passed to the client
...
err = client.Get("search/repositories", &response) <--- notice the endpoint /search/repositories

Question

What is the correct way to achieve the above?

mislav commented 2 years ago

You can add query parameters to the "search/repositories" string by constructing a url.Values object and serializing it to string using its Encode() method.

The argument to client.Get(path) is the path component of the URL with optional query parameters separated with ?.

gennaro-tedesco commented 2 years ago

Thank you for your quick reply. However, when you say:

The argument to client.Get(path) is the path component of the URL with optional query parameters separated with ?.

would this mean that at the end of the day one must pass a whole string of the form

search/repositories?name=<name>?language=lang

to client.Get()? Because this looks different from what the query string for gh API /search/repositories -f q='...' is (so it is a little hard to understand what the right grammar is).

mislav commented 2 years ago

When you do

gh api -X GET search/repositories -f q1=foo -f q2=bar

that's equivalent to

gh api search/repositories?q1=foo&q2=bar

with the added bonus that you don't have to worry about encoding all the special characters in the query string properly, since that's handled by gh api.

Similarly, you could do:

client.Get("path?q1=foo&q2=bar")

and that will work, but I wouldn't recommend it because, again, you'd have to worry about properly encoding query values. Instead, you should do:

searchTerm := "<name>"
repoLanguage := "go"
myQuery := url.Values{}
myQuery.Add("q", fmt.Sprintf("%s in:name language:%s", searchTerm, repoLanguage))
myQuery.Add("per_page", "30")
client.Get("path?"+myQuery.Encode())
gennaro-tedesco commented 2 years ago

Thank you very much for your exhaustive reply, it works fine!