概要
net/http
ライブラリを使ってリクエストを送信する場合、Content-Typeに複数の値を格納してリクエストしたい。
なんてことがありますよね。
例えば、Content-Typeに
- application/json
- charset=Shift_JIS
を付与する場合、リクエストヘッダーは以下のように送信したいとします。
content-type=application/json;charset=Shift_JIS`
この**;(セミコロン)**で区切った形式で送信した場合、少しハマるポイントがあったので紹介します。
結論
content-type=application/json;charset=Shift_JIS
上記のように、**;(セミコロン)**で区切った値をリクエストヘッダーに付与して送信したい場合、
net/http
ライブラリでは、以下のように記述する。
main.go
(略)
header := http.Header{}
header.Set("Content-Type", "application/json;charset=Shift_JIS")
(略)
以下のように記述した場合、想定した値にならない。
main.go
(略)
header := http.Header{}
header.Set("Content-Type", "application/json")
header.Add("Content-Type", "charset=Shift_JIS")
(略)
検証
クライアント、サーバーのアプリケーションを書いてサクッとリクエストヘッダーの中身を見てみた。
クライアント
Golangのバージョンは、go1.11.2 darwin/amd64
main.go
package main
import (
"bytes"
"fmt"
"net/http"
"github.com/labstack/echo"
)
func main() {
client := &http.Client{}
header := http.Header{}
header.Set("Content-Type", "application/json")
header.Add("Content-Type", "charset=Shift_JIS") // 今回問題の箇所
req, _ := http.NewRequest(
echo.POST,
"http://localhost:3000",
bytes.NewBufferString("hoge"),
)
req.Header = header
client.Do(req)
}
サーバー
nodeのバージョンは v9.11.2
server.js
var http = require('http');
var url = require('url');
var server = http.createServer(function (req, res) {
try {
console.log('requested.');
console.log('method: ' + req.method);
console.log('url: ' + req.url);
console.log('query: %j', url.parse(req.url, true).query);
console.log('user agent: ' + req.headers['user-agent']);
console.log('header' + JSON.stringify(req.headers));
}
catch (err) {
console.error('unhandled exception has occured.');
console.error(err);
}
finally {
res.end();
}
});
server.listen(3000, function () {
console.log('http server is running...press enter key to exit.');
process.stdin.on('data', function (data) {
if (data.indexOf('\n') !== -1) {
server.close(function () {
console.log('http server closed.');
process.exit(0);
});
}
});
});
server.on('error', function (err) {
console.error(err);
process.exit(1);
});
検証手順
サーバーのアプリケーションを起動する。
$ node server.js
クライアントアプリケーションを実行
$ go run main.go
サーバーのログ
$ node server.js
http server is running...press enter key to exit.
requested.
method: POST
url: /
query: {}
user agent: Go-http-client/1.1
header{"host":"localhost:3000","user-agent":"Go-http-client/1.1","content-length":"4","content-type":"application/json","accept-encoding":"gzip"}
headerのcontent-typeにcharset=Shift_JISがない...?
リクエストヘッダーを組み立てる処理を以下のように修正
main.go
(略)
header := http.Header{}
header.Set("Content-Type", "application/json;charset=Shift_JIS")
(略)
サーバーのログ
http server is running...press enter key to exit.
requested.
method: POST
url: /
query: {}
user agent: Go-http-client/1.1
header{"host":"localhost:3000","user-agent":"Go-http-client/1.1","content-length":"4","content-type":"application/json;charset=Shift_JIS","accept-encoding":"gzip"}
期待通り。
net/httpライブラリの Header.Add
は、 ;(セミコロン)区切りでContent-Typeを組み立てないことがわかった。
参照文献