net/http: On redirect original request headers are not kept

2,080 views
Skip to first unread message

stephane....@gmail.com

unread,
Mar 31, 2012, 8:44:13 AM3/31/12
to golan...@googlegroups.com
Hi again,
  I'm quite stressing the net/http package ;)

  I have discovered that if I set a custom HTTP header to a request, and hit a 301/302/etc. redirect, those headers are not kept. Example code:

package main
import (
"log"
"net/http"
)
func main() {
client := &http.Client{}

req, err := http.NewRequest("GET", "http://combo.cc/redirect", nil)
if err != nil {
log.Fatalln(err)
}

req.Header.Set("User-Agent", "MSIE 5.15 (MacintoshOS 9)")
log.Println("User-Agent before redirect:", req.UserAgent())

resp, err := client.Do(req)
if err != nil {
log.Fatalln(err)
}
defer resp.Body.Close()

log.Println("User-Agent after redirect:", resp.Request.UserAgent())
}

  Output:

2012/03/31 14:43:02 User-Agent before redirect: MSIE 5.15 (MacintoshOS 9)
2012/03/31 14:43:02 User-Agent after redirect: 

  This is what I'm getting on my nginx access.log:
    
93.56.194.199 - - [31/Mar/2012:14:36:59 +0200] "GET /redirect HTTP/1.1" 301 185 "-" "MSIE 5.15 (MacintoshOS 9)"
93.56.194.199 - - [31/Mar/2012:14:36:59 +0200] "GET / HTTP/1.1" 200 798 "http://combo.cc/redirect" "Go http package"

  As you can see the first request had my custom header, the second one did not.

  In http://golang.org/src/pkg/net/http/client.go, line 204, upon redirect a new set of headers is being constructed, and only "Referer" is set, instread of copying the headers from the original request.

  If this looks like a bug to you, I'll open a report.

Stephane

Brad Fitzpatrick

unread,
Mar 31, 2012, 3:44:57 PM3/31/12
to stephane....@gmail.com, golan...@googlegroups.com
You can mutate the subsequent redirect requests with your Client's CheckRedirect function.

Jamie Hall

unread,
Sep 16, 2013, 4:39:16 PM9/16/13
to golan...@googlegroups.com, stephane....@gmail.com
For reference, this is occurring in net/http/client.go, lines 255 - 279, when a new request is created and just its URL and Method copied.
To maintain the original header values (which is really quite useful, and I can't think of any drawbacks), simply store a reference to the original headers
after line 255 and change line 261 to:

req.Header = oldheader

Dave Cheney

unread,
Sep 16, 2013, 9:39:33 PM9/16/13
to Jamie Hall, golang-nuts, stephane....@gmail.com
Jamie, is there an issue logged for this ? The thread of discussion is
over a year old now.
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.

Jamie Hall

unread,
Sep 17, 2013, 4:45:10 AM9/17/13
to golan...@googlegroups.com, stephane....@gmail.com
Sorry, I didn't spot the date until after I'd posted. Yes, the following issue relates to this for future reference:



On Saturday, 31 March 2012 13:44:13 UTC+1, stephane....@gmail.com wrote:

xingyu...@gmail.com

unread,
Nov 9, 2013, 4:43:01 AM11/9/13
to golan...@googlegroups.com, stephane....@gmail.com
find 
old row : req.Header = make(Header)

new row : req.Header = ireq.Header

在 2012年3月31日星期六UTC+8下午8时44分13秒,stephane....@gmail.com写道:
Reply all
Reply to author
Forward
0 new messages