{"action":"closed","issue":{"url":"https://api.github.com/repos/valyala/fasthttp/issues/409","repository_url":"https://api.github.com/repos/valyala/fasthttp","labels_url":"https://api.github.com/repos/valyala/fasthttp/issues/409/labels{/name}","comments_url":"https://api.github.com/repos/valyala/fasthttp/issues/409/comments","events_url":"https://api.github.com/repos/valyala/fasthttp/issues/409/events","html_url":"https://github.com/valyala/fasthttp/issues/409","id":358300391,"node_id":"MDU6SXNzdWUzNTgzMDAzOTE=","number":409,"title":"fasthttp is not recognizing the request as chunked if 'Transfer-Encoding' header is in lowercase and header normalization is disabled","user":{"login":"codesenberg","id":6357982,"node_id":"MDQ6VXNlcjYzNTc5ODI=","avatar_url":"https://avatars3.githubusercontent.com/u/6357982?v=4","gravatar_id":"","url":"https://api.github.com/users/codesenberg","html_url":"https://github.com/codesenberg","followers_url":"https://api.github.com/users/codesenberg/followers","following_url":"https://api.github.com/users/codesenberg/following{/other_user}","gists_url":"https://api.github.com/users/codesenberg/gists{/gist_id}","starred_url":"https://api.github.com/users/codesenberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codesenberg/subscriptions","organizations_url":"https://api.github.com/users/codesenberg/orgs","repos_url":"https://api.github.com/users/codesenberg/repos","events_url":"https://api.github.com/users/codesenberg/events{/privacy}","received_events_url":"https://api.github.com/users/codesenberg/received_events","type":"User","site_admin":false},"labels":[{"id":274727799,"node_id":"MDU6TGFiZWwyNzQ3Mjc3OTk=","url":"https://api.github.com/repos/valyala/fasthttp/labels/bug","name":"bug","color":"fc2929","default":true},{"id":1039651697,"node_id":"MDU6TGFiZWwxMDM5NjUxNjk3","url":"https://api.github.com/repos/valyala/fasthttp/labels/pending/development","name":"pending/development","color":"10556b","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-09-08T14:36:50Z","updated_at":"2018-09-11T23:59:04Z","closed_at":"2018-09-11T23:59:04Z","author_association":"NONE","body":"When header normalization is disabled `fasthttp` cannot recognize the fact that request's transfer encoding is `chunked` and treats it as a usual request. This leads to i/o timeout, since `fasthttp` thinks that there is more to come and request is finished.\r\n\r\nHere is a client for repro.\r\n`client.go`:\r\n```go\r\npackage main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"log\"\r\n\t\"os\"\r\n\t\"time\"\r\n\r\n\t\"github.com/valyala/fasthttp\"\r\n)\r\n\r\nfunc main() {\r\n\turl := os.Args[1]\r\n\r\n\tclient := fasthttp.Client{\r\n\t\tReadTimeout:                   2 * time.Second,\r\n\t\tDisableHeaderNamesNormalizing: true,\r\n\t}\r\n\treq := fasthttp.AcquireRequest()\r\n\tresp := fasthttp.AcquireResponse()\r\n\r\n\tdefer fasthttp.ReleaseRequest(req)\r\n\tdefer fasthttp.ReleaseResponse(resp)\r\n\r\n\treq.SetRequestURI(url)\r\n\r\n\terr := client.Do(req, resp)\r\n\tif err != nil {\r\n\t\tlog.Fatal(err)\r\n\t} else {\r\n\t\tfmt.Print(resp.Header.String())\r\n\t\tfmt.Print(string(resp.Body()))\r\n\t}\r\n}\r\n```\r\nAnd here is a simplest possible server.\r\n`bugger_server.go`:\r\n```go\r\npackage main\r\n\r\nimport (\r\n\t\"flag\"\r\n\t\"log\"\r\n\t\"net\"\r\n)\r\n\r\nfunc main() {\r\n\tbug := flag.Bool(\r\n\t\t\"bug\",\r\n\t\tfalse,\r\n\t\t\"controls whether to cause bug with fasthttp client\",\r\n\t)\r\n\taddress := flag.String(\r\n\t\t\"addr\",\r\n\t\t\"localhost:8080\",\r\n\t\t\"specifies which address to use for the server\",\r\n\t)\r\n\tflag.Parse()\r\n\r\n\tl, err := net.Listen(\"tcp\", *address)\r\n\tif err != nil {\r\n\t\tlog.Fatal(err)\r\n\t}\r\n\r\n\tlog.Print(\"server started at \" + *address)\r\n\tfor {\r\n\t\tc, err := l.Accept()\r\n\t\tif err != nil {\r\n\t\t\tlog.Print(err)\r\n\t\t\tcontinue\r\n\t\t}\r\n\r\n\t\tif *bug {\r\n\t\t\tc.Write([]byte(\"HTTP/1.1 200 OK\\r\\n\" +\r\n\t\t\t\t\"content-type: text/plain\\r\\n\" +\r\n\t\t\t\t\"transfer-encoding: chunked\\r\\n\\r\\n\"))\r\n\t\t} else {\r\n\t\t\tc.Write([]byte(\"HTTP/1.1 200 OK\\r\\n\" +\r\n\t\t\t\t\"Content-Type: text/plain\\r\\n\" +\r\n\t\t\t\t\"Transfer-Encoding: chunked\\r\\n\\r\\n\"))\r\n\t\t}\r\n\r\n\t\tchunks := [][]byte{\r\n\t\t\t[]byte(\"24\\r\\nThis is the data in the first chunk \\r\\n\"),\r\n\t\t\t[]byte(\"1B\\r\\nand this is the second one \\r\\n\"),\r\n\t\t\t[]byte(\"3\\r\\ncon\\r\\n\"),\r\n\t\t\t[]byte(\"8\\r\\nsequence\\r\\n\"),\r\n\t\t\t[]byte(\"0\\r\\n\\r\\n\"),\r\n\t\t}\r\n\r\n\t\tfor _, ch := range chunks {\r\n\t\t\tc.Write(ch)\r\n\t\t}\r\n\t}\r\n}\r\n```\r\nYou run them as:\r\n```bash\r\ngo run bugged_server.go --bug\r\n```\r\nand\r\n```bash\r\ngo run client.go http://localhost:8080\r\n```\r\nFor another example of a real world server with same behaviour see [here](https://github.com/codesenberg/bombardier/issues/38#issue-349412953).\r\nNow, I'm not quite sure where RFCs stand on this, but I think I read somewhere that the clients ought to treat headers in a case-insensitive manner, also, other clients like `curl` or the one from Go's `net/http` have no problem with this kind of servers."}}
{"actor":{"display_login":"erikdubbelboer"}}