Goのhttp.RequestでPostの値を取得する(ParseFormとParseMultipartFormの違いに注意しよう)

author

GoでPostの値を取得するにはParseFormを使う。

func PostComment(w http.ResponseWriter, r *http.Request) {
e := r.ParseForm()
log.Println(e)
category := r.Form.Get("category")
content := r.Form.Get("content")
}

http.RequestのParseFormは、レスポンス(r)のFormに値をセットする。Goの公式ページにあるように、http.Requestは構造体で、要素の一つにurl.Valuesという型のFormがある。

ParseFormの後でrからpostの値を取得する。これはForm.Get、FormValue、PostFormValueの3種類がある。

  • r.Form.Get("category")
  • r.FormValue("category")
  • r.PostFormValue("category")

どれも同じ値が返ってくる。

開発者がつまずくポイント

値がとれないとき、次の原因が考えられる。

  • ParseFormをしないでpostの値を取ろうとする
  • postする側(htmlまたはjs)がpostをmultipart/form-dataに指定している

フロントエンドに慣れていないとpostに種類があることを忘れる。multipart/form-dataの場合、GoはRequestをParseFormでなくParseMultipartFormで処理する。

よく使うpostは2種類あった。

  • x-www-form-urlencoded
  • multipart/form-data
表現 パース
x-www-form-urlencoded ParseForm
multipart/form-data ParseMultipartForm

で処理する。postの値が入らないと嘆く前に、postがどの形かチェックしよう。特にapiサーバーの開発者は、postする側であるjsのfetch(ajax, superagent, ...)が、送りつける情報のbodyに何を入れているか確認しよう。FormDataになっていたらmultipart/form-dataを選んでいる。

jsのfetchでは次のようにpostする。

function proposing(text) {
return new Promise(
function (resolve, reject) {
try {
const category = "Apple";
const content = "iPhoneの使い方";
const body = new URLSearchParams();
body.append('category', category);
body.append("content", text);
fetch('/proposing', {
method: 'post',
body: body,
headers: new Headers({
'Accept': 'application/json',
}),
})
.then(res => res.json())
.then(data => {
resolve("");
})
.catch(function () {
reject('');
});
} catch (e) {
reject('');
}
}
);
}

URLSearchParamsに注目。URLSearchParamsはx-www-form-urlencodedを意味するため、ヘッダーにx-www-form-urlencodedを書かなくてもいい。