サーバーへパラメータを渡す方法について自分なりにまとめてみた。

f:id:hira98:20190523164525p:plain

【結論】

  • サーバーへパラメーターを渡す方法は、URLに含める方法とそうでない方法の2つに分類できる。
  • URLに含めない方法の仕組みを理解するには、HTTP、URL、CURLの知識が必要。
  • Railsで実装したことはあるが、本質の理解ができていなかったので自分なりにまとめてみた。
  • まとめてみた結果、時間をかけた割に質の悪い文字の塊が生成された😭

【目次】

予備知識

サーバーにパラメータを渡す方法を理解するにあたり、前提となる単語が3つあります。

  1. HTTP
  2. URL
  3. CURL

以降で説明します。

HTTPとは

堅苦しい説明はウィキペディアにお任せします。

Hypertext Transfer Protocolハイパーテキストトランスファープロトコル、略称 HTTP)とは、HTMLなどのコンテンツの送受信に用いられる通信プロトコルである。主としてWorld Wide Webにおいて、WebブラウザWebサーバとの間での転送に用いられる。

引用:Hypertext Transfer Protocol

個人的にはAmazonで商品ポチった時に届くダンボールをイメージすればいいのかなと。

Amazonから消費者に商品を安全かつ個人のプライバシーを守って届けるために、Amazonでは次のような作業を行なっているはずです。

  1. 送る商品を用意する。
  2. 届ける商品のサイズに応じたダンボールを選定する。
  3. その中に商品を入れて梱包する。
  4. 梱包した商品に応じて、必要であればシールを貼る(割れ物注意とか要冷蔵など)
  5. 送り先の住所を貼り付ける。
  6. 運送屋さんに配送をお願いする。

この商品発送の一連の流れは、データ転送時にも必要なってきます。

  • 送信するデータ
  • データ量
  • データの種類
  • 送り先情報
  • …etc

これら必要な情報を送るためのルールを規格としまとめたのがHTTPになります。

ネット上でやり取りされるデータは基本的にHTTPに従っているため、どんなブラウザを使ってもネットサーフィンができるようになっています。

URLの構成要素

URLにパラメータを格納する方法について説明する前に、URLの構成要素について説明します。

URLは下図のフォーマットになっています。

f:id:hira98:20190524204953g:plain 引用:CodeZine

引用した図だと分かりにくいですが、http://pプロトコルを表します。プロトコルとは、コンピューター同士が通信をする際の手順や規約などの約束事です。インターネット上のデータのやり取りはHTTP(Hyper Text Transfer Protocol)というプロトコルに従ってやり取りされます。

ホスト名ポート番号はインターネット上の住所です。ホスト名が建物名を表します。一軒家であれば建物名だけで場所を特定できます。しかし、マンションのように複数人が同じ建物に住んでいる場合、建物名だけで特定できないため901号室のように部屋番号まで指定します。部屋番号に当たるのがポート番号になります。

パスはサバー側で要求を分類するための文字列です。ファイルのパス指定のように/文字で区切り、右に行くほど階層が深くなります。サーバー側の実装次第では、パスにパラメータを渡すことも可能です。

クエリ・パラメータ名前から分かる通り、サーバーへ渡すパラメータを指定します。?以降の文字列がクエリ・パラメータになります。変数名1=値1&変数名2=値2のように&で区切って複数のパラメータを渡すこともできます。

フラグメントは同一ページ内の特定の場所へのリンクであることを表します。本でいう目次的な役割です。詳しくは以下記事を参照ください。

例えば記事ページの目次などはこのページ内リンクを使って作られることが多いです。その目次の場所まですぐに移動するという事がページ内リンクを使うことで簡単に実現できます

引用:RLに「#(シャープ)」が付く意味は?URLフラグメントを使いこなそう!

CURLとは?

CURL(カール)と呼びます。

念の為言っておきますが、CURLであってカールじゃないですよ。

f:id:hira98:20190523164555j:plain

CURLはターミナルを操作しサーバーへ要求を投げるためのコマンドです。

CURLを使う理由として「ターミナル経由でPC操作してるオレかっこいいー!!」と言うような、ナルシスト成分は5%程度です。全く無いとは言いません。

ブラウザを使ってパラメーターを送る場合、URLにパラメータを指定する方法は簡単に実装できます。しかし、HTTPプロトコルのボディー部にパラメータを含ませる場合、HTMLのフォームを作成するか、ツール(chromeが提供している「Restlet Client」など)を使う必要があります。フォームは書くの面倒だし、GUIツールだとブログに載せるのが面倒。と言う理由で、CURLを採用しました。 CURLの使い方については後述します。

サーバーにパラメータを渡す方法

