[知らなかった]form要素のaction属性に指定するURLの末尾のスラッシュを省略すると

Read More

HTMLの挙動について今更ながらに気がついたことがある。


HTMLページにおいて、
form要素のaction属性にURLを指定する際、URLの末尾の"/"(スラッシュ)を省略するとPOSTデータがsubmitされないことがわかった。






な…なんだってー!?




まあこれだけだとちょっと意味がわからんだろうから下のコードを見て欲しい。


■index.php
<?php
if (isset($_POST))
{
  print_r($_POST);
  print '<br>';
}
if (isset($_GET))
{
  print_r($_GET);
  print '<br>';
}
?>
<form action="http://example.com" method="post">
  <input type="text" name="txt_1" value="test">
  <input type="submit" name="btn_submit" value="submit">
</form>

上記のコードをindex.phpの名前で保存し、http://example.com/index.php で呼び出せる場所に設置する。

form要素のaction属性は"http://example.com"としている。
submitはindex.phpに飛ばしたいわけだがURL末尾のスラッシュとindex.phpの指定は省略している。

なおこのURLの指定は別に必ずしもドメインのルートである必要はなく間にフォルダを挟んでもよい。
例えばsampleフォルダの下にindex.phpを設置する場合はURL指定が"http://example.com/sample"となるようにする。


まあ先述したコードを見てもらえばわかると思うが、
要するにformが自分自身のファイルにsubmitをしてリクエストパラメータを画面上に表示する、というシンプルなもの。


デモを用意したのでこちらで挙動をそれぞれ試してみて欲しい。
↓デモ
http://xirasaya.com/demo/8



動作させてみると、
URLの末尾のスラッシュを省略して かつmethodがpostの時のみPOSTデータが送られていない。
この挙動は本当に驚きなんだが。


Firefox、Chrome、IEなんかで適当に確認してみたけどどれも同じ挙動となる。


えー、そうなの?
そんなルールがあったの?
オレはマジで今までこんなの知らなかったし意識したこともなかったよ。



これみんな知ってるの情報なの?
知ってて当然の挙動なの?





--
おまけ:
アンカー要素にURLを指定するときもURL末尾のスラッシュを省略することがある。

昔どこかの記事で、
「HTMLページのアンカー要素で指定するURLにはスラッシュはあったほうが良い」
って記事を読んだことがある。

URL末尾のスラッシュはフォルダをあらわしているので、サーバ側で補完する挙動がない分、ファイルアクセスの処理が高速になるんだとかなんとか。

当時はふーんって感じで、
「まあスラッシュがあった方が良いのね」くらいにしか思ってなかった。
しかしこのせいもあってそれ以来はなるべく付けるようにしてた。

ま、だから今日までform要素でこんな挙動があるって知らなかったわけなんだが。

もっとも今はサーバのスペックが高いのでこんなこといちいち考えてやってるやつは皆無だろう。

しかし当時はそんなちょっとしたことですら皆気にしてた時代があった。
今はメモリ破棄すら知らないやつがいるからなあ。




--
おまけのおまけ:
そういえばスーパーマリオの容量なんてわずか40KBなのだそうな。
これはスマホで撮影した写真1枚の容量(約50KB~1.2M)よりも小さい。
マジにとんでもないことだ。


昔の人はそれはもう大変な創意工夫をしてメモリ削ったり処理を見直して最適化してた。

で、不思議なことにそういった制限がきつかった時代の方が面白いゲームが多かったように思う。
もちろん面白いと感じた理由は他の要因も強くあると思うが。

しかし当時から比べてみるとあらゆるものの上限が大幅に伸びて自由にできることが多くなった。
しかしその変わりに色んなものを失ってる気がする。


ゲームに限らず、小説や絵や音楽なども制限があった方がいいものができる。
これは本当にそう思う。


例えば真っ白な画用紙を渡されて「好きなものを書いていいよ」と言われると大抵は何を書いたらいいかわからなくてとまどう。
だが「大きな木を書いて」と言われると誰でも木を書く。書ける。
「家より大きな」と加えるとより明確に書ける。
ある程度の方向性を示してやることでわりと誰でも一定の成果が得られるようになるわけだ。

