Laravelの外部URLリクエスト機能「HTTPクライアント」を使ってみる
2024年 4月17日 Posted 野々瀨(フロントエンドエンジニア)
Laravelには外部URLリクエストを行うことのできる、HTTPクライアントという機能があります。LaravelのHTTPクライアントは、GuzzleというライブラリをLaravel上で扱いやすくしたものです。ちなみにGuzzleは内部的にはPHPのcURLを使用しています。
今回はLaravelのHTTPクライアントの使い方をご紹介しようと思います。なお、全ての機能をご紹介するわけではありませんので、ご了承ください。
LaravelのHttpファサード
ファサード(Facade)とは、クラスをインスタンス化せずに静的(static)メソッドとして使用できる機能のことです。
クラス名::メソッド();
LaravelではHTTPクライアントをHttpファサードとして提供しています。ここではこのHttpファサードの使い方をご紹介します。
基本的な使い方
Httpファサードをuse
キーワードで読み込みます(インポート)。また、Httpファサードは基本的にIlluminate\Support\Facades\Response
インスタンスを返しますので、こちらも読み込みます。
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\Response;
HttpファサードはHttp::メソッド名()
で実行します。
$response = Http::xxx();
またチェーンメソッドとしてHttp::メソッド名()->メソッド()
のようにメソッドを繋げて実行することも可能です。
$response = Http::xxx()->xxx();
リクエスト
各HTTPメソッドでのリクエスト
HTTPクライアントはGET、POST、HEAD、PUT、PATCH、DELETEのHTTPメソッドに対応しています。HTTPメソッドは対応するHttpファサードの各メソッドでリクエストすることができます。各メソッドは第一引数にリクエストしたいURLを指定します。
$response = Http::get('https://www.example.co.jp/'); // GETメソッド
$response = Http::post('https://www.example.co.jp/'); // POSTメソッド
$response = Http::head('https://www.example.co.jp/'); // HEADメソッド
$response = Http::put('https://www.example.co.jp/'); // PUTメソッド
$response = Http::patch('https://www.example.co.jp/'); // PATCHメソッド
$response = Http::delete('https://www.example.co.jp/'); // DELETEメソッド
リクエストデータの追加
リクエストメソッドの内、post
メソッド、put
メソッド、patch
メソッド、delete
メソッドは、第二引数にリクエストデータを追加することができます。リクエストデータは連想配列で指定します。
$response = Http::get('https://www.example.co.jp/', [
'foo' => 'abc',
'bar' => 123
]);
第二引数を指定すると、初期状態ではapplication/json
としてリクエストされます。
クエリ文字列
リクエストメソッドの内、get
メソッドとhead
メソッドは、第二引数にクエリ文字列を指定することができます。クエリ文字列は連想配列で指定します。
$response = Http::get('https://www.example.co.jp/', [
'foo' => 'abc',
'bar' => 123
]);
また、withQueryParameters
メソッドを使用することでもクエリ文字列を指定することができます。
$response = Http::withQueryParameters([
'foo' => 'abc',
'bar' => 123
])->get('https://www.example.co.jp/');
ヘッダーの追加
withHeaders
メソッドを使用して、ヘッダーを追加することができます。
$response = Http::withHeaders([
'User-Agent' => 'xxx',
'Content-Type' => 'application/json'
])->post('https://www.example.co.jp/', [
'foo' => 'abc',
'bar' => 123
]);
コンテンツタイプ(Content-Type)の追加
コンテンツタイプ(Content-Type)ごとにメソッドが用意されています。
コンテンツタイプ | メソッド名 | 説明 | コード例 |
---|---|---|---|
application/x-www-form-urlencoded | asForm | フォームとして送信する際に使用します。 | Http::asForm()->post( ... ) |
application/json | asJson | JSONとして送信する際に使用します。 | Http::asJson()->post( ... ) |
multipart/form-data | asMultipart | 添付したファイルを送信する際に使用します。 | Http::asMultipart()->post( ... ) |
$response = Http::asForm()->post('https://www.example.co.jp/', [
'foo' => 'abc',
'bar' => 123
]);
本文として送信
素の本文(リクエストボディ)として送信する場合は、withBody
メソッドを使用します。第一引数に送信する内容を指定します。また第二引数でコンテンツタイプ(Content-Type)を指定することができ、初期値は"application/json"です。
$response = Http::withBody('{"foo": "abc", "bar": 123}')->post('https://www.example.co.jp/');
$response = Http::withBody(
base64_encode(file_get_contents('image.jpg')),
'image/jpeg'
)->post('https://www.example.co.jp/');
ユーザーエージェントの追加
withUserAgent
メソッドを使用することで、ユーザーエージェントを追加することができます。
$response = Http::withUserAgent('xxx')->get('https://www.example.co.jp/');
なお、Laravelのバージョン8.8より以前はwithUserAgent
メソッドがなく、代わりに次のようにwithHeaders
メソッドを使用して対応していました。
$response = Http::withHeaders(['User-Agent' => 'xxx'])->get('https://www.example.co.jp/');
ファイルを送信(アップロード)
attach
メソッドを使用することで、ファイルを送信(アップロード)することができます。これはコンテンツタイプを"multipart/form-data"として送信します。第二引数にファイル(文字列またはバイナリまたはファイルポインタ)、第三引数に送るファイル名を指定します。
$response = Http::attach(
'attachment',
file_get_contents('image.jpg'),
'image.jpg'
)->post('https://www.example.co.jp/');
受け取ったデータを処理する形式
ブラウザなどのクライアントとして、サーバからどのような形式で受け取りたいかの形式を指定することができます。JSONで受け取りたい場合は、acceptJson
メソッド、それ以外に自身で指定する場合はaccept
メソッドまたはwithHeaders
メソッドを使用します。
// JSON
$response = Http::acceptJson()->get('https://www.example.co.jp/');
// 任意(acceptメソッドの場合)
$response = Http::accept('application/json')->post('https://www.example.co.jp/');
// 任意(withHeadersメソッドの場合)
$response = Http::->withHeaders([
'Accept' => 'application/json'
])->get('https://www.example.co.jp/');
Cookieを送信
withCookies
メソッドを使用することで、Cookieを追加して送信することができます。第一引数にCookie名と値をセットにした連想配列、第二引数にドメインを指定します。
$response = Http::withCookies([
'foo' => 'abc',
'bar' => 123
], 'example.co.jp')->get('https://www.example.co.jp/');
Basic認証またはDigest認証を通す
withBasicAuth
メソッドでBasic認証、withDigestAuth
メソッドでDigest認証をそれぞれ通すことができます。どちらのメソッドも第一引数にユーザー名、第二引数にパスワードを指定します。
// Basic認証
return Http::withBasicAuth('username', 'password')->get('https://www.example.co.jp/');
// Digest認証
return Http::withDigestAuth('username', 'password')->get('https://www.example.co.jp/');
Guzzleのオプションを設定
withOptions
メソッドを使用することで、Guzzle自体のオプションを設定・変更することができます。例えば次のコードではリダイレクトに関する詳細な設定を変更しています。
return Http::withOptions([
'allow_redirects' => [
'max' => 5,
'strict' => false,
'referer' => false,
'protocols' => ['http', 'https'],
'track_redirects' => true
]
])->get('https://www.example.co.jp/');
Guzzleのオプションについて詳しくは次のページをご覧ください。https://docs.guzzlephp.org/en/stable/request-options.html
リダイレクトしないようにする
LaravelのHTTPクライアントは通常、リクエスト先がリダイレクトである場合、そのリダイレクト先を辿っていきます。巡り続け、リダイレクトで亡くなった時に初めてレスポンスとして返すようになります。
withoutRedirecting
メソッドを使用することで、リダイレクト先を巡らずにその状態のままレスポンスとして返すことができます。
return Http::withoutRedirecting()->get('https://www.example.co.jp/');
リダイレクトを巡る最大回数
maxRedirects
メソッドを使用することで、リダイレクトを巡る最大回数を指定することができます。
return Http::maxRedirects(3)->get('https://www.example.co.jp/');
SSL証明書の検証を行わない
withoutVerifying
メソッドを使用することで、SSL証明書の検証を行わないように設定することができます。
$response = Http::withoutVerifying()->get('https://www.example.co.jp/');
タイムアウト
timeout
メソッドを指定すると、リクエストのタイムアウトを指定することができます。第一引数にタイムアウトするまでの時間を「秒」で指定します。初期値は「30」です。
$response = Http::timeout(10)->get('https://www.example.co.jp/');
サーバへの接続のタイムアウト
connectTimeout
メソッドを指定すると、サーバへの接続した際のタイムアウトを指定することができます。第一引数にタイムアウトするまでの時間を「秒」で指定します。初期値は「10」です。
$response = Http::connectTimeout(30)->get('https://www.example.co.jp/');
接続失敗時の再試行の設定
retry
メソッドを使用することで、接続失敗時の再試行の設定を粉うことができます。 第一引数に回数、第二引数に待機時間(秒)、第三引数に再試行の条件を指定することができます。
return Http::retry(3, 100)->get('https://www.example.co.jp/');
レスポンス
レスポンスボディを取得
body
メソッドを使用することで、レスポンスボディを取得することができます。戻り値は文字列で返します。
$response = Http::get('https://www.example.co.jp/');
$body = $response->body();
またjson
メソッドを使用すると、JSON形式で取得することができます。戻り値はオブジェクトで返します。引数を指定することもでき、第一引数はキー、第二引数に値が見つからなかった時の初期値を指定することができます。
$json = $response->json();
// 取得するキーを指定した場合
$value = $response->json('foo'); // 初期値なし
$value = $response->json('foo', 'abc'); // 初期値あり
状況(HTTPステータス)の取得
status
メソッドを使用することで、状況(HTTPステータス)を取得することができます。戻り値は200などHTTPステータスコードの番号を数値で返します。
$response = Http::get('https://www.example.co.jp/');
$status = $response->status();
また各状況は真偽値として、評価することもできます。戻り値はBoolean値で返します。
HTTPステータスコード | 名称 | 例 |
---|---|---|
200 | 200 OK | $result = $response->ok(); |
201 | 201 Created | $result = $response->created(); |
202 | 202 Accepted | $result = $response->accepted(); |
204 | 204 No Content | $result = $response->noContent(); |
200 以上 300 未満 | $result = $response->successful(); |
|
301 | 301 Moved Permanently | $result = $response->movedPermanently(); |
302 | 302 Found | $result = $response->found(); |
400 | 400 Bad Request | $result = $response->badRequest(); $result = $response->failed(); |
401 | 401 Unauthorized | $result = $response->unauthorized(); |
402 | 402 Payment Required | $result = $response->paymentRequired(); |
403 | 403 Forbidden | $result = $response->forbidden(); |
403 | 403 Forbidden | $result = $response->forbidden(); |
404 | 404 Not Found | $result = $response->notFound(); |
408 | 408 Request Timeout | $result = $response->requestTimeout(); |
409 | 409 Conflict | $result = $response->conflict(); |
422 | 422 Unprocessable Entity | $result = $response->unprocessableEntity(); |
429 | 429 Too Many Requests | $result = $response->tooManyRequests(); |
400 以上 500 未満 | $result = $response->clientError(); |
|
500 | 500 Internal Server Error | $result = $response->serverError(); |
$response = Http::get('https://www.example.co.jp/');
if ($response->notFound()) {
...
}
さらにreason
メソッドを使用すれば、直観的なフレーズで状況を取得することができます。例えばリクエストしたHTTPステータスコードが200だった場合の戻り値は"OK"と返し、404であれば"Not Found"と返します。
$response = Http::get('https://www.example.co.jp/');
echo $response->reason();
レスポンスヘッダーを取得
headers
メソッドを使用することで、レスポンスヘッダーを取得することができます。戻り値は連想配列で返します。
$response = Http::get('https://www.example.co.jp/');
$headers = $response->headers();
echo $headers['Content-Type'];
また、header
メソッドを使用することで、特定のヘッダーを取得することもできます。
$response = Http::get('https://www.example.co.jp/');
echo $response->header('Content-Type');
Cookieの制御(取得・設定・編集・削除)
cookies
メソッドを使用することで、Cookieの制御を行うことができます。cookiesメソッドはGuzzleHttp\Cookie\CookieJar
オブジェクトを返します。
$response = Http::get('https://www.example.co.jp/');
$cookies = $response->cookies();
GuzzleHttp\Cookie\CookieJar
オブジェクトはgetCookieByName
メソッドを使用して、特定のCookie名の情報を取得することができます。 getCookieByNameメソッドはGuzzleHttp\Cookie\SetCookie
オブジェクトを返します。
$response = Http::get('https://www.example.co.jp/');
// Cookie名"foo"の情報を取得
$cookie = $response->cookies()->getCookieByName('foo');
GuzzleHttp\Cookie\CookieJar
オブジェクトはforeach
文で繰り返すこともできます。
$response = Http::get('https://www.example.co.jp/');
foreach ($response->cookies() as $cookie) {
...
}
GuzzleHttp\Cookie\SetCookie
オブジェクトは、各Cookieの情報の取得と設定するメソッドが用意されています。
メソッド | 戻り値の型 | 引数の型 | 説明 | コード例 |
---|---|---|---|---|
getName() |
string | Cookie名を取得しします。 | $result = $cookie->getName(); |
|
getValue() |
string | 値を取得します。 | $result = $cookie->getValue(); |
|
getDomain() |
string | ドメインを取得します。 | $result = $cookie->getDomain(); |
|
getPath() |
string | パスを取得します。 | $result = $cookie->getPath(); |
|
getMaxAge() |
int | 有効期限(秒数)を取得します。 | $result = $cookie->getMaxAge(); |
|
getExpires() |
int | 有効期限(日数)を取得します。 | $result = $cookie->getExpires(); |
|
getSecure() |
bool | セキュアかを取得します。 | $result = $cookie->getSecure(); |
|
getDiscard() |
bool | 破棄されたCookieかを取得します。 | $result = $cookie->getDiscard(); |
|
getHttpOnly() |
bool | JavaScriptからのCookieのアクセスを禁止しているかを取得します。 | $result = $cookie->getHttpOnly(); |
|
setName(...) |
string | Cookie名を設定します。 | $cookie->setName('foo'); |
|
setValue(...) |
string | 値を設定します。 | $cookie->setValue('abc'); |
|
setDomain(...) |
string | ドメインを設定します。 | $cookie->setDomain('www2.example.co.jp'); |
|
setPath(...) |
string | パスを設定します。 | $cookie->setPath('/foo/bar/'); |
|
setMaxAge(...) |
int | 有効期限(秒数)を設定します。 | $cookie->setMaxAge(1); |
|
setExpires(...) |
int | 有効期限(日数)を設定します。 | $cookie->setExpires(1000); |
|
setSecure(...) |
bool | セキュアを有効にするかどうかを設定します。 | $cookie->setSecure(true); |
|
setDiscard(...) |
bool | Cookieを破棄するかを設定します。 | $cookie->setDiscard(true); |
|
setHttpOnly(...) |
bool | JavaScriptからのCookieのアクセスを禁止するかを設定します。 | $cookie->setHttpOnly(true); |
|
matchesPath(...) |
bool | string | 引数のパスがCookieのパスに一致するかどうかを判定します。 | $result = $cookie->matchesPath('/'); |
matchesDomain(...) |
bool | string | 引数のドメインがCookieのドメインに一致するかどうかを判定します。 | $result = $cookie->matchesDomain('www.example.co.jp'); |
isExpired() |
bool | 有効期限を迎えているかを判定します。 | $result = $cookie->isExpired(); |
$response = Http::get('https://www.example.co.jp/');
// Cookieを全て取得
$cookies = $response->cookies();
// 特定のCookie名に一致する情報を取得
$cookie = $cookies->getCookieByName('foo');
// 設定または変更
$cookie->setValue('abc');
// パスの判定
if ($cookie->matchesPath('/')) {
...
}
リクエストのステータス情報を取得
handlerStats
メソッドを使用することで、リクエストのステータス情報を取得することができます。例えば、リクエストしてから通信完了までの時間やダウンロードの容量などを取得することができます。
$response = Http::get('https://www.example.co.jp/');
$stats = $response->handlerStats();
echo $stats['total_time'];
複数のURLを同時にリクエスト
HTTPクライアントのPool
を使用することで、複数のURLを同時にリクエストすることができます。 Illuminate\Http\Client\Pool
を読み込み、Http::pool
メソッドの引数で処理する関数を指定、戻り値としてリクエストするURLのリクエストするオブジェクトを配列で返します。なお、次のコードで$pool->get
とありますが、post
メソッドやwithHeaders
メソッドなど通常のリクエストのメソッドと同様のメソッドを使用することができます。
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\Pool;
$responses = Http::pool(fn (Pool $pool) => [
$pool->get('https://www.example.co.jp/1'),
$pool->asForm()->post('https://www.example.co.jp/2'),
$pool->withBasicAuth('username', 'password')->get('https://www.example.co.jp/3')
]);
レスポンスはリクエストした分の配列として返します。
if ($responses[0]->ok()) {
...
}
なお、as
メソッドを使用すれば、asメソッドの引数で指定した名前でレスポンスの連想配列として受け取ることもできます。
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\Pool;
$responses = Http::pool(fn (Pool $pool) => [
$pool->as('first')->get('https://www.example.co.jp/1'),
$pool->as('second')->get('https://www.example.co.jp/2'),
$pool->as('third')->get('https://www.example.co.jp/3')
]);
if ($responses['first']->ok()) {
...
}
リダイレクトの追跡
LaravelのHTTPクライアントでは通常、リクエスト先がリダイレクトであった場合、最終的に行き着いた先の情報を取得します。そこでGuzzleのオプションを設定するwithOptions
メソッドを使用することで、その間のリクエストしたURLを追跡することができます。allow_redirects
プロパティのtrack_redirects
プロパティをtrue
に設定することで、レスポンスのヘッダーにX-Guzzle-Redirect-Status-History
とX-Guzzle-Redirect-History
が追加されます。X-Guzzle-Redirect-Status-History
はHTTPステータスコードが格納され、X-Guzzle-Redirect-History
は最初にリクエストしたURLを除く最終的に行き着いた先までのURLが格納されています。
$response = Http::withOptions([
'allow_redirects' => [
'track_redirects' => true
]
])->get('https://www.example.co.jp/');
$headers = $response->headers();
$status = $headers('X-Guzzle-Redirect-Status-History');
$urls = $headers('X-Guzzle-Redirect-History');
if ($status[0] === 200) {
...
}