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?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
FrankJ
  • 11
  • 4
  • Get requests don't normally submit data. Post and Put requests do. http://stackoverflow.com/questions/8498371/curl-get-and-x-get – reticentroot Apr 06 '17 at 01: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. – Christian Apr 06 '17 at 07: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`. – Adrian Apr 06 '17 at 14:58

2 Answers2

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))

}
reticentroot
  • 3,612
  • 2
  • 22
  • 39
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.

Christian
  • 3,551
  • 1
  • 28
  • 24
  • Christian, this method worked perfectly thanks for your help ill take a look at http://olivere.github.io/elastic/ you suggested – FrankJ Apr 07 '17 at 12:27