やりたいこと
https://AAAA.jpx から https://BBBB.jpx へREST形式でGETしたりPOSTを送りたい。
RESTfulAPI について
URLをリソースとして表現してアドレスによってデータの取得、作成、削除、更新などを行えるようにする設計思想
https://example.com/api/create
へPOSTリクエストとリソースを作成する。
例えばレスポンスとして作成されたリソースのid:123が返ってくるなど。
https://example.com/api/get/123
へGETリクエストを送るとid:123のリソースを取得する。
https://example.com/api/update/123
へPUTリクエストを送るとid:123のリソースを更新する。
https://example.com/api/delete/123
へDELETEリクエストを送るとid:123のリソースを削除する。
といった感じになる。
割と雑な説明なので注意。
CORS (Cross-Origin Resource Sharing)について
最近のWebブラウザは悪いことができないようにSame-Origin Policyが適用されている。
これが適用されている場合ドメインが違うとアクセスに制限がかかる。
ドメインだけでなくポートが違うだけでもアクセスすることができない。
※スキーム(httpとhttpsなど)が違う場合もアクセスできないという解説が見受けられるがそもそも使用しているポートが違うので分ける必要があるかは不明
サンプルソース
基本はレスポンスにヘッダを2つ追加するといい
例えばnode.js * express だと
router.get("", /* @callback */ function(req, res) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.send("Hello REST Api"); });
といった感じで簡単にCORS対応が可能(上記ソースは多少問題がある)だがlaravelだとルーティング周りでいろいろやっているので一手間必要になる。
1. Controller作成
ターミナルからプロジェクトルートで以下のコマンドを叩くことでコントローラが作成できる。そのまま作ってもいい。
php artisan make:controller RestController --resource
...projectDir\Http\Controllers\RestController.php
に作成されるはず
getやpostをするためのメソッドが一通り作られる。
2. routes.phpに追記
cors対応を行う。実際は記述箇所はどこでもいいが一応ファイルの先頭へ下記を追記する。
header('Access-Control-Allow-Origin: *'); header( 'Access-Control-Allow-Headers: Authorization, Content-Type' );
「こんなところに書いて大丈夫なの?」という疑問が湧くかもしれない(実際私がそう思ったけど)
意味合いとしては全体を外部からのアクセスを許可するというということだが後述のCSRF対策があるので問題ないはず。
3. routes.phpにルートを追記
下記はGET,POST,PUT,DELETEを定義しているが必要なものだけでもいいRoute::group(['prefix' => 'api'], function () { Route::resource('xxxx', 'XXXXController'); });URLは
webRoot/api/xxxx になる
ルートの状態はプロジェクトのルートで下記のコマンドを入力することで確認できる。
php artisan route:list
+--------+-----------+----------------------+------------------+---------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+----------------------+------------------+---------------------------------------------+------------+
| | GET|HEAD | / | | Closure | web |
| | POST | api/rest | api.rest.store | App\Http\Controllers\RestController@store | web |
| | GET|HEAD | api/rest | api.rest.index | App\Http\Controllers\RestController@index | web |
| | GET|HEAD | api/rest/create | api.rest.create | App\Http\Controllers\RestController@create | web |
| | DELETE | api/rest/{rest} | api.rest.destroy | App\Http\Controllers\RestController@destroy | web |
| | PUT|PATCH | api/rest/{rest} | api.rest.update | App\Http\Controllers\RestController@update | web |
| | GET|HEAD | api/rest/{rest} | api.rest.show | App\Http\Controllers\RestController@show | web |
| | GET|HEAD | api/rest/{rest}/edit | api.rest.edit | App\Http\Controllers\RestController@edit | web |
+--------+-----------+----------------------+------------------+---------------------------------------------+------------+
+--------+-----------+----------------------+------------------+---------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+----------------------+------------------+---------------------------------------------+------------+
| | GET|HEAD | / | | Closure | web |
| | POST | api/rest | api.rest.store | App\Http\Controllers\RestController@store | web |
| | GET|HEAD | api/rest | api.rest.index | App\Http\Controllers\RestController@index | web |
| | GET|HEAD | api/rest/create | api.rest.create | App\Http\Controllers\RestController@create | web |
| | DELETE | api/rest/{rest} | api.rest.destroy | App\Http\Controllers\RestController@destroy | web |
| | PUT|PATCH | api/rest/{rest} | api.rest.update | App\Http\Controllers\RestController@update | web |
| | GET|HEAD | api/rest/{rest} | api.rest.show | App\Http\Controllers\RestController@show | web |
| | GET|HEAD | api/rest/{rest}/edit | api.rest.edit | App\Http\Controllers\RestController@edit | web |
+--------+-----------+----------------------+------------------+---------------------------------------------+------------+
4. クロスサイトリクエストフォージェリ(CSRF)対策の対策
以上でいけるかと思いきやエラーになる。CSRFチェックから除外するURLを記述(Laravel5.1以降のみ)
下記はwebRoot/api以下を全て除外
App/Http/Middleware/VerityCsrfToken.php
protected $except = [ 'api/*', ];
ここまででやったことをまとめると全体に外部からアクセス可能なようにヘッダを追加して、
RestfulAPI用にルートを作成して、
webRoot/api以下をCSRFチェックから除外した と言った感じになる。
これで外部からリクエストを投げることが可能になります(取扱注意!!)
メモ
5.1未満が CSRFの除外設定ができないので一手間いるかも
5.3以降はルーティングの方法が変わっているが、ここにある情報で十分対応可能かと(apiっていうミドルウェアが追加されているのでそれ使うだけでいいかもしれない)
参考
REST APIとは? – API設計のポイント!
http://wp.tech-style.info/archives/683
CORSまとめ
http://qiita.com/tomoyukilabs/items/81698edd5812ff6acb34
cors - Laravel5 + AngularJS で作るSPA
http://qiita.com/fluke8259/items/c884bada22ccd286cf48
Laravel - RESTful
http://qiita.com/fluke8259/items/23e833ed327c10fcace0
Laravel5.0 CSRFチェックを無効化
http://qiita.com/rana_kualu/items/3f9d0d6b9a363fd2108e