AngularJsの$http.postで414エラー

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
414はエンジェルナンバー

この記事を三行にまとめると

URLが長すぎるぞっていうエラー
「params」を「data」に変えればオーケー
天使のご加護をあなたに
別にAngularJsに限った話ではないのですが、GETやPOSTのリクエスト時に414エラーが出ることがあります。

414は「Request-URI too large」というエラーです。URLが長すぎるぞっていうエラー。URLのパラメータにやたらめったらと文字をつけ足してリクエストを投げるとこのエラーが出ます。

具体的にどれくらい長いとやばいのかってのはブラウザやサーバーの設定によって変わるみたいなのですが……参考までに、Apache2.2ではデフォルトの設定だと8190バイトが上限みたいです。8190バイト……半角文字で8190文字ってことですね。URLが8000文字を超えるってなかなかありえないケースのような気がしますが、まあとにかく414エラーが出たらURLがとんでもなく長くなってるぞって判断すればいいです。

で、今回僕はAngularJsでデータをPOSTする際に414エラーが出たわけなのですが、どういう状況で出たかってのとそれを解消するにはどうすればいいかってのを見ていただきたく存じます。



状況確認

とりあえず以下のコードをご覧くだせえ。

url = POSTするURL
data = フォームのデータ

$http({
  url: url,
  method: "POST",
  params: data
}).then(function(response){
  //処理成功
});

凄いざっくりしたコードですがこんな感じでデータをPOSTしていました。「data」という変数にフォームのデータが入ってると仮定してください。もしフォームにテキストエリアが複数あったりすると、もんのすごーい文字数になるケースも出てきます。

上記のコードでは「params」というパラメータにdataを設定しています。このparamsというのはURLのパラメータに該当する部分なので、この場合だとフォームで入力されたデータが全部URLにくっついちゃうわけですね。もんのすごーい文字数がURLにくっつく。場合によっては8190バイトを超えるくらいに。

そもそもこれだとPOSTしているように見えて実質的にはGETなんですよね。だからPHP側でも$_POSTではデータを受け取れず、$_GETで受け取るような形になっちゃってます。



$_POSTで受け取れるように

では$_POSTで受け取れるようにするにはどう改修すれば良いか。

答えは簡単です。「params」を「data」に変えればオーケー。

url = POSTするURL
data = フォームのデータ

$http({
  url: url,
  method: "POST",
  data: data
}).then(function(response){
  //処理成功
});

これでURLにデータがくっつかなくなるので414エラーにもならず、さらにPHP側で$_POSTでデータを受け取れるようになります。



もし取れなかった場合

例えばdataの中身がJSON形式の文字列だった場合。

data = {title:'タイトル',text:'本文'}

例えばこんなの。こういう場合は上記のやり方でデータをPOSTしても$_POSTで受け取れないことがあります。ヘッダーのContent-Typeが「application/x-www-form-urlencoded」だったりすると$_POSTに値が入ってこない。

そういう場合はクエリ形式に直してデータを送信する必要があります。クエリ形式ってのはURLの後ろにパラメータをくっつけるときのあの感じ。

data = 'title=タイトル&text=本文'

JSON形式のデータをクエリ形式に直したいのなら自分でそういう処理を書くか、jQueryを併用してるなら「$.param()」などを使うのがいいと思います。

url = POSTするURL
data = $.param({title:'タイトル',text:'本文'});

$http({
  url: url,
  method: "POST",
  data: data
}).then(function(response){
  //処理成功
});

あるいは「transformRequest」というパラメータを追加してもいいです。

url = POSTするURL
data = {title:'タイトル',text:'本文'};

$http({
  url: url,
  method: "POST",
  transformRequest: function(data){
   return $.param(data);
  },
  data: data
}).then(function(response){
  //処理成功
});

やってることは一緒です。





414エラーってそうそう頻繁に発生するものではないので、最初何のエラーかよく分かってませんでした。てゆーか動作テストの段階ではそんなにものすごい長文を入れてテストしてなかったもんだから、ユーザーからエラーを指摘されても「こっちじゃ再現できねーんですけど。おたくの端末のせいじゃね?」って強気な態度取っちゃってました。

ようやくエラーが判明した時も最初何のことだかやっぱり状況を分かってなくて「414って何だよ。エンジェルナンバー? エラーどころか天使の祝福を受けてるじゃねーかぁぁぁ」ってあくまでも非を認めないスタンスだったんですが、お告げに従っていろいろ調査してみたら上のような感じでしたという次第で……。

まあ何にせよ、データをPOSTさせようとしたのになぜか動かなかったり$_POSTにデータが入ってこないって時には、この辺が原因かもしれないのでちょいと疑ってみてください。

天使のご加護をあなたに。
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください