HTTP リスナリファレンス

HTTP リスナは、HTTP サーバをセットアップして、HTTP 要求を受信したらフローをトリガできるようにするイベントソースです。

ソースが受け入れるメソッド (GET、POST、メソッドのリストなど) や、要求を受け入れるパスを選択できるため、さまざまなフローを使用した要求の転送が可能になります。

要求がリスナによって受け入れられると、対応するフローが HTTP 本文をペイロード、HTTP データを属性 (ヘッダー、クエリパラメータなど) としてトリガされます。

HTTP リスナでは、フローの実行終了後、実行が成功かどうかに基づいて HTTP 応答をカスタマイズできます。たとえば、異なる状況コードを返すことができます。

HTTP リスナ設定

HTTP リスナを使用するには、設定と対応する接続を宣言する必要があります。この宣言により、要求をリスンする HTTP サーバが確立されます。

さらに、ベースパスを設定してすべてのリスナに適用できます。

<http:listener-config name="HTTP_Listener_config" basePath="api/v1">
  <http:listener-connection host="0.0.0.0" port="8081" />
</http:listener-config>

HTTP リスナ接続

この接続では、サーバがセットアップされるホストとポート、および使用するプロトコル (通常の接続には HTTP、TLS 接続には HTTPS) が定義されます。

HTTPS を介したセキュアな接続を可能にするには、接続に TLS コンテキストを定義し、サーバのキーストアを指定する必要があります。相互認証が必要な場合は トラストストアも指定する必要があります。詳細は、「TLS Configuration」(TLS 設定) を参照してください。

<http:listener-connection host="0.0.0.0" port="8081" protocol="HTTPS">
  <tls:context>
    <tls:trust-store path="keystore.jks" password="MyP455W0rD"/>
  </tls:context>
</http:listener-connection>
=== プロジェクトを CloudHub にデプロイするには、ホストを 0.0.0.0 に設定する必要があります。これにより、マシン上のすべてのインターフェース上でリスンするための接続がセットアップされます。

テスト目的でローカルにデプロイする場合は、ホストを localhost に設定することをお勧めします。そうすることで、ローカルに生成された要求のみが受信され、アプリケーションが外部の脅威から攻撃を受けにくくなります。 ===

より高度な設定では、接続が永続的かどうかも定義できます。永続的ではない場合、タイムアウトが設定されます。

HTTP Listener (HTTP リスナ)

HTTP リスナは、フロー内のイベントソースとして設定され、使用する設定と、要求をリスンするパスを参照する必要があります。

<flow name="http-triggered-flow">
  <http:listener path="/" config-ref="HTTP_Listener_config"/>
  <set-payload value="Help! I've been triggered!"/>
</flow>

HTTP 要求がリスナと一致すると、その要求データを使用してフローがトリガされます。本文はペイロードとして設定され、要求行からヘッダーまでその他すべてのデータは属性として反映されます。 トリガされたフローが完了すると、HTTP リスナはその結果を使用して適切な HTTP 応答を生成します。

パス

HTTP リスナのパスは、静的 (完全一致が必要) にすることも、機能のプレースホルダにすることもできます。プレースホルダは、ワイルドカード (*) (比較対象の一部または全部と一致) にすることも、パラメータ ({param}) (一部または全部と一致するだけでなく、URI パラメータマップ上のそれらの値も取得) にすることもできます。

