LoginSignup
1
1

More than 5 years have passed since last update.

【Golang】net/httpを使ってリクエストヘッダーの属性に複数の値を付与する場合の注意点

Last updated at Posted at 2019-01-20

概要

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がない...?:thinking:

リクエストヘッダーを組み立てる処理を以下のように修正

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を組み立てないことがわかった。

参照文献

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1