r.URL.Host is empty for web site behind Nginx proxy

719 views
Skip to first unread message

Philippe Ivaldi

unread,
Jul 23, 2014, 6:39:07 AM7/23/14
to golan...@googlegroups.com
Hi,

For a web site behind Nginx we use fastcgi_pass to pass the requests to a Go fgci.serve(…).
All is right but we often have error messages writing to a closed network connection :
"template: searchResults.html:1:1632: executing \"body\" at <</div><div id=\"csite...>: use of closed network connection"

In order to use a http.CloseNotifier, we need to use a http.serve instead of fcgi.serve and so we use Nginx proxy_pass instead of fastcgi_pass.
Our problem now is that "r.URL.Host", where "r" is an "http.Request" pointer, is always empty and so all the web page are 404 because the "gorilla mux" router does not match any routes.
We also have the error message "http: multiple response.WriteHeader calls" which does not appear with fcgi.

Here a simplified version of our Nginx configuration for development environment :
upstream http_upstream_dev {
    server
127.0.0.1:9001;
    keepalive
50;
}


server
{
        listen
8081;
        server_name
.*dev.csite;
        client_max_body_size
5M;
        add_header
Access-Control-Allow-Origin "http://csite.cdn.local:8081";
        charset utf
-8;
        access_log
/var/log/nginx/csite_access.log;
        error_log
/var/log/nginx/csite_error.log warn;


        location
/ {
          proxy_redirect off
;
          proxy_buffering off
;
          proxy_pass_request_headers on
;


          proxy_set_header X
-Real-IP $remote_addr;
          proxy_set_header X
-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X
-Scheme $scheme;
          proxy_set_header
Referer $http_referer;
          proxy_set_header
Host $host;
          proxy_set_header X
-Forwarded-Host $host;
          proxy_set_header X
-Forwarded-Server $host;
          proxy_set_header X
-Raw-Url $scheme://$http_host$request_uri;
          proxy_set_header X
-Real-IP $remote_addr;
          proxy_set_header X
-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X
-Nginx-Proxy true;
          proxy_pass http
://http_upstream_dev;
       
}
}

The go server is loaded as this, in a goagain environment :
l, err = net.Listen("tcp", ":"+strconv.Itoa(theApp.Config.Const.PORT))
[…]
http
.Serve(l, theApp)

where theApp is an instance of a App struct :
type App struct {
[…]
 
Router                *mux.Router
[…]
}



func
(app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 defer func
() {
 
if reco := recover(); reco != nil {
 app
.NewHttpError(w, r, "¡¡ PANIC RECOVERY !!\n", reco)
 
}
 
}()

 fmt
.Printf("Host=`%s`\n", r.URL.Host)

 app
.Router.ServeHTTP(w, r)
}


and "app.Router" is a "gorilla/mux.Router" pointer.

After reading tons of post about Go web app behind Nginx using proxy_pass, we can not solve the problem of empty host without adding the ugly code r.URL, err = r.URL.Parse(r.Header.Get("X-Raw-Url")) before "app.Router.ServeHTTP(w, r)" and we have no solution for the "multiple response.WriteHeader calls" error.

Can someone help us, please ?

Matt Silverlock

unread,
Jul 23, 2014, 6:54:38 AM7/23/14
to golan...@googlegroups.com
proxy_set_header Host $http_host;
Message has been deleted

Philippe Ivaldi

unread,
Jul 23, 2014, 7:45:24 AM7/23/14
to golan...@googlegroups.com
proxy_set_header Host $http_host;

We already have  "proxy_set_header Host $host;"
Using "$http_host" does not change anything.

The field "Host" does not appear in r.Header and so r.Header.Get("Host") is empty.

[root@t520]$ apt-cache show nginx
Package: nginx
Version: 1.2.1-2.2+wheezy2

Thank you anyway

Michael Banzon

unread,
Jul 23, 2014, 4:55:45 PM7/23/14
to Philippe Ivaldi, golang-nuts
Have you tried setting an X-header to the host in nginx and see if that comes through?


--
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/d/optout.



--
Michael Banzon
http://michaelbanzon.com/

Philippe Ivaldi

unread,
Jul 23, 2014, 6:31:05 PM7/23/14
to golan...@googlegroups.com, pipri...@gmail.com, mic...@banzon.dk
In my initial message I said :
we can not solve the problem of empty host without adding the ugly code r.URL, err = r.URL.Parse(r.Header.Get("X-Raw-Url"))

So, yes "X-*" comes through but not the "Host" field and we must parse again the URL which does not seems a regular method.

Michael Banzon

unread,
Jul 23, 2014, 8:26:19 PM7/23/14
to Philippe Ivaldi, golang-nuts
Sorry for not reading through everything in the first pass.

I put together a small experiment and r.URL.Host was empty. However r.Host holds the correct value.

Philippe Ivaldi

unread,
Jul 25, 2014, 4:52:56 AM7/25/14
to golan...@googlegroups.com, pipri...@gmail.com
Thank you for this information.
In my case "r.Host" remains empty. I must set in the Nginx location part the line "proxy_set_header X-Forwarded-Host $host;"

It seems there is no other solution than parsing again the url with "r.URL, err = r.URL.Parse(r.Header.Get("X-Raw-Url"))"
Also, we corrected the "multiple response.WriteHeader calls" problem…
Reply all
Reply to author
Forward
0 new messages