次のパスの例では、3 つのリスナが api/v1 を確立する設定をベースパスとして使用しています。

  • account/mulesoft/main-contact: パス要求 http://awesome-company.com/api/v1/account/mulesoft/main-contact とのみ完全一致します。

  • account/{accountId}/main-contact: 類似の構造を持つすべてのパス要求 (http://awesome-company.com/api/v1/account/salesforce/main-contact など) と一致し、salesforceaccountId の値として保存します。

  • account/{accountId}/*: main-contact とは異なるすべてのパス要求 (http://awesome-company.com/api/v1/account/mulesoft/users など) と一致し、mulesoftaccountId の値として保存します。

パスの末尾にワイルドカードを使用すると、未処理のリソースへの要求を取得してより適切なエラーメッセージを表示するのに役立ちます。

複数のリスナが定義されている場合、要求は常に最も具体的なリスナに転送されます。そのため、前の例では accountId: mulesoft とサフィックス main-contact を含む要求は最初のリスナで処理され、異なる accountId 値を含む要求は、3 番目ではなく 2 番目のリスナによって処理されます。

メソッドについて

要求は、受信した HTTP メソッドに基づいて転送することもできます。デフォルトでは、リスナはすべてのメソッドを処理しますが、これらを選択したメソッド (カスタムメソッドを含む) に制限できます。次の例では、GETPOST、および PUT 要求は異なるフローに転送されます。 これは、データの表示を制限する場合に便利です。特定のユーザにデータの表示を許可し、数人のユーザにのみ変更を許可することができます。

<flow name="main-contact-write">
  <http:listener path="account/{accountId}/main-contact" allowedMethods="POST, PUT" config-ref="HTTP_Listener_config"/>
  <!-- validate user permissions -->
  <!-- store or update main contact for accountId -->
</flow>

<flow name="main-contact-read">
  <http:listener path="account/{accountId}/main-contact" allowedMethods="GET" config-ref="HTTP_Listener_config"/>
  <!-- fetch main contact for accountId -->
</flow>

<flow name="main-contact-general">
  <http:listener path="account/{accountId}/main-contact" config-ref="HTTP_Listener_config"/>
  <set-payload value="#['The main contact resource does not support ' ++ attributes.method ++ ' requests.']"
</flow>

複数のリスナが定義されている場合、要求はメソッドと最初に一致したリスナに転送されるため、デフォルトのリスナは常に最後に定義する必要があります。

HTTP 要求から Mule メッセージへ

メソッド、要求パス、クエリ、および URI パラメータなど HTTP 要求行からのデータとヘッダーはすべてトリガされたフロー内で属性として使用できます。 一方、本文と Content-Type ヘッダーは、ペイロードとその MIME タイプのセットアップに使用されます。これにより、他のコンポーネントがペイロードの MIME タイプを検査できます。たとえば、DataWeave では HTTP ペイロードを使用するのに入力情報を必要としません。 さらに、X-Correlation-ID または MULE_CORRELATION_ID (Mule 3 との相互運用目的) ヘッダーが存在する場合、トレーサビリティ目的でメッセージの相関関係 ID の設定に使用されます。

次の HTTP 要求を考えてみます。

POST api/v1/account/salesforce/main-contact?overwrite=true&notify=jane.doe&notify=admin HTTP/1.1
Host: localhost:8081
Content-Type: application/json
Content-Length: 166
X-Correlation-ID: 9cf32672-4f0b-4e8b-b988-40c13aae85b4

{
  "name": "John",
  "surname": "Doe",
  "role": "Senior Vice President",
  "organization": "Marketing",
  "phone": 701222369,
  "email": "john.doe@salesforce.com"
}

メッセージの相関関係 ID は 9cf32672-4f0b-4e8b-b988-40c13aae85b4 で、そのペイロードは次の JSON です。

{
  "name": "John",
  "surname": "Doe",
  "role": "Senior Vice President",
  "organization": "Marketing",
  "phone": 701222369,
  "email": "john.doe@salesforce.com"
}

#[payload.name ' ' payload.surname] のような式は John Doe を返します。これは、DataWeave が正しく JSON データを解釈しているためです。

メッセージには以下のような属性があります。

  • method: POST

  • listenerPath: api/v1/account/{accountId}/main-contact

  • requestPath: api/v1/account/salesforce/main-contact

  • relativePath: account/salesforce/main-contact

  • queryParams: エントリ overwrite ⇒ truenotify ⇒ jane.doenotify ⇒ admin を含む、マルチマップ

  • uriParams: accountId ⇒ salesforce を含むマップ

  • headers: エントリ`host ⇒ localhost:8081`、content-type ⇒ application/jsoncontent-length ⇒ 166x-correlation-id ⇒ 9cf32672-4f0b-4e8b-b988-40c13aae85b4 を含むマルチマップ

マルチマップは、特定のキーに対して複数の値が許可される点を除き、マップと似ています。単一値セレクタ (.) の使用時は最初の値を返しますが、複数値セレクタ (.*) の使用時はすべての値の取得が許可されます。

#['Received a ' attributes.method ' request for account ' attributes.uriParams.accountId '. The following users are notified: ' ++ (attributes.queryParams.*notify joinBy ', ')] のような式は Received a POST request for account salesforce. The following users are notified: admin, jane.doe を返します。

全 HTTP 要求属性の詳細なリストについては、HTTP ドキュメントリファレンスを参照してください。

マルチパートフォームの例

次の例は、HTML フォームを受信したときの HTTP リスナイベントソースメッセージの操作を示します。

<form action="http://server.com/cgi/handle"
        enctype="multipart/form-data"
        method="post">

    How would you like to identify the logo? <INPUT type="text" name="name"><BR>
    Which is the logo file? <INPUT type="file" name="logo"><BR>
    What is the main color in the logo? <INPUT type="text" name="color"><BR>
    <INPUT type="submit" value="Send"> <INPUT type="reset">

</form>

フォーム送信時に生成された HTTP 要求はマルチパートになります。

POST /api/v1/account/mulesoft/logo HTTP/1.1
Content-Type: multipart/form-data; boundary=489691234097965980223899
Host: localhost:8081
content-length: 34332

--489691234097965980223899
Content-Disposition: form-data; name="name"

Corporate Logo
--489691234097965980223899
Content-Disposition: form-data; name="logo"; filename="MuleSoft_logo.png"
Content-Type: image/png

.PNG
.
...
IHDR.......L......~.....	pHYs...#...#.x.?v.. .IDATx....q.W.6.....~".N....t....t..#.....LD0T.CF0b..:.3......Q..@...q]U*y\c....
....`%.$....V"H....`%.$....V"H....`%.$....V"H....`%.$....V"H....`%.$....V"H....`%.$....V"H....`%.$....V"H....`%.$....V"H....`%
.$....V"H....`%.$....V"H....`%.$....V"H....`%.$....V"H....`%.$....V"H....`%.$....^6.......|..P.....IEND.B`.
--489691234097965980223899
Content-Disposition: form-data; name="color"

blue
--489691234097965980223899--

各項目は parts オブジェクトを使用して名前または項目番号でアクセスできます。たとえば、2 つ目のパートは payload.parts.logo または payload.parts[1] でアクセスできます。後者は、名前が指定されない場合に便利です。 各パート内で、そのコンテンツとヘッダーにアクセスできます。たとえば、payload.parts.color.contentblue を返し、payload.parts.logo.headers.'Content-Type'application/png を返します。 非常に一般的なシナリオは、パートのファイル名の取得です。そのため、Content-Disposition ヘッダーは解析されて payload.parts.logo.headers.'Content-Disposition'.filename のような式を許可します。この場合は MuleSoft_logo.png が返されます。

マルチパートコンテンツの読み取りと書き込みについての詳細は、「DataWeave でサポートされる形式」を参照してください。

HTTP 応答について

トリガされたフローの実行が完了すると、結果が返されてリスナは応答を提供できるようになります。フローが正常に実行された場合は通常の応答が返されますが、フローがエラーで終了した場合はエラー応答が返されます。 デフォルトでは、通常の応答は 200 状況コードと共に本文としてメッセージペイロードを返し、エラー応答は 500 状況コードと共に本文としてフローエラーの説明を返します。これらの応答は次の情報を指定することでカスタマイズできます。

  • 状況コード

  • 理由を示す語句

  • ヘッダーマルチマップ

  • Body

DataWeave を使用して各パラメータを生成でき、変数を使用してフローからデータを反映できます。

次の例では、アカウントのロゴを保存するためのエンドポイントが定義されます。

  1. 正常に保存されると、201 CreatedCorporate Logo has been stored as a mulesoft logo などの本文と一緒に返されます。

  2. 保存に失敗すると、状況コードは errorCode 変数 (使用可能な場合) で定義されるか、デフォルトで 500 になります。

  3. カスタムヘッダーも追加されます (X-Time)。

  4. 本文 (Corporate Logo could not be stored など) が返されます。

  5. たとえば、ロゴの保存時に CONNECTIVITY エラーがある場合、返される状況コードは 504、他のエラーはすべて 500 になります。

エラー応答の理由を示す語句が定義されていないと、コネクタは状況コードに基づいて定義を試みます。そのため、上記で説明したシナリオでは Gateway Timeout または Internal Server Error が返されます。
<flow name="store-logo">
  <http:listener config-ref="HTTP_Listener_config" path="/account/{accountId}/logo">
    <http:response statusCode="201" reasonPhrase="Created"> // 1
      <http:body ><![CDATA[#[output text/plain --- vars.logoName ++ ' has been stored as a ' ++ vars.accountId ++ ' logo.']]]></http:body>
    </http:response>
    <http:error-response statusCode="#[vars.errorCode default 500]"> // 2
      <http:body ><![CDATA[#[vars.logoName ++ ' could not be stored.']]]></http:body> // 3
      <http:headers ><![CDATA[#[
        output application/java
        ---
        {
          "X-Time" : "50s" // 4
        }
      ]]]></http:headers>
    </http:error-response>
  </http:listener>
  <set-variable variableName="logoName" value="#[payload.parts.name.content]"
  mimeType="text/plain"/>
  <set-variable variableName="accountId" value="#[attributes.uriParams.accountId]"
  mimeType="text/plain"/>
  <!-- store logo -->
  <error-handler >
    <on-error-propagate type="CONNECTIVITY"> // 5
      <set-variable variableName="errorCode" value="504"/>
    </on-error-propagate>
  </error-handler>
</flow>

HTTP ストリーミングモード

応答本文の処理時、HTTP コネクタは、送信するデータのサイズが明らかではない場合はデータの種類を考慮し、chunked エンコードを使用します (サイズ情報のないストリームとみなす)。この動作は、responseStreamingMode オプションを使用して変更できます。

  • AUTO (自動) (デフォルト): 本文のサイズが定義されている場合、リスナは Content-Length エンコードを使用します。それ以外の場合は Transfer-Encoding: chunked を使用します。

  • ALWAYS (常時): 存在するサイズデータに関係なく Transfer-Encoding: chunked を使用します。

  • NEVER (なし): Content-Length エンコードを使用し、必要に応じてストリームをコンシュームしてデータサイズを判定します。

次の例では、アカウントの主連絡先は常に Content-Length エンコードを使用して返されます。

<flow name="main-contact-read">
  <http:listener path="account/{accountId}/main-contact" allowedMethods="GET" responseStreamingMode="NEVER" config-ref="HTTP_Listener_config"/>
  <!-- fetch main contact for accountId -->
</flow>

Was this article helpful?

💙 Thanks for your feedback!

Edit on GitHub