Goがv1.5(.1?) になりWebサーバーで
undecodedなURLのpathを取得する定番の方法が決まったのでメモしておく。
URL.EscapedPath()を使うのが解決策。
また確認した所ではURL.RequestURI()
の挙動にも変更が加えられており、これでも解決できる。
背景
少し前はWebサーバーを書く時Undecodedなリクエストパスを取得したくなると少し困っていた。
以下の様にリクエストパスを得るがv1.4.3 以前では後述する問題があった。
1
2
3
4
5
6
7
8
9
10
|
func sampleHandler(w http.ResponseWriter, r * http.Request) {
fmt.Fprintf(w, "r.RequestURI:%s\n", r.RequestURI)
fmt.Fprintf(w, "r.URL.RequestURI():%s\n", r.URL.RequestURI())
// fmt.Fprintf(w, "r.URL.RawPath:%s\n", r.URL.RawPath)
// fmt.Fprintf(w, "r.URL.EscapedPath():%s\n", r.URL.EscapedPath())
}
func main() {
http.HandleFunc("/", sampleHandler)
http.ListenAndServe(":18080", nil)
}
|
v1.4.3の時の挙動
r.RequestURI
はリクエスト内容が直接出力されるが、
absolute-formが
request-targetに使われていると
スキーマなどが含まれて扱いにくい。
URL.RequestURI()
はGoがエンコードした内容が含まれる。
そのため%24
で転送された部分が$
として残る事になる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
$ export GOROOT=${HOME}/go1.4/
$ ~/go1.4/bin/go run ./main.go &
$ telnet localhost 18080
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET /test_%24host%20$ HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
Date: Thu, 29 Oct 2015 13:46:11 GMT
Content-Length: 66
Content-Type: text/plain; charset=utf-8
r.RequestURI:/test_%24host%20$
r.URL.RequestURI():/test_$host%20$
GET http://localhost/test_%24host%20$ HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
Date: Thu, 29 Oct 2015 13:46:40 GMT
Content-Length: 82
Content-Type: text/plain; charset=utf-8
r.RequestURI:http://localhost/test_%24host%20$
r.URL.RequestURI():/test_$host%20$
^C
Connection closed by foreign host.
|
v1.5.1の時の挙動
r.RequestURI
の挙動は変わらない。変わったのはURL.RequestURI()
だ。
URL.RequestURI()
はリクエストされたrequest-target
が妥当な内容の場合、該当リクエストのパス部分を返す。
これはリクエストから取られGoが再エンコードする訳ではない。
さらにabsolute-formであってもパス部分が取得できる。
ただし、この変更が正しいのかわからない。
困っていた内容を解決する意図のURL.EscapedPath()
が追加されていた。 これを使うのが良さそう。
とにかく、これで解決した。やったぜ。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
$ telnet localhost 18080
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET /test_%24host%20$ HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
Date: Thu, 29 Oct 2015 14:18:40 GMT
Content-Length: 68
Content-Type: text/plain; charset=utf-8
r.RequestURI:/test_%24host%20$
r.URL.RequestURI():/test_%24host%20$
GET http://localhost/test_%24host%20$ HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
Date: Thu, 29 Oct 2015 14:19:03 GMT
Content-Length: 84
Content-Type: text/plain; charset=utf-8
r.RequestURI:http://localhost/test_%24host%20$
r.URL.RequestURI():/test_%24host%20$
^C
Connection closed by foreign host.
|