このように決められた範囲の中でこそ実力を発揮できるというやつは案外多い。
もう少し端的に書くと、多くの人は何かしらの制限があった方がパフォーマンスを発揮する

誰しもに真っ白な画用紙なんか必要ないのだ。
やりたいことの明確なビジョンがある奴にだけ真っ白な画用紙が必要なだけで。


やりたいことがあるやつは自分の中で一本筋が通っている。
それがいわゆる「自分ルール」である。
こと 自由な物づくりに関してはこの「自分ルール」という特殊な制限を自分自身に課しているやつが総じていいものを作れるのだと思う。

まあ ともすればただの頑固者と呼ばれることになるのだが。
あるいは変人とかかね




-- 参考サイト
■URLの最後に付ける「トレイリング スラッシュ」ありなしの違いはSEOに影響するのか? | 海外SEO情報ブログ
https://www.suzukikenichi.com/blog/differences-between-trailing-slash-and-non-trailing-slash/

■307 Temporary Redirect - HTTP | MDN
https://developer.mozilla.org/ja/docs/Web/HTTP/Status/307


-- 2019/03/26 本文をいくつか修正













Comments(9)

1  びるぱん  2013/07/17 (水) 18:11 ID:1HRonTP15
大学では、消費メモリを意識してプログラムを書けと教わった。

現在は、可読性が高くなるように冗長に書けと言われる。

どうすりゃいいのさ。

さすがに何も考えずにphp書くと、さすがに遅い気はするね。

末尾のスラッシュもそうなんだけど、(google先生曰く)リンクはhttp://hogehoge.comではなくて、://hogehoge.comって書くと良いんだってねぇ。

時々、curlなんかでこれ書いてエラー吐かれるケドね。
本当、どうすりゃいいのさ。

スラッシュの件は知らなかった、むしろたぶんいつの間にか無視というかそんなもんだと思って修正してたな。

2  みやび  2013/07/17 (水) 18:30 ID:RJX4pe315
昔はメモリが少なかったけど、今はメモリより人間様の生産性的なボトルネックが問題。
なので可読性重視で、明らかに効率の悪い箇所だけ対処する位で良いと思う。

PHPって実行速度やオブジェクト指向的な考えを妥協しつつ、
それなりに動くWebサイトを早く仕上げるのに適した言語だと思うしね。

3  シラサヤ  2013/07/17 (水) 22:54 ID:LQnjuua15
>末尾のスラッシュもそうなんだけど、(google先生曰く)リンクはhttp://hogehoge.comではなくて、://hogehoge.comって書くと良いんだってねぇ。

↑これマジ?
プロトコル省略したらなんか色々と問題になりそうだけど…



>昔はメモリが少なかったけど、今はメモリより人間様の生産性的なボトルネックが問題

昔と今と決定的に違うのはメモリの使い方だろうなあ。
今はメモリ上にデータを展開させてどうこうするプログラムがほんとに多い。memcachedにしてもCodeIgniterにしても。

まあそれで動作速度が劇的に上がるんだから仕方ないんだけど。



まとめたら書き方も考え方もどんどん変化してるんだなーと






4  みやび  2013/07/18 (木) 09:22 ID:hl6rTiZ15
GoogleがjQueryのライブラリとかホストしてますが
https://developers.google.com/speed/libraries/devguide?hl=ja

そこのサンプルコードがこんな感じですね
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

ただ、何故こうするのかがわかってないです。
ブラウザではhttpとhttpsの違いで表示してくれないケースが有り、
その差異を上手く吸収してくれるという記事を読んだ気がしますが見つからない;w;

5  シラサヤ  2013/07/18 (木) 20:52 ID:b4rGIOy15
>そこのサンプルコードがこんな感じですね
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

おわーほんまじゃー


>ブラウザではhttpとhttpsの違いで表示してくれないケースが有り、
その差異を上手く吸収してくれるという記事を読んだ気がしますが見つからない;w;

