回答編集履歴
2
動作例追記
answer
CHANGED
|
@@ -10,4 +10,111 @@
|
|
|
10
10
|
HTTP1.1以降はConnectionヘッダを省略したリクエストはコネクションをキープしようとするという挙動です。
|
|
11
11
|
[HTTP1.1の接続仕様(MDN)](https://developer.mozilla.org/ja/docs/Web/HTTP/Connection_management_in_HTTP_1.x)
|
|
12
12
|
|
|
13
|
-
curlの「-H `Connection: close'」などを付け足して見てみるのも良いかもしれません。
|
|
13
|
+
curlの「-H `Connection: close'」などを付け足して見てみるのも良いかもしれません。
|
|
14
|
+
|
|
15
|
+
## 追記
|
|
16
|
+
|
|
17
|
+
動くようなコードに修正してみました。
|
|
18
|
+
net/textprotoのReaderの場合、必要以上に読むことはないのでこういう用途に適しています。
|
|
19
|
+
|
|
20
|
+
```go
|
|
21
|
+
package main
|
|
22
|
+
|
|
23
|
+
import (
|
|
24
|
+
"bufio"
|
|
25
|
+
"fmt"
|
|
26
|
+
"io"
|
|
27
|
+
"log"
|
|
28
|
+
"net"
|
|
29
|
+
"net/textproto"
|
|
30
|
+
"strconv"
|
|
31
|
+
"strings"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
func handleConn(conn net.Conn) {
|
|
35
|
+
defer conn.Close()
|
|
36
|
+
reader := bufio.NewReader(conn)
|
|
37
|
+
scanner := textproto.NewReader(reader)
|
|
38
|
+
i := 0
|
|
39
|
+
headers := map[string]string{}
|
|
40
|
+
var url, method string
|
|
41
|
+
for {
|
|
42
|
+
ln, err := scanner.ReadLine()
|
|
43
|
+
if err != nil {
|
|
44
|
+
log.Println(err)
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if i == 0 {
|
|
49
|
+
fs := strings.Fields(ln)
|
|
50
|
+
method = fs[0]
|
|
51
|
+
url = fs[1]
|
|
52
|
+
fmt.Println("METHOD", method)
|
|
53
|
+
fmt.Println("URL", url)
|
|
54
|
+
} else {
|
|
55
|
+
// in headers now
|
|
56
|
+
// when line is empty, header is done
|
|
57
|
+
if ln == "" {
|
|
58
|
+
break
|
|
59
|
+
}
|
|
60
|
+
fs := strings.SplitN(ln, ": ", 2)
|
|
61
|
+
headers[fs[0]] = fs[1]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
i++
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// parse body
|
|
68
|
+
|
|
69
|
+
// ここがポイントと思われる
|
|
70
|
+
if method == "POST" || method == "PUT" {
|
|
71
|
+
amt, _ := strconv.Atoi(headers["Content-Length"])
|
|
72
|
+
buf := make([]byte, amt)
|
|
73
|
+
// 単に ReadFull ではデータを読み込むことができない
|
|
74
|
+
_, err := io.ReadFull(reader, buf)
|
|
75
|
+
if err != nil {
|
|
76
|
+
fmt.Println("error:", err)
|
|
77
|
+
}
|
|
78
|
+
// in buf we will have the POST content
|
|
79
|
+
fmt.Println("BODY:", string(buf))
|
|
80
|
+
}
|
|
81
|
+
// ここまで
|
|
82
|
+
// response
|
|
83
|
+
body := `
|
|
84
|
+
<!DOCTYPE html>
|
|
85
|
+
<html lang="en">
|
|
86
|
+
<head>
|
|
87
|
+
<meta charset="UTF-8">
|
|
88
|
+
<title></title>
|
|
89
|
+
</head>
|
|
90
|
+
<body>
|
|
91
|
+
<form method="POST">
|
|
92
|
+
<input type="text" name="key" value="">
|
|
93
|
+
<input type="submit">
|
|
94
|
+
</form>
|
|
95
|
+
</body>
|
|
96
|
+
</html>
|
|
97
|
+
`
|
|
98
|
+
|
|
99
|
+
io.WriteString(conn, "HTTP/1.1 200 OK\r\n")
|
|
100
|
+
fmt.Fprintf(conn, "Content-Length: %d\r\n", len(body))
|
|
101
|
+
io.WriteString(conn, "\r\n")
|
|
102
|
+
io.WriteString(conn, body)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
func main() {
|
|
106
|
+
server, err := net.Listen("tcp", ":9000")
|
|
107
|
+
if err != nil {
|
|
108
|
+
log.Fatalln(err.Error())
|
|
109
|
+
}
|
|
110
|
+
defer server.Close()
|
|
111
|
+
|
|
112
|
+
for {
|
|
113
|
+
conn, err := server.Accept()
|
|
114
|
+
if err != nil {
|
|
115
|
+
log.Fatalln(err.Error())
|
|
116
|
+
}
|
|
117
|
+
go handleConn(conn)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
1
追記
answer
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
なぜ標準ライブラリを使わずに書いているのかは学習目的と仮定します。
|
|
2
|
+
|
|
1
3
|
まずは、「io.ReadFull」の戻り値のerror値の内容を確認するように修正してください。もしnilではないのであればその内容を追記してください。
|
|
2
4
|
「io.ReadFull」の次の行が実行されない可能性もあります。
|
|
3
5
|
|
|
4
6
|
io.ReadFullの次に処理が進むのかを確認し、
|
|
5
|
-
戻り値のerrorをログに出すなりしてその内容を教えて下さい。
|
|
7
|
+
戻り値のerrorをログに出すなりしてその内容を教えて下さい。
|
|
8
|
+
|
|
9
|
+
「io.ReadFull」の次の行が実行されない可能性の原因として考えられるのは
|
|
10
|
+
HTTP1.1以降はConnectionヘッダを省略したリクエストはコネクションをキープしようとするという挙動です。
|
|
11
|
+
[HTTP1.1の接続仕様(MDN)](https://developer.mozilla.org/ja/docs/Web/HTTP/Connection_management_in_HTTP_1.x)
|
|
12
|
+
|
|
13
|
+
curlの「-H `Connection: close'」などを付け足して見てみるのも良いかもしれません。
|