Perl Hackers Hub

第70回Raisin入門 ―Rest APIマイクロフレームワークを使ってみよう!(2)

前回の(1)こちらから。

パラメータの操作

(2)の本節では、パラメータの操作方法を説明します。

paramsでパラメータの検証

パラメータを検証するにはparamsを、強制オプションを定義するにはrequiresを使います。

次の例では、ユーザーを追加するAPIにusersパラメータを必須として定義しています。

raisin.pl
use Types::Standard qw(HashRef Str);
(省略)
params(
    requires(
        'users',
        type => HashRef,
        desc => 'User object',
        group {
            requires(
                'name',
                type => Str,
                desc => 'User Name'
            ),
            optional(
                'email', type => Str,
                default => undef,
                regex => qr/.+\@.+/,
                desc => 'User email'
            ),
    }),
);
post sub { ... }

必須ではないパラメータはoptionalで宣言できます。regexを使うと正規表現で形式を指定できます。

空のJSONをPOSTすると、usersがないためエラーを返却できていることが確認できます。エラーメッセージも自動で返却されます。

$ curl -X POST -H 'Content-Type: application/json' \
  http://localhost:5000/users -d '{}'
- Invalid Parameters

エラーログにも警告メッセージが自動で表示されます。ステータスコード400(Bad Request)で返却できていることを確認できます。

WARN 2021-08-08T04:37:52.787 `users` is required
127.0.0.1 - - [09/Aug/2021:15:10:16 +0900]
"POST /users HTTP/1.1" 400 25 "-" "curl/7.64.1"

include_missingですべてのパラメータの取得

すべてのパラメータを取得するにはinclude_missingを使います。デフォルトでは値のないパラメータは取得できないため注意してください。

raisin.pl
(省略)
post sub {
    my $all_params = include_missing(shift);
};

route_paramでルートパラメータの取得

ルートパラメータを取得するにはroute_paramを使用します。何も指定しない場合はどんな値でも入るため、requiresを使用した強制オプションの定義を推奨します。

raisin.pl
(省略)
use HTTP::Status qw(:constants);

my %USERS = (
    1 => {
        name => 'Sample Taro',
        email => 'taro@sample.com',
    },
    2 => {
        name => 'Sample Jiro',
        email => 'jiro@sample.com',
    },
);
(省略)
params requires(
    'id',
    type => Int,
    desc => 'User ID'
);
route_param 'id' => sub {
    get sub {
        my $params = shift;
        $USERS{ $params->{id} };
    };

    del sub {
        my $params = shift;
        delete $USERS{ $params->{id} };
        res->status(HTTP_NO_CONTENT);
        undef;
    };
}

実行タイミングの操作

任意のタイミングで処理を実行するにはhooksを使います。実行される順番から、beforebefore_validationafter_validationafterの4種が存在します。

beforeでAPIの実行前に処理実行

APIの実行前に処理を実行したい場合はbeforebefore_validationを使います。beforeのあとにbefore_validationが実行されます。実行タイミング以外の違いはありません。

次の例では、ログを出力できるプラグインRaisin::Loggerを使って、APIの実行時にリクエスト内容をログに出力しています。

raisin.pl
(省略)
plugin 'Logger', fallback => 1;

before sub {
  my $self = shift;
  app->log( debug => $self->req->method . "\t" .
  $self->req->path );
};

APIを実行すると、ログに出力されていることが確認できます。

DEBUG 2021-08-08T04:15:21.976 GET     /users/1

afterでAPIの実行後に処理実行

APIの実行後に処理を実行したい場合はafterafter_validationを使います。after_validationのあとにafterが実行されます。実行タイミング以外の違いはありません。beforeとは違ってAPIが正常終了しないと呼び出されない点に注意してください。

次の例では、APIの実行完了時に成功メッセージをログに出力しています。

raisin.pl
(省略)
after sub {
    app->log( debug => "Success" );
};

存在しないエンドポイントを指定してAPIが正常に終了しなかった場合は、ログに出力されていないことが確認できます。

DEBUG 2021-08-19T07:13:35.629 GET       /not_exist_path
127.0.0.1 - - [19/Aug/2021:07:13:35 +0900] "GET /not_exi
st_path HTTP/1.1" 404 2 "-" "curl/7.64.1"

便利モジュール

本節では、Raisinを使ううえで便利なモジュールを説明します。

Raisin::Plugin::SwaggerでAPIドキュメントの作成

HTML形式でドキュメントを生成できるSwagger UIのためのJSONを生成するには、Raisin::Plugin::Swaggerを使います。生成されたJSONをSwagger UIで読み込むと、ドキュメントを自動生成できます。

使用するには、APIの中でSwaggerのプラグインを有効にします。

plugin 'Swagger';

/swagger.jsonにアクセスすると、Swagger UI用のJSONが返ってくることが確認できます。このJSONをSwagger UIで読み込むと、図1のようにAPIドキュメントを確認できます。

図1 Swagger UI
図1 Swagger UI

Plack::TestでAPIのテストの実施

RaisinはPlackに準拠しているため、Plack::Testモジュールでテストを行えます。

先ほどのAPIのテストの例を記述します。

test.pl
use Test::More;
use Plack::Test;
use HTTP::Request::Common;
use Plack::Loader;
use Plack::Util();
use JSON qw/decode_json/;

my $app = Plack::Util::load_psgi('./raisin.pl');

test_psgi $app, sub {
    my $cb = shift;
    my $req = HTTP::Request->new(GET => '/users/1');
    my $res = $cb->($req);
    my $json_data = decode_json($res->content);

    is $res->code, 200;
    is $json_data->{name}, 'Hoge';
};

done_testing;

レスポンスコードのチェックとJSONの文字列をチェックします。

$ perl test.psgi
ok 1
not ok 2
#   Failed test at test.psgi line 19.
#          got: 'Sample Taro'
#     expected: 'Hoge'
1..2
# Looks like you failed 1 test of 2.

失敗したテストでは、期待値と実際に受け取った値を確認できます。

まとめ

本稿では、Rest APIマイクロフレームワークであるRaisinを使ったRest APIの作成方法について解説しました。Raisinはマイクロフレームワークながら、APIドキュメントの生成などAPI開発に欠かせない機能を兼ね備えている強力なフレームワークです。

本稿で紹介したものは一部にすぎません。セッション管理や、Mooseと組み合わせると型制約の使用もできます。みなさんも、PerlでRest APIを作成する際はRaisinを試してください。

さて、次回の執筆者は小林謙太さんで、テーマは「ISUCON11の実装から最近のPerlを学ぶ」です。お楽しみに。

WEB+DB PRESS

本誌最新号をチェック!
WEB+DB PRESS Vol.130

2022年8月24日発売
B5判/168ページ
定価1,628円
(本体1,480円+税10%)
ISBN978-4-297-13000-8

  • 特集1
    イミュータブルデータモデルで始める
    実践データモデリング

    業務の複雑さをシンプルに表現!
  • 特集2
    いまはじめるFlutter
    iOS/Android両対応アプリを開発してみよう
  • 特集3
    作って学ぶWeb3
    ブロックチェーン、スマートコントラクト、NFT

おすすめ記事

記事・ニュース一覧