概要
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 ライブラリでは、以下のように記述する。
(略)
header := http.Header{}
header.Set("Content-Type", "application/json;charset=Shift_JIS")
(略)
以下のように記述した場合、想定した値にならない。
(略)
header := http.Header{}
header.Set("Content-Type", "application/json")
header.Add("Content-Type", "charset=Shift_JIS")
(略)
検証
クライアント、サーバーのアプリケーションを書いてサクッとリクエストヘッダーの中身を見てみた。
クライアント
Golangのバージョンは、go1.11.2 darwin/amd64
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
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がない...?
リクエストヘッダーを組み立てる処理を以下のように修正
(略)
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を組み立てないことがわかった。
参照文献