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を書かなくてもいい。