PrismでProxyサーバーを構築する

n-ozawan

皆さん、こんにちは。技術開発グループのn-ozawanです。
秋ですね。秋の味覚カボチャは、電子レンジで加熱して調味料で和えれば、カボチャサラダの完成です。

本題です。
前回はPrismでモックサーバーを構築しました。Prismはモックサーバーだけでなく、Proxyサーバーとしても動かすことが出来ます。今回はPrism Proxyについてはお話しします。

Prism Proxy

概要

Prism Proxyはその名の通り、APIサーバーのProxyとして動作します。Prism Proxyは受け取ったリクエストをそのままAPIサーバーへ渡します。その際、APIサーバーから応答があれば、その結果をフロントエンドへ返却します。APIサーバーが501 Not Implementedを返却した場合は、モックサーバーとして動作します。

フロントエンドとバックエンドが並行して開発している場合、完成したAPIだけでもバックエンドと結合したいケースがあります。Prism Proxyはそのような期待に応えます。

例えば新規開発の場合であれば、全てのAPIが完成してから結合すると思い通りに動作せず、思わぬ工数が発生してしまいます。しかし、事前に完成したAPIから結合しながら確認すれば、問題を早期に発見することが出来ます。

例えば改良開発の場合であれば、開発済みのAPIはAPIサーバーで、新規開発分のAPIはモックで動かすことも出来ます。

Prism Proxy を動かしてみる

Prism Proxyを起動してみましょう。以下のコマンドでProxyサーバーを起動します。

npx prism proxy ./openapi.yaml https://www.example.com

(省略)
[1:23:20 PM] › [CLI] ▶  start     Prism is listening on http://127.0.0.1:4010

https://www.example.comにはAPIサーバーへのURLを指定します。

実際にAPIをリクエストしてみましょう。./openapi.yamlの内容は前回を参照してください。APIサーバーには以下が実装されています。

  @Data
  public class User {
    String userId;
    String name;
    Integer age;
  }

  @GetMapping("/api/user/{id}")
  public User getUser(@PathVariable String id) {
    User user = new User();
    user.userId = id;
    user.name = "バックエンド三郎";
    user.age = 12;
    return user;
  }

/api/user/{id}をリクエストすると以下のようになります。

curl -i http://localhost:4010/api/user/1

HTTP/1.1 200 OK
(省略)
{"userId":"1","name":"バックエンド三郎","age":12}

モックで返却したい場合は501応答をする必要がある

Prism Proxyの注意点としては、APIサーバーは必ず501(Not Implemented)を応答しなくてはなりません。例えば、APIサーバーが起動していない場合は、Prism ProxyはAPIサーバーへの接続エラーとして500 Internal Server Errorを応答します。

curl -i http://localhost:4010/api/user/1

HTTP/1.1 500 Internal Server Error
(省略)
{
  "type":"FetchError",
  "title":"request to http://localhost:3020/api/user/hoge failed, reason: connect ECONNREFUSED 127.0.0.1:3020",
  "status":500,
  "detail":""
}

仮にAPIサーバーが起動していたとしても、501以外のエラー応答はそのままフロントエンドへ返されます。例えば、Spring Bootでは、実装していないAPIへのリクエストは404応答を返します。

curl -i http://localhost:4010/api/user/1

HTTP/1.1 404 Not Found
(省略)
{
  "type":"about:blank",
  "title":"Not Found",
  "status":404,"detail":
  "No static resource api/user/hoge.",
  "instance":"/api/user/hoge"
}

必要なAPIには501応答するように予めAPIサーバー側に実装してあげる必要があります。

@GetMapping("/api/user/{id}")
public void getUser(@PathVariable String id) {
  throw new ErrorResponseException(HttpStatus.NOT_IMPLEMENTED);
}

501応答であればモックの内容が返却されます。

curl -i http://localhost:4010/api/user/1

HTTP/1.1 200 OK
(省略)
{"userId":1,"name":"太郎","age":20}

APIサーバーからのレスポンス内容をチェックしたい

PrismをProxyサーバーで動かすと、フロントエンドからのリクエスト内容をチェックしてくれません。代わりに、バックエンドからのレスポンス内容をチェックしてくれます。

例えばuserIdtype: integerと定義しており、APIサーバー側で数値以外を返却したとします。

  @GetMapping("/user/{id}")
  public User getUser(@PathVariable String id) {
    User user = new User();
    user.userId = "hoge";     // API仕様に反する返却値
    user.name = "バックエンド三郎";
    user.age = 12;
    return user;
  }

APIをリクエストしても200応答でレスポンスされますが、npx prism proxyを実行しているターミナルにはエラーが出力されます。これによりAPIサーバー側の不具合を早期に発見することが出来ます。

curl -i http://localhost:4010/api/user/1

HTTP/1.1 200 OK
(省略)
{"userId":"hoge","name":"太郎","age":20}
[2:46:10 PM] ›     [VALIDATOR] ✖  error     Violation: response.body.userId Response body property userId must be integer

画像ファイルなどのバイナリには対応していない

残念ながらAPIサーバーから画像をレスポンスしても、Prism Proxyの何らかの処理にて、画像が壊れます。

おわりに

Prism Proxyは少々クセがあるものの、フロントエンドとバックエンドの開発に十分に寄与してくれるのではないでしょうか。画面で動かしながらAPIの動作確認も行いたい方にお勧めです。

ではまた。

Recommendおすすめブログ