httpとhttpsの差異を吸収してくれるってのは理由として納得できるね。



まあオレはそれでもプロトコル省略はすることはないだろうなあ。
変な癖付いたらいやだしね






6  みやび  2013/07/22 (月) 16:17 ID:AbsmhxT15
ちゃんと勉強してきましたよ(仕事中に)

↓のサイトによるとRFC3986に定義されてるって話です(RFC読むと眠くなるので未確認)
http://www.koikikukan.com/archives/2012/05/11-012345.php

1  2 3
http  : //hogehoge.com

URLは以下のように分類分けされています。
1:スキーム名
2:スキーム名とパスの区切り文字
3:パス

RFC3986によると1,2を省略した場合、
アクセスに使用したスキーム(http or https)を利用して他の接続を行うとのことです。
つまりプロトコルの差異を吸収してくれます。

とはいえ、SSLを利用しつつSSLを維持して他のサイトへアクセス…
GoogleのjQueryホストとかを利用するくらいしかメリット無さそうですね。
個人利用だとほぼ使う箇所皆無だと思います。

7  シラサヤ  2013/07/22 (月) 21:58 ID:YlTXbKU15
> ttp://www.koikikukan.com/archives/2012/05/11-012345.php

URIに関する仕様としてRFC3986では
「//」でURIを開始することが認めてあるんだね。

でもそれだとIEで2回読み込まれる問題が残るんだね…
■Missing schema double download
ttp://www.stevesouders.com/blog/2010/02/10/5a-missing-schema-double-download/



あとリンク先で言及されてたけど、
「URIスキーム」って言葉と「プロトコル」って言葉は区別して使われるものなんだね。

まあ確かに、
「URIスキームに指定されたプロトコルによってブラウザはリソースを取得する方法を決定する」
って具合にその仕組みをちゃんと文章にしたらそれも納得できる。

今回の場合はURIの書式の話だから
「プロトコルが省略され…」
って言うより
「URIスキームが省略され…」
って方が正しいだろう。



うーん言葉って難しいわ…







8  ゆいちょ  2019/03/24 (日) 20:41 ID:rcB7kND15
ものすごく前の記事に対してで申し訳ないのですが、
気になって検証してみたのでコメントしておきます。

トレイリングスラッシュ無しへアクセスした場合、基本的に301リダイレクトされます

root@sv2:~# curl -sv 'http://xirasaya.com/demo/8' 2>&1 1>/dev/null | awk '/HTTP/ || /Location/'
> GET /demo/8 HTTP/1.1
< HTTP/1.1 301 Moved Permanently
< Location: http://xirasaya.com/demo/8/
root@sv2:~#

301リダイレクトされるとブラウザはPOSTパラメータを捨ててGETで取りに行くので、submitされないようです。

ちなみに、GETの時はURLにパラメーターがあるので、リダイレクト後のURLにもパラメーターがくっついてるために、301リダイレクトされても問題ないようです。

root@sv2:~# curl -sv 'http://xirasaya.com/demo/8?txt_2=test2&btn_submit2=submit' 2>&1 1>/dev/null | awk '/HTTP/ || /Location/'
> GET /demo/8?txt_2=test2&btn_submit2=submit HTTP/1.1
< HTTP/1.1 301 Moved Permanently
< Location: http://xirasaya.com/demo/8/?txt_2=test2&btn_submit2=submit
root@sv2:~#

多分サーバーの設定でトレイリングスラッシュなしは307リダイレクトをするようにできればPOSTもsubmitされるかと思います(未検証)

9  シラサヤ  2019/03/26 (火) 11:07 ID:4wIP89v15
トレイリングスラッシュ有りの場合はレスポンスコードで200が返ってきてるのに対して、
トレイリングスラッシュ無しの場合は301でlocationリダイレクトされてるね

なるほどPOST値がなくなるわけだ


あと307(2014/1発行)の存在を知らなかったのでそちらも勉強になりました
感謝