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-HistoryX-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) {
    ...
}

参考リンク