30

I am trying to add a query parameter to a HTTP GET request but somehow methods pointed out on SO (e.g. here) don't work.

I have the following piece of code:

package main

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

func main() {
    req, err := http.NewRequest("GET", "/callback", nil)
    req.URL.Query().Add("code", "0xdead 0xbeef")
    req.URL.Query().Set("code", "0xdead 0xbeef")
    // this doesn't help
    //req.URL.RawQuery = req.URL.Query().Encode()

    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("URL      %+v\n", req.URL)
    fmt.Printf("RawQuery %+v\n", req.URL.RawQuery)
    fmt.Printf("Query    %+v\n", req.URL.Query())
}

which prints:

URL      /callback
RawQuery 
Query    map[]

Any suggestions on how to achieve this?

Playground example: https://play.golang.org/p/SYN4yNbCmo

2
  • Something wrong with http.NewRequest("GET", "/callback?code=0xdead 0xbeef", nil)? Commented Dec 7, 2017 at 21:00
  • 4
    @Adrian I didn't want to build the query myself - I have a bunch of variables that I need to attach there Commented Dec 7, 2017 at 21:05

2 Answers 2

63

Check the docs for req.URL.Query():

Query parses RawQuery and returns the corresponding values.

Since it "parses RawQuery and returns" the values what you get is just a copy of the URL query values, not a "live reference", so modifying that copy does nothing to the original query. In order to modify the original query you must assign to the original RawQuery.

q := req.URL.Query() // Get a copy of the query values.
q.Add("code", "0xdead 0xbeef") // Add a new value to the set.
req.URL.RawQuery = q.Encode() // Encode and assign back to the original query.

// URL      /callback?code=0xdead+0xbeef
// RawQuery code=0xdead+0xbeef
// Query    map[code:[0xdead 0xbeef]]

Note that your original attempt to do so didn't work because it simply parses the query values, encodes them, and assigns them right back to the URL:

req.URL.RawQuery = req.URL.Query().Encode()
// This is basically a noop!
Sign up to request clarification or add additional context in comments.

3 Comments

Well then I should hit myself in the head with "RTFM" sign. Thanks!
This is a very annoying API :(
Thanks for the docs quote because I couldn't figure out why the RawQuery overwrite was necessary just by reading StackOverflow answers.
4

You can directly build the query params using url.Values

func main() {
    req, err := http.NewRequest("GET", "/callback", nil)
    req.URL.RawQuery = url.Values{
        "code": {"0xdead 0xbeef"},
    }.Encode()

    ...
}

Notice the extra braces because each key can have multiple values.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.