名もなき未知

エンジニアリングとか、日常とかそういうのをまとめる場所。

GuzzleでHTTP通信してみる

PHPでモダンな感じで HTTP 通信するなら何?みたいな話をいつだったかしていました。

どうやら Guzzle が流行ってるらしい、とのことだったので、試しに Authorizationリクエストヘッダも含めた HTTP 通信をしてみることにしました。

なお、5年ぶりくらいに PHP を触ったので、連想配列を書くだけでも苦戦してました(他言語の書き方に慣れすぎたか…)。まあ思い出したけど。

やったこと

まず Docker で Guzzle を入れる

正直ここが一番大変だったといっても過言ではないです。

背景としては、特に普段から PHP を書いていないのでローカルに開発環境は不要と思い、実行環境だけあればよい気持ちになったためです。

Overview — Guzzle Documentation を見ている限りでは、 composer で入れるのが良いらしいですね。

ちょっと調べると composer も Docker Image があることを知りました。やったー。

というわけで下記の2つを使ってマルチステージビルドしました。

というわけで Dockerfile は下記になりました。

FROM php:8.0-fpm-buster

# composer はマルチステージビルドで持ってくる
# refer: https://qiita.com/yatsbashy/items/02bbbebbfe7e5a5976bc
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# composer need git
RUN apt-get update && apt-get install -y git

RUN composer require guzzlehttp/guzzle:^7.0
COPY . .
RUN chmod u+x entrypoint.sh

ENTRYPOINT ["/var/www/html/entrypoint.sh"]
# RUN ["php", "main.php"]

よくわかってないのですが、なぜか WORKDIR が /var/www/html/ になっているので(composerのせいか?) ENTRYPOINT はそこに合わせています(デバッグするときは ENTRYPOINT 外して、雑に exec -it {image_id} bash で入ってデバッグしていた)。

Guzzle でリクエストをする

Qiita の API でも試しに叩いてみることにします。認証しているユーザーを返す API がある GET /authenticated_user のでそれをたたいてみることにします。

基本的には Client を作って、リクエストして、結果を受け取る形です。下記のページを参照に作っていきます。

出来上がったものがこちら。

<?php

require 'vendor/autoload.php';

$token = getenv('QIITA_ACCESS_TOKEN');

$client = new \GuzzleHttp\Client(
    [
        'base_uri' => 'https://qiita.com',
        'timeout' => 2.0,
    ]
);

$headers = [
    'Content-Type' => 'application/json;charset=utf-8',
    'Authorization' => 'Bearer '.$token,
];

$res = $client->request(
    'GET', '/api/v2/authenticated_user', [
        'headers' => $headers
    ]
);

echo $res->getStatusCode()."\n";
echo $res->getHeaderLine('content-type')."\n";
echo $res->getBody()."\n";

token は直打ちするとよろしくないので、環境変数からとる形にしています。

環境変数を渡しつつ実行する

最後に虚無みたいな entrypoint.sh を作っておくことにします。

#!/bin/bash

php main.php

まずはビルドします。

❯ docker build . -t php-practice
Sending build context to Docker daemon  4.608kB
Step 1/7 : FROM php:8.0-fpm-buster
 ---> 4ebd60322a2b
Step 2/7 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
 ---> Using cache
 ---> 49f3a96a6383
Step 3/7 : RUN apt-get update && apt-get install -y git
 ---> Using cache
 ---> 0bd8cb7267ee
Step 4/7 : RUN composer require guzzlehttp/guzzle:^7.0
 ---> Using cache
 ---> ea788036ebab
Step 5/7 : COPY . .
 ---> Using cache
 ---> a5fb0b2fa934
Step 6/7 : RUN chmod u+x entrypoint.sh
 ---> Using cache
 ---> 3db87772286c
Step 7/7 : ENTRYPOINT ["/var/www/html/entrypoint.sh"]
 ---> Using cache
 ---> ee0a466366fd
Successfully built ee0a466366fd
Successfully tagged php-practice:latest

で、うまくいったら run します。 ENTRYPOINT を指定してるし、 run したら消していいはずなので --rm つけてます。

トークンは Qiita のユーザーページから発行してください。

❯ docker run  -e QIITA_ACCESS_TOKEN=${PEKOPEKO} -t php-practice --rm
200
application/json; charset=utf-8
{"description":"えんじにゃー。ぷりぷりかしこま。Pythonしかできない。","facebook_id":"","followees_count":19,"followers_count":21,"github_login_name":"yumechi","id":"yumechi","items_count":9,"linkedin_id":"","location":"東京","name":"Senri Yumechi","organization":"","permanent_id":72473,"profile_image_url":"ほげほげ","team_only":false,"twitter_screen_name":"__yumechi","website_url":"https://namonakimichi.hatenablog.com/","image_monthly_upload_limit":104857600,"image_monthly_upload_remaining":104857600}

ちょっとやばそうなところは雑にマスクしましたが、無事に実行できました。やったね。

まとめ

やっぱり Docker ! マルチステージビルド ! はいいですね。ローカル環境が汚れにくいし、再現性もあっていい感じです。

環境変数も実行時に入れることによって、挙動を制御することもできるので、活用していきたいですね。

そして Guzzle ですが、ヘッダーの設定、リクエストの受付、そのあたり見ても他の言語の通信と大差ない感じで扱えて非常に楽でした。

cURL でリクエストする方法も知っていますが、 Guzzle にはどうやらまだ使いこなせていない機能でいいもんがたくさんありそうです。

PHP でなにかつくるかはわかりませんが、頭の片隅には入れておこうと思います。

追記

静的解析も少しやったんだった。この記事を参考にした。

PHPの静的解析いろいろ - Qiita

php -l <filename> はガバガバなので何も出なかった。

phpcs を試して多少おこられたので直しました( main.php はこれに従って直した)。

ほかについては試してませんが、 CI とか回すときにコードチェックもついでにできるようになるといいかもしれないですね (希望的観測)。

これで今度こそ終わり。