6. リクエスト・レスポンスマッピング

6.1. テンプレート記法

x-proxy ベンダ拡張内のいくつかの箇所では、 FreeMarker のテンプレート記法を使用することができます。

テンプレートは ${...} のフォーマットで記述します。

テンプレートに引き渡される Model はハッシュマップとなっており、内容は以下のとおりとなっています。 テンプレートでこれらの値を参照することができます。

キー 内容 型(Java)
request.pathParams パスパラメータ Map<String,String>
request.queryParams クエリパラメータ Map<String,String>
request.headers リクエストヘッダ (注1) Map<String,String>
response.headers レスポンスヘッダ (注1) Map<String,String>
request.body リクエストボディ全体(注2) String
response.body レスポンスボディ全体(注2) String
request.json JSONパースされたリクエストボディ (注3) Map<String,String>
response.json JSONパースされたレスポンスボディ (注3) Map<String,String>
response.status ステータスコード int
request.contentType リクエスト Content-Type String
response.contentType レスポンス Content-Type String
request.user.id 認証ユーザID(未認証時は空文字列) String
request.user.name 認証ユーザ名(未認証時は空文字列) String
request.user.email 認証ユーザE-mailアドレス(未認証時は空文字列) String
request.sessionToken セッショントークン(未認証時は空文字列) String
request.tenantId テナントID String
request.tenantName テナント名 String
  • 注1) キーとなるヘッダ名はすべて小文字に正規化されます
  • 注2) 本記述は変換前の Content-Type が application/json, application/xml, text/* だった場合にのみ使用できます
  • 注3) 本記述は変換前の Content-Type が application/json だった場合にのみ使用できます

なお、response.* キーの内容はリクエスト変換時には参照できません。 逆に request.* キーの内容はレスポンス変換時にも参照できます。

6.1.1. エスケープ

テンプレート内の文字列は自動ではエスケープされませんので、出力フォーマット(Content-Type) に応じて適宜 FreeMarker のエスケープ directive を指定してください。

  • JSON 文字列("...") 内にテンプレート記述する場合は、json_string を使用してください (例: "${json.msg?json_string}")
  • 出力が HTML/XML 形式の場合はそれぞれ html/xml を使用してください (例: ${json.msg?html})

6.2. リクエストマッピング (HTTP)

リクエストのマッピング(変換規則)は request フィールド内に記述します。 以下に例を示します。

x-proxy:
  method: GET
  uri: http://example.com/
  request:
    headers:
      default: $pass
      mapping:
        Referer: $drop
        Accept: application/json
    queryParams:
      default: $drop
      mapping:
        token: ${request.queryParams.secret}
        query: $pass

以下の3つの設定を記述できます(いずれもオプション)

  • headers: ヘッダの変換規則を記述する
  • queryParams: クエリパラメータの変換規則を記述する
  • body: ボディの変換規則を記述する

6.2.1. ヘッダ変換規則

ヘッダ変換規則は "headers" に記述します。以下2つの設定を記述できます。

  • default: デフォルト変換規則
  • mapping: マッピング規則

mapping には、ヘッダ名をキーに各ヘッダ毎の変換規則を記述します。 以下のいずれかの値を記述できます。省略時は $pass を指定したものとみなされます。

  • $pass : ヘッダをそのまま通過させる
  • $drop : ヘッダを削除する
  • 上記以外: テンプレート記法

default にはマッピング規則に合致しなかったヘッダの変換規則を記述します。 記述方法は mapping と同じく、$pass, $drop, テンプレート記法のいずれかです。

上に示した例では、Referer を削除、Accept を application/json に指定、それ以外のヘッダはすべて通過という規則になっていいます。

制限事項

以下のヘッダはマッピング規則は記述できません(記述しても無視されます)

  • Access-Control-Request-Headers
  • Access-Control-Request-Method
  • Connection
  • Content-Length
  • Content-Transfer-Encoding
  • Host
  • Keep-Alive
  • Origin
  • Trailer
  • Transfer-Encoding
  • Upgrade
  • Via

6.2.2. クエリパラメータ変換規則

クエリパラメータ変換規則は "queryParams" に記述します。 記述方法はヘッダ変換規則と同じです。

6.2.3. ボディ変換規則

ボディ変換規則は "body" に記述します。ボディ変換規則には以下の3種類があります。

  • template: FreeMarker テンプレートによる変換
  • jsonPatch: JSON Patch (RFC 6902) による JSON変換
  • jsonMerge: JSON Merge Patch (RFC 7386) による JSON変換

上記変換は複数同時に指定することも可能です。この場合、上述した順序で変換が適用されます。

template は任意のテキスト(UTF-8)形式のボディに対して適用できます。

jsonPatch/jsonMerge は JSON テキスト(UTF-8)形式のボディに対して適用できます。 (ボディが JSON で無かった場合は、空 JSON ({}) として扱われます)

注意

ボディ変換規則を使用する場合、ボディを一旦すべてメモリ上にロードし変換してから転送する動作となります。 (変換しない場合は、メモリ上にロードせずストリームのまま転送します)。

このため、大容量のボディを変換・転送する場合、メモリを大量に消費しますので注意してください。

注意

ボディ変換規則を定義した場合、Content-Encodingされたリクエストには'400 Bad Request'を返します。 エンティティボディの自動デコードは行いません。 (ただし、'Content-Encoding: identity'の場合を除く。この場合は通常通りにボディ変換を実施します。)

テンプレート変換

"template" フィールドにテンプレート文字列をそのまま記述します。

以下に例を示します (ここでは YAML のヒアドキュメントを利用しています)

x-proxy:
  method: POST
  uri: http://example.com/some/url
  request:
    body:
      template: |
        {
         "reason": "${request.json.msg?js_string}"
        }

なお、template に文字列ではなく JSON を指定している場合は、JSON を文字列に変換してからテンプレートを適用します。 したがって、上記記述は以下のようにも記述できます。

x-proxy:
  method: GET
  uri: http://example.com/some/url
  request:
    body:
      template:
        reason: "${request.json.msg?js_string}"

JSON Patch (RFC 6902)

JSON Patch (RFC 6902) に従って JSON 変換を行います。 以下に例を示します。

x-proxy:
  method: POST
  uri: http://example.com/some/url
  request:
    body:
      jsonPatch:
        - op: add
          path: /reason
          value: "${request.json.msg?js_string}"
        - op: remove
          path: /secret

上記例では、reason フィールドに値を追加し、secret フィールドの値を削除しています。

注意

remove/replace などで、変換元 JSON に存在しない path を指定した場合、 変換エラーとなります。リクエストの変換が失敗した場合は 400 Bad Request、 レスポンスの変換が失敗した場合は 500 Internal Server Error が返却されます。

JSON Merge Patch (RFC 7386)

JSON Merge Patch (RFC 7386) に従って JSON 変換を行います。 JSON Patch よりもシンプルに記述できますが、フィールド名変更(move)、コピー(copy) などの細かい制御はできません。

以下に例を示します。

x-proxy:
  method: POST
  uri: http://example.com/some/url
  request:
    body:
      jsonMerge:
        reason: "${request.json.msg?js_string}"
        secret: null

上記変換規則は前述の JSON Patch の例と同じ処理となります。

6.3. レスポンスマッピング (HTTP)

レスポンスのマッピングは "response" に記述します。以下に例を示します。

x-proxy:
  method: GET
  uri: http://example.com/
  response:
    - 20.:
        status: 200
        headers:
    - .*:
        status: 500
        headers:

レスポンスマッピングは、ステータスコード毎に異なる変換規則を指定できます。

規則は配列で指定します。複数の規則にマッチする場合は、先に指定した規則のほうが優先されます。

注意

バージョン v5 ⇒ v6 で規則の記述形式が変更になりましたので注意してください。 v5 では配列ではありませんでしたが、v6 では優先順位を明確にするため配列となっています。

各規則は、ステータスコードをキー、変換規則(JSONオブジェクト)を値にした JSON オブジェクトとして記述します。

ステータスコードは正規表現で表現します。 上記例では 200系ステータスとそれ以外の2通りで変換規則を記述しています。 なお、合致するステータスコードがなかった場合は、レスポンスはそのままパススルーされます。

各ステータスコード配下には以下の規則を記述できます。すべてオプションです。

  • status: ステータスコード
  • headers: ヘッダ変換規則
  • body: ボディ変換規則

なお、headers と body の変換規則の記述方法はリクエストの場合と同じです。

6.4. ボディマッピング (RabbitMQ)

RabbitMQ の publish/consume については、データボディについて変換を行うことができます。 以下に例を示します。

x-proxy:
  type: amqp-publish
  exchange: exchange1
  routingKey: key1
  confirm: false
  body:
    jsonMerge:
      key1: 12345

"body" キー内に変換規則を記述します。 変換規則の記述方法は HTTP リクエストの場合と同じです。

6.5. 注意事項

以下のいずれかの場合、API Gateway は Body を一旦すべてメモリ上に読み込んでから転送を実施します。

  • Content-Type が application/json, application/xml, text/* だった場合
  • template 変換を指定している場合
  • JSON Patch / JSON Merge Patch を指定している場合

Body のサイズが非常に大きい場合、すべてのデータをメモリ上に読み込んでから転送するため BaaS サーバのメモリを大量に消費します。100MBなど大きいデータを API Gateway で転送する場合は、 上記に該当しないよう注意してください。