HTTP response sent but never closed and ending with "HTTP/1.1 400 Bad Request"

728 views
Skip to first unread message

RobM

unread,
Oct 13, 2013, 2:53:54 PM10/13/13
to golan...@googlegroups.com
Hello,

I wrote a really simple server :

-----------------------------------------------------------------------------------------------------
package main
 
import (
  "fmt"
  "net/http"
)
 
func main() {
  http.HandleFunc("/", root)

  fmt.Println("listening on port: 7777")
err := http.ListenAndServe(":7777", nil)
if err != nil {
 panic(err)
}
}
 
func root(res http.ResponseWriter, req *http.Request) {
fmt.Fprintf(res, "Hello")
}
-----------------------------------------------------------------------------------------------------------------------------

When I do "curl localhost:7777/" I see "hello" printed in the response so all is ok. But when I play the same request using netcat:

------------------------------------------------------------------------------------------------------------------------------
$> nc localhost 7777
GET / HTTP/1.1                                      #writing the request manually
User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5
Host: localhost:7777
Accept: */*

HTTP/1.1 200 OK                                     #response headers
Content-Type: text/plain; charset=utf-8
Content-Length: 5
Date: Sun, 13 Oct 2013 18:42:55 GMT

Hello                                                         #here the connection stays open just after "Hello", when I type return
HTTP/1.1 400 Bad Request                        # I see this and the connection really close

------------------------------------------------------------------------------------------------------------------------------

What's happening here ? There is obviously something wrong but I can't tell what.

minux

unread,
Oct 13, 2013, 2:57:50 PM10/13/13
to RobM, golang-nuts
the problem is that you typed return here.

your root handler doesn't output a \n, so you typed a \n, however, the HTTP server is
treating that empty line you just typed as a new request line, and then it says bad request
as the request line is empty. 

RobM

unread,
Oct 13, 2013, 3:03:00 PM10/13/13
to golan...@googlegroups.com, RobM
Ok thanks got it but even if I change "Hello" to "Hello\n" the connection stays opened ... Shouldn't it be closed once the handler returns ?

minux

unread,
Oct 13, 2013, 3:12:09 PM10/13/13
to RobM, golang-nuts
On Sun, Oct 13, 2013 at 3:03 PM, RobM <robin...@gmail.com> wrote:
Ok thanks got it but even if I change "Hello" to "Hello\n" the connection stays opened ... Shouldn't it be closed once the handler returns ?
by default, the net/http tries to wait some time before closing the connection (http 1.1 keepalive),
so the the client don't need to open a new connection for each resource and can reuse the current
connection.

you can get the behavior you want by sending this:
GET / HTTP/1.0

or this:
GET / HTTP/1.1
Host: localhost
Connection: close


RobM

unread,
Oct 13, 2013, 3:24:39 PM10/13/13
to golan...@googlegroups.com, RobM
Thank you for your answer. I thought this was the reason why I couldn't get HTTP trailer working but it seems that it's not. Here is what I do at the end of my handler
----------------------------------------------------
trailers := map[string]string {
    "x-my-trailer": "here it is",
}
m := make(http.Header)
for k, v := range(trailers) {
   m.Add(k, v)
}
req.Trailer = m
----------------------------------------------------
I should see the trailer using netcat (did it before in node.js) but I don't. Any idea where is my mistake ?

Dave Cheney

unread,
Oct 13, 2013, 6:55:09 PM10/13/13
to RobM, golan...@googlegroups.com, RobM
If you want the remote server to close the connection it's response you need to ask it to do so. Two ways to do this are, using HTTP/1.0 or sending a Connection: close header with HTTP/1.1. 

On 14 Oct 2013, at 6:03, RobM <robin...@gmail.com> wrote:

Ok thanks got it but even if I change "Hello" to "Hello\n" the connection stays opened ... Shouldn't it be closed once the handler returns ?

--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/2f3fe522-80ce-4528-889e-aced81b7c443%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

RobM

unread,
Oct 14, 2013, 5:23:39 AM10/14/13
to golan...@googlegroups.com, RobM
Ok guys thanks for that I understand now. Any ideas about my HTTP trailer issue ?

Dave Cheney

unread,
Oct 14, 2013, 5:31:09 AM10/14/13
to RobM, golang-nuts
> Ok guys thanks for that I understand now. Any ideas about my HTTP trailer
> issue ?

Can you please remind me what the trailer issue is ?

Benjamin Measures

unread,
Oct 14, 2013, 6:21:41 AM10/14/13
to golan...@googlegroups.com
> I couldn't get HTTP trailer working but it seems that it's not. Here is what I do at the end of my handler

Make sure you're checking for errs:
http://golang.org/pkg/net/http/#pkg-variables
> ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"}

You cannot use trailers unless HTTP/1.1 and chunked encoding.

Apart from that suggestion, my magic ball came up with nothing (show your code).

RobM

unread,
Oct 14, 2013, 12:16:31 PM10/14/13
to golan...@googlegroups.com
Here is the code I use in a handler to send HTTP trailers when the request ends:
----------------------------------------------------
res.Header().Add("Trailer", "x-my-trailer")    #warning the client that trailer is expected

//doint stuff here

trailers := map[string]string {
    "x-my-trailer": "here it is",
}
m := make(http.Header)                             #creating a trailer (of type http.Header)
for k, v := range(trailers) {
   m.Add(k, v)
}
req.Trailer = m                                          #setting the trailer
----------------------------------------------------

As I said before, I should see trailer at the end of my request using netcat (after the 0 sized chunk). I'm using HTTP 1.1 as well as chunked encoding.
Any idea ? I read that HTTP trailers are not yet fully supported in Go

Dave Cheney

unread,
Oct 14, 2013, 2:07:42 PM10/14/13
to RobM, golan...@googlegroups.com
I'm pretty sure I remember Brad saying that trailers are not supported. Does your client signal it is willing to accept trailers with the TE header?


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

RobM

unread,
Oct 14, 2013, 3:36:14 PM10/14/13
to golan...@googlegroups.com, RobM
Well, it's supposed to be "partially complete". From http://golang.org/src/pkg/net/http/request.go :
// Trailer maps trailer keys to values.  Like for Header, if the
// response has multiple trailer lines with the same key, they will be
// concatenated, delimited by commas.
// For server requests, Trailer is only populated after Body has been
// closed or fully consumed.
// Trailer support is only partially complete.
Trailer Header
Client side request is ok, doing the same request on a nodejs server I get the trailers I expect. Trailer usage may not be possible yet ...

Benjamin Measures

unread,
Oct 14, 2013, 6:13:33 PM10/14/13
to golan...@googlegroups.com, RobM
On Monday, 14 October 2013 19:07:42 UTC+1, Dave Cheney wrote:
I'm pretty sure I remember Brad saying that trailers are not supported.

Oh yes:
> // zero EOF chunk, trailer key/value pairs (currently
> // unsupported in Go's server), followed by a blank
> // line.

(Beside not trying to modify request.Trailer) The OP will need to modify/implement their own http.server, possibly using httputil.ServerConn . Considering client support though (they can be silently dropped), it's hard to see how it's worth the effort.

Robin Monjo

unread,
Oct 15, 2013, 5:45:59 AM10/15/13
to Benjamin Measures, golan...@googlegroups.com
Ok thanks I won't use trailer then.

Kyle Lemons

unread,
Oct 16, 2013, 12:55:53 AM10/16/13
to Dave Cheney, RobM, golan...@googlegroups.com
ResponseWriter has no trailer support.  You're trying to set the trailer on the incoming request, but that has no effect on the response sent to the client.


RobM

unread,
Oct 16, 2013, 5:08:04 AM10/16/13
to golan...@googlegroups.com, Dave Cheney, RobM
Hum yes you're right, I got confused !
Reply all
Reply to author
Forward
0 new messages