PrismでProxyサーバーを構築する
皆さん、こんにちは。技術開発グループの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サーバーで動かすと、フロントエンドからのリクエスト内容をチェックしてくれません。代わりに、バックエンドからのレスポンス内容をチェックしてくれます。
例えばuserId
はtype: 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の動作確認も行いたい方にお勧めです。
ではまた。