サーバーにパラメーターを渡す方法は3つあります。

  1. パスパラメーター

    URLのパスにパラメーターを設定する方法。

  2. リクエストパラメーター(クエリ・パラメーター)

    URLのクリエ・パラメーターに設定する方法。

  3. ボディーパラメーター

    サーバーとやり取りする際は、HTTPというプロトコルにそってやり取りしている。HTTPプロトコルで扱うデータはヘッダー部とボディー部に分類することができる。URLは送信先を示す情報であるため、HTTPプロトコルではヘッダー部に格納される。HTTPプロトコルのヘッダー部でなく、ボディー部にパラメーターを格納して送信する方法をボディーパラメータと言う。

URLにパラメータを含めるケース

URL構成要素で軽く説明した通り、URLでパラメータを指定する方法は、次の2パターンがあります。

  • パスで指定する(これを、パスパラメータと言う)

  • クエリ・パラメータで指定する(リクエストパラメータとも言う)

# 例
http://example.com/path/param1/param2?query1=param3&query2=param4

# パスパラメータはparam1, param2
# リクエストパラメータはparam3とparam4になります。

URLにパラメータを含めないケース

理解するには、URLとHTTPプロトコルの関係性ついて把握する必要があります。

こいつらの関係性を把握するために使うのが、麦わら帽子がトレンドマークのあのキャラ。

f:id:hira98:20190523164615j:plain

そうルフィー!!

ではなく、カールおじさん

f:id:hira98:20190523164630j:plain

でもなく、CURLです。

(すみません。疲れてきたので、おふざけ入れてます。)

CURLを使うことで、どのようなHTTPリクエストが送られているかを把握することができます。

URLにパラメータを含むケースと、含まないケースの実行結果を以下に示します。

1) URLにパラメーターを含めるケース

$ curl http://localhost:8080/api/test2?name=98hira -s -v
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /api/test2?name=98hira -s HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 400 
< Transfer-Encoding: chunked
< Date: Thu, 23 May 2019 06:31:28 GMT
< Connection: close
  

2) URLにパラメーターを含めないケース

$ curl -X POST -H "Content-Type: application/json" -d '{"Name":"sensuikan1973","Age":"100"}' http://localhost:8080/api/post -s -v 
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /api/post HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 36
> 
* upload completely sent off: 36 out of 36 bytes
< HTTP/1.1 200 
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 49
< Date: Thu, 23 May 2019 06:33:33 GMT
< 
登録だよ{"Name":"sensuikan1973","Age":"100"}
* Connection #0 to host localhost left intact

上記例で使用したCURLコマンドのオプションと見方は次の通りです。

  • culr [URL]だけで、ブラウザ使ってURLアクセスした時と同じ結果をえられる。

  • -s-vをつけるとHTTPリクエストヘッダーの詳細が次のルールに従って出力される。

    • >がサーバーへ送ったデータ
    • <がサーバーからの応答結果
  • -XでHTTPメソッド(GETやPOST)を指定できる。未指定の場合はGETになる。

  • -HでHTTPヘッダーフィールドを追加できる。

    例で書いたContent-Typeは送るデータの種類をjson形式に指定しています。

    因みに、データの種類の指定方法はMIMEタイプに従う必要があります。

  • -dでは実際に送るデータの中身を指定します。

次にコマンドの実行結果について見ていきます。

色々出ていますが、注目すべきは「2.URLにパラメーターを含めないケース」の時にだけ出力されるContent-Length: 36です。これがボディー部に含まれるデータのサイズを表しています。

データは -d '{"Name":"sensuikan1973","Age":"100"}'で指定しています。

指定したデータの文字数を数えてみると確かに一致することが分かります。

$ irb
irb(main):001:0> s = '{"Name":"sensuikan1973","Age":"100"}'
=> "{\"Name\":\"sensuikan1973\",\"Age\":\"100\"}"
irb(main):002:0> s.length
=> 36

以上のことから、URLにパラメータを含めないケースでは、HTTPのボディー部にデータを格納していることが分かりました。

ちなみに、CURLでボディー部も表示したかったのですが、オプションが分かりませんでした。。

(コマンド引数にデータを指定してるんだからわざわざ表示する必要ないでしょ。という方針だと勝手に判断しました。)

参考

https://viral-community.com/security/curl-8263/

→CULRの使い方

https://ryoutaku-jo.hatenablog.com/

→ブログ投稿のモチベーションを維持するための情報源です。

最後に

色々と欲張りすぎてしまいました。

興味の赴くままに調べて範囲を広げすぎてしまい収集がつかなくなって、挙句の果てに面倒くさくなったので無理やり終わらせました。

もっと戦略的に取り組むべきだと実感しました。