web-dev-qa-db-fra.com

Aller faire une requête GET et construire le Querystring

Je suis assez nouveau pour Go et je ne comprends pas encore tout. Dans la plupart des langages modernes Node.js, Angular, jQuery, PHP, vous pouvez effectuer une requête GET avec des paramètres de chaîne de requête supplémentaires.

Faire cela dans Go n'est pas aussi simple qu'il y paraît, et je ne le comprends pas encore. Je ne veux vraiment pas avoir à concaténer une chaîne pour chacune des demandes que je veux faire.

Voici l'exemple de script:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    client := &http.Client{}

    req, _ := http.NewRequest("GET", "http://api.themoviedb.org/3/tv/popular", nil)
    req.Header.Add("Accept", "application/json")
    resp, err := client.Do(req)

    if err != nil {
        fmt.Println("Errored when sending request to the server")
        return
    }

    defer resp.Body.Close()
    resp_body, _ := ioutil.ReadAll(resp.Body)

    fmt.Println(resp.Status)
    fmt.Println(string(resp_body))
}

Dans cet exemple, vous pouvez voir qu'il existe une URL qui requiert une variable GET de api_key avec votre clé api comme valeur. Le problème est que cela devient codé en dur sous la forme de:

req, _ := http.NewRequest("GET", "http://api.themoviedb.org/3/tv/popular?api_key=mySuperAwesomeApiKey", nil)

Est-il possible de construire cette chaîne de requête de manière dynamique? Pour le moment, je devrai assembler l'URL avant cette étape afin d'obtenir une réponse valide.

51
Rudi Strydom

Comme un commentateur l'a mentionné, vous pouvez obtenir Values à partir de net/url, Qui a une méthode Encode. Vous pouvez faire quelque chose comme ceci (req.URL.Query() renvoie le url.Values Existant)

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
)

func main() {
    req, err := http.NewRequest("GET", "http://api.themoviedb.org/3/tv/popular", nil)
    if err != nil {
        log.Print(err)
        os.Exit(1)
    }

    q := req.URL.Query()
    q.Add("api_key", "key_from_environment_or_flag")
    q.Add("another_thing", "foo & bar")
    req.URL.RawQuery = q.Encode()

    fmt.Println(req.URL.String())
    // Output:
    // http://api.themoviedb.org/3/tv/popular?another_thing=foo+%26+bar&api_key=key_from_environment_or_flag
}

http://play.golang.org/p/L5XCrw9VIG

150
jcbwlkr

Utilisez r.URL.Query() lorsque vous ajoutez une requête existante, si vous construisez un nouvel ensemble de paramètres, utilisez la méthode url.Values struct comme si

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/url"
    "os"
)

func main() {
    req, err := http.NewRequest("GET","http://api.themoviedb.org/3/tv/popular", nil)
    if err != nil {
        log.Print(err)
        os.Exit(1)
    }

    // if you appending to existing query this works fine 
    q := req.URL.Query()
    q.Add("api_key", "key_from_environment_or_flag")
    q.Add("another_thing", "foo & bar")

    // or you can create new url.Values struct and encode that like so
    q := url.Values{}
    q.Add("api_key", "key_from_environment_or_flag")
    q.Add("another_thing", "foo & bar")

    req.URL.RawQuery = q.Encode()

    fmt.Println(req.URL.String())
    // Output:
    // http://api.themoviedb.org/3/tv/popularanother_thing=foo+%26+bar&api_key=key_from_environment_or_flag
}
20
allyraza

Utiliser NewRequest simplement pour créer une URL est une overkill. Utilisez le net/url paquet:

package main

import (
    "fmt"
    "net/url"
)

func main() {
    base, err := url.Parse("http://www.example.com")
    if err != nil {
        return
    }

    // Path params
    base.Path += "this will get automatically encoded"

    // Query params
    params := url.Values{}
    params.Add("q", "this will get encoded as well")
    base.RawQuery = params.Encode() 

    fmt.Printf("Encoded URL is %q\n", base.String())
}

Aire de jeu: https://play.golang.org/p/YCTvdluws-r

0
Janek Olszak