1

I'm relatively new to Go and I'm currently trying to search records in elastic search, below is the basic code I have created, so far I'm able to perform a simple GET request "http://10.132.0.13:9200/" and results are returned as expected. However, once I try to run a slightly more complex GET request it fails.

Below is the code I have created so far.

package main import ( "fmt" "io/ioutil" "net/http" ) func main() { //request, err := http.Get(`http://10.132.0.13:9200/`) // this just returns the test page request, err := http.Get(`http://10.132.0.13:9200/database-*/_search?pretty -d { "query": { "match": {"_all": "searchterm"}}}`) if err != nil { //error } defer request.Body.Close() body, err := ioutil.ReadAll(request.Body) fmt.Println(string(body)) } 

I can query the index directly with the use of curl -xget and it returns the expected results

Is there a way to implement a similar curl -xget in golang?

3
  • Get requests don't normally submit data. Post and Put requests do. stackoverflow.com/questions/8498371/curl-get-and-x-get Commented Apr 6, 2017 at 1:55
  • Even though sending a body with a GET request is not common it's completely valid and there is not really a reason to not do it. If you only read data and do not change/add data GET is the right choice whereas POST would be wrong. Elastic is using GET for it's queries and for the more complex queries it uses data from the body of the GET requests. Commented Apr 6, 2017 at 7:19
  • If you look at your call to http.Get, it has one parameter, the URL. In your non-working example, you're not passing a valid URL; you're passing what you would pass to curl, which isn't the same thing. URLs do not have flags like -d. Commented Apr 6, 2017 at 14:58

2 Answers 2

1

You can try something like this. Your submitting JSON data (or form data), which means that you should probably be using a POST or a PUT. XGET overrides the default behavior of a GET request. Using curl switch over to a POST and see if your query still works.

package main import ( "bytes" "fmt" "io/ioutil" "net/http" ) func main() { query := []byte(`{"query": { "match": {"_all": "searchterm"}}}`) req, err := http.NewRequest("POST", "http://10.132.0.13:9200/database-*/_search?pretty", bytes.NewBuffer(query)) if err != nil { panic(err) } client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(string(body)) } 
Sign up to request clarification or add additional context in comments.

2 Comments

reticentroot, Thanks for your help this solution also worked without any issues.
@FrankJ no problem, happy to help.
1

To pass body data to a get request you have to construct your request object a bit differently:

requestBody := `{ "query": { "match": {"_all": "searchterm"}}}` // convert string to reader requestReader := bytes.NewReader([]byte(requestBody)) // construct the request object request, err := http.NewRequest("GET", `http://10.132.0.13:9200/database-*/_search?pretty`, requestReader) // send the request using default client response, err := http.DefaultClient.Do(request) if err != nil { panic(err) } defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) fmt.Println(string(body)) 

If you have to use more complex elastic queries it might make sense to use a go client like for example: http://olivere.github.io/elastic/

But depending on your usecase, using http.Request is better.

1 Comment

Christian, this method worked perfectly thanks for your help ill take a look at olivere.github.io/elastic you suggested

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.