8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Go言語: net/httpで建てたサーバにnetcatでリクエストすると400 Bad Requestが付いてくる件

Posted at

Goの標準ライブラリ、net/httpで作ったHTTPサーバに対して、netcatやtelnetでリクエストを送ると、なぜがレスポンスボディの後に「HTTP/1.1 400 Bad Request」が付いてくることに気が付きました。

$ nc localhost 8080
GET / HTTP/1.1
Host: localhost:8080
[ここまで入力したらENTERキーを押す]

HTTP/1.1 200 OK
Date: Sat, 09 May 2015 07:56:54 GMT
Content-Length: 13
Content-Type: text/plain; charset=utf-8

Hello, World
[ここでENTERキーを押す]
HTTP/1.1 400 Bad Request

一番最後の行に注目してください。なぜか最後に「Bad Request」がついてきます。ちなみに、レスポンスヘッダの「Content-Length」は13なので、最後の行はレスポンスボディではないことが分かります。

この現象を再現するには、次のコードでサーバを立てると再現できます。

main.go
package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello, World\n")
	})
	http.ListenAndServe(":8080", nil)
}

このサーバは、go runコマンドで起動することができます。

$ go run main.go

この現象について調べていたら、GoのGoogleグループに「HTTP response sent but never closed and ending with "HTTP/1.1 400 Bad Request"」というスレッドを見つけました。このスレッドによれば、net/httpはHTTP 1.1であれば、リクエストヘッダーにConnection: closeが無い限り、Keep Aliveで通信を行うように作られているとのことです。これは、HTTP 1.1の仕様に従っているので、不具合ではありません。

従って、今回のケースでは、2回目のENTER押下をしていますが、それが空っぽのリクエストとしてサーバが認識した結果、Bad Requestのレスポンスが帰ってきたと理解できます。ですので、2回目のENTERの代わりに、リクエストをもう一度書くと、レスポンスを得ることができます。

$ nc localhost 8080
GET / HTTP/1.1
Host: localhost:8080
[ここまで書いてENTER押下]

HTTP/1.1 200 OK
Date: Sat, 09 May 2015 08:06:28 GMT
Content-Length: 13
Content-Type: text/plain; charset=utf-8

Hello, World
GET / HTTP/1.1
Host: localhost:8080
[更にここまで書いてENTER押下]

HTTP/1.1 200 OK
Date: Sat, 09 May 2015 08:06:31 GMT
Content-Length: 13
Content-Type: text/plain; charset=utf-8

Hello, World
[ENTER押下]
HTTP/1.1 400 Bad Request

最後の「HTTP/1.1 400 Bad Request」を受け取らないようにするには、ヘッダにConnection: closeを書きます。

$ nc localhost 8080
GET / HTTP/1.1
Host: localhost:8080
Connection: close
[ここまで書いてENTER押下]

HTTP/1.1 200 OK
Date: Sat, 09 May 2015 08:08:40 GMT
Content-Length: 13
Content-Type: text/plain; charset=utf-8
Connection: close

Hello, World

もちろん、HTTP 1.0でリクエストをすれば、Keep Aliveがデフォルトで無効の状態となり、最後の「HTTP/1.1 400 Bad Request」も受け取らなくなります。

$ nc localhost 8080
GET / HTTP/1.0
[ここまで書いてENTER押下]

HTTP/1.0 200 OK
Date: Sat, 09 May 2015 08:09:14 GMT
Content-Length: 13
Content-Type: text/plain; charset=utf-8

Hello, World
8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?