検索

12.2. Node.js 関数の開発

download PDF

Node.js 関数プロジェクトを作成 したら、指定のテンプレートを変更して、関数にビジネスロジックを追加できます。これには、関数呼び出しと返されるヘッダーとステータスコードの設定が含まれます。

12.2.1. 前提条件

12.2.2. Node.js 関数テンプレート構造

Knative (kn) CLI を使用して Node.js 関数を作成すると、プロジェクトディレクトリーは典型的な Node.js プロジェクトのようになります。唯一の例外は、関数の設定に使用される追加の func.yaml ファイルです。

http および event トリガー関数のテンプレート構造はいずれも同じです。

テンプレート構造

.
├── func.yaml 1
├── index.js 2
├── package.json 3
├── README.md
└── test 4
    ├── integration.js
    └── unit.js

1
func.yaml 設定ファイルは、イメージ名とレジストリーを判断するために使用されます。
2
プロジェクトに関数を 1 つエクスポートする index.js ファイルを追加する必要があります。
3
テンプレート package.json ファイルにある依存関係に限定されるわけではありません。他の Node.js プロジェクトと同様に、別の依存関係を追加できます。

npm 依存関係の追加例

npm install --save opossum

デプロイメント用にプロジェクトをビルドすると、これらの依存関係は作成したランタイムコンテナーイメージに含まれます。

4
統合およびテストスクリプトは、関数テンプレートに含まれます。

12.2.3. Node.js 関数の呼び出しについて

Knative (kn) CLI を使用して関数プロジェクトを作成する場合に、CloudEvents に応答するプロジェクト、または単純な HTTP 要求に応答するプロジェクトを生成できます。Knative の CloudEvents は HTTP 経由で POST 要求として転送されるため、関数タイプはいずれも受信 HTTP イベントをリッスンして応答します。

Node.js 関数は、単純な HTTP 要求で呼び出すことができます。受信要求を受け取ると、関数は context オブジェクトで最初のパラメーターとして呼び出されます。

12.2.3.1. Node.js コンテキストオブジェクト

関数は、context オブジェクトを最初のパラメーターとして渡して呼び出されます。このオブジェクトは、受信 HTTP 要求情報へのアクセスを提供します。

この情報には、HTTP リクエストメソッド、リクエストと共に送信されたクエリー文字列またはヘッダー、HTTP バージョン、およびリクエスト本文が含まれます。CloudEvent を含む受信リクエストは、CloudEvent の受信インスタンスをコンテキストオブジェクトに添付し、context.cloudevent を使用してアクセスできるようにします。

12.2.3.1.1. コンテキストオブジェクトメソッド

context オブジェクトには、データの値を受け入れ、CloudEvent を返す cloudEventResponse() メソッドが 1 つあります。

Knative システムでは、サービスとしてデプロイされた関数が CloudEvent を送信するイベントブローカーによって呼び出される場合に、ブローカーが応答を確認します。応答が CloudEvent の場合、このイベントはブローカーによって処理されます。

コンテキストオブジェクトメソッドの例

// Expects to receive a CloudEvent with customer data
function handle(context, customer) {
  // process the customer
  const processed = handle(customer);
  return context.cloudEventResponse(customer)
    .source('/handle')
    .type('fn.process.customer')
    .response();
}

12.2.3.1.2. CloudEvent data

受信要求が CloudEvent の場合は、CloudEvent に関連付けられたデータがすべてイベントから抽出され、2 番目のパラメーターとして提供されます。たとえば、以下のように data プロパティーに JSON 文字列が含まれる CloudEvent が受信されると、以下のようになります。

{
  "customerId": "0123456",
  "productId": "6543210"
}

呼び出されると、context オブジェクトの後の関数の 2 番目のパラメーターは、customerId プロパティーと productId プロパティーを持つ JavaScript オブジェクトになります。

署名の例

function handle(context, data)

この例の data パラメーターは、customerId および productId プロパティーが含まれる JavaScript オブジェクトです。

12.2.3.1.3. 任意のデータ

関数は CloudEvents だけでなく任意のデータを受信できます。たとえば、任意のオブジェクトを本文に指定した POST を使用して関数を呼び出すことができます。

{
  "id": "12345",
  "contact": {
    "title": "Mr.",
    "firstname": "John",
    "lastname": "Smith"
  }
}

この場合、関数を次のように定義できます。

function handle(context, customer) {
  return "Hello " + customer.contact.title + " " + customer.contact.lastname;
}

関数に連絡先オブジェクトを指定すると、次の出力が返されます。

Hello Mr. Smith
12.2.3.1.4. サポートされるデータタイプ

CloudEvents には、JSON、XML、プレーンテキスト、バイナリーデータなど、さまざまなデータ型を含めることができます。これらのデータ型は、それぞれの形式で関数に提供されます。

  • JSON データ: JavaScript オブジェクトとして提供されます。
  • XML データ: XML ドキュメントとして提供されます。
  • プレーンテキスト: 文字列として提供されます。
  • バイナリーデータ: Buffer オブジェクトとして提供されます。
12.2.3.1.5. 関数内の複数のデータ型

Content-Type ヘッダーをチェックし、それに応じてデータを解析することで、関数がさまざまなデータ型を処理できることを確認します。以下に例を示します。

function handle(context, data) {
  if (context.headers['content-type'] === 'application/json') {
    // handle JSON data
  } else if (context.headers['content-type'] === 'application/xml') {
    // handle XML data
  } else {
    // handle other data types
  }
}

12.2.4. Node.js 関数の戻り値

関数は、有効な JavaScript タイプを返すことも、戻り値を持たないこともできます。関数に戻り値が指定されておらず、失敗を指定しないと、呼び出し元は 204 No Content 応答を受け取ります。

関数は、CloudEvent または Message オブジェクトを返してイベントを Knative Eventing システムにプッシュすることもできます。この場合、開発者は CloudEvent メッセージング仕様を理解したり実装したりする必要はありません。返された値からのヘッダーおよびその他の関連情報は抽出され、応答で送信されます。

function handle(context, customer) {
  // process customer and return a new CloudEvent
  return new CloudEvent({
    source: 'customer.processor',
    type: 'customer.processed'
  })
}

12.2.4.1. プリミティブ型を返す

関数は、文字列、数値、ブール値などのプリミティブを含む、任意の有効な JavaScript 型を返すことができます。

文字列を返す関数の例

function handle(context) {
  return "This function Works!"
}

この関数を呼び出すと、次の文字列が返されます。

$ curl https://myfunction.example.com
This function Works!

数値を返す関数の例

function handle(context) {
  let somenumber = 100
  return { body: somenumber }
}

この関数を呼び出すと、次の数値が返されます。

$ curl https://myfunction.example.com
100

ブール値を返す関数の例

function handle(context) {
  let someboolean = false
  return { body: someboolean }
}

この関数を呼び出すと、次のブール値が返されます。

$ curl https://myfunction.example.com
false

プリミティブをオブジェクトにラップせずに直接返すと、空の本文を持つ 204 No Content ステータスコードが返されます。

プリミティブを直接返す関数の例

function handle(context) {
  let someboolean = false
  return someboolean
}

この関数を呼び出すと、次の結果が返されます。

$ http :8080
HTTP/1.1 204 No Content
Connection: keep-alive
...

12.2.4.2. 返されるヘッダー

headers プロパティーを return オブジェクトに追加して応答ヘッダーを設定できます。これらのヘッダーは抽出され、呼び出し元に応答して送信されます。

応答ヘッダーの例

function handle(context, customer) {
  // process customer and return custom headers
  // the response will be '204 No content'
  return { headers: { customerid: customer.id } };
}

12.2.4.3. 返されるステータスコード

statusCode プロパティーを return オブジェクトに追加して、呼び出し元に返されるステータスコードを設定できます。

ステータスコード

function handle(context, customer) {
  // process customer
  if (customer.restricted) {
    return { statusCode: 451 }
  }
}

ステータスコードは、関数で作成および出力されるエラーに対して設定することもできます。

エラーステータスコードの例

function handle(context, customer) {
  // process customer
  if (customer.restricted) {
    const err = new Error(‘Unavailable for legal reasons’);
    err.statusCode = 451;
    throw err;
  }
}

12.2.5. Node.js 関数のテスト

Node.js 関数は、コンピューターに対してローカルでテストできます。kn func create を使用して関数を作成する際に作成されるデフォルトプロジェクトには、簡単なユニットテストおよびインテグレーションテストが含まれる test フォルダーがあります。

前提条件

  • OpenShift Serverless Operator および Knative Serving がクラスターにインストールされている。
  • Knative (kn) CLI がインストールされている。
  • kn func create を使用して関数を作成している。

手順

  1. 関数の test フォルダーに移動します。
  2. テストを実行します。

    $ npm test

12.2.6. liveness および readiness プローブの値の上書き

Node.js 関数の liveness および readiness プローブの値を上書きできます。これにより、関数に対して実行されるヘルスチェックを設定できます。

前提条件

  • OpenShift Serverless Operator および Knative Serving がクラスターにインストールされている。
  • Knative (kn) CLI がインストールされている。
  • kn func create を使用して関数を作成している。

手順

  1. 関数コードで、次のインターフェイスを実装する Function オブジェクトを作成します。

    export interface Function {
      init?: () => any; 1
    
      shutdown?: () => any; 2
    
      liveness?: HealthCheck; 3
    
      readiness?: HealthCheck; 4
    
      logLevel?: LogLevel;
    
      handle: CloudEventFunction | HTTPFunction; 5
    }
    1
    サーバーの起動前に呼び出される初期化関数。この関数はオプションであり、同期する必要があります。
    2
    サーバーの停止後に呼び出される shutdown 関数。この関数はオプションであり、同期する必要があります。
    3
    liveness 関数。サーバーが生きているかどうかを確認するために呼び出されます。この関数はオプションであり、サーバーが稼動している場合は 200/OK を返す必要があります。
    4
    readiness 関数。サーバーがリクエストを受け入れる準備ができているかどうかを確認するために呼び出されます。この関数はオプションであり、サーバーが準備できている場合は 200/OK を返すはずです。
    5
    HTTP リクエストを処理する関数。

    たとえば、以下のコードを index.js ファイルに追加します。

    const Function = {
    
      handle: (context, body) => {
        // The function logic goes here
        return 'function called'
      },
    
      liveness: () => {
        process.stdout.write('In liveness\n');
        return 'ok, alive';
      }, 1
    
      readiness: () => {
        process.stdout.write('In readiness\n');
        return 'ok, ready';
      } 2
    };
    
    Function.liveness.path = '/alive'; 3
    Function.readiness.path = '/ready'; 4
    
    module.exports = Function;
    1
    カスタム liveness 関数。
    2
    カスタム readiness 関数。
    3
    カスタム liveness エンドポイント。
    4
    カスタム readiness エンドポイント。

    Function.liveness.path および Function.readiness.path の代わりに、LIVENESS_URL および READINESS_URL 環境変数を使用してカスタムエンドポイントを指定できます。

    run:
      envs:
      - name: LIVENESS_URL
        value: /alive 1
      - name: READINESS_URL
        value: /ready 2
    1
    liveness パス。ここで /alive に設定されます。
    2
    readiness パス。ここで /ready に設定されます。
  2. 新しいエンドポイントを func.yaml ファイルに追加して、Knative サービスのコンテナーに適切にバインドされるようにします。

    deploy:
      healthEndpoints:
        liveness: /alive
        readiness: /ready

12.2.7. Node.js コンテキストオブジェクトのリファレンス

context オブジェクトには、関数開発者が利用可能なプロパティーが複数あります。これらのプロパティーにアクセスすると、HTTP 要求に関する情報が提供され、出力がクラスターログに書き込まれます。

12.2.7.1. log

出力をクラスターロギングに書き込むために使用可能なロギングオブジェクトを提供します。ログは Pino logging API に準拠します。

ログの例

function handle(context) {
  context.log.info(“Processing customer”);
}

kn func invoke コマンドを使用して、この関数にアクセスできます。

コマンドの例

$ kn func invoke --target 'http://example.function.com'

出力例

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"Processing customer"}

ログレベルは、fatalerrorwarninfodebugtrace、または silent のいずれかに設定できます。これを実行するには、config コマンドを使用してこれらの値のいずれかを環境変数 FUNC_LOG_LEVEL に割り当てて、logLevel の値を変更します。

12.2.7.2. query

要求のクエリー文字列 (ある場合) をキーと値のペアとして返します。これらの属性はコンテキストオブジェクト自体にも表示されます。

サンプルクエリー

function handle(context) {
  // Log the 'name' query parameter
  context.log.info(context.query.name);
  // Query parameters are also attached to the context
  context.log.info(context.name);
}

kn func invoke コマンドを使用して、この関数にアクセスできます。

コマンドの例

$ kn func invoke --target 'http://example.com?name=tiger'

出力例

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"tiger"}

12.2.7.3. ボディー

要求ボディー (ある場合) を返します。要求ボディーに JSON コードが含まれている場合は、属性が直接利用できるように解析されます。

ボディーの例

function handle(context) {
  // log the incoming request body's 'hello' parameter
  context.log.info(context.body.hello);
}

curl コマンドを使用してこの関数を呼び出すことができます。

コマンドの例

$ kn func invoke -d '{"Hello": "world"}'

出力例

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"world"}

12.2.7.4. ヘッダー

HTTP 要求ヘッダーをオブジェクトとして返します。

ヘッダーの例

function handle(context) {
  context.log.info(context.headers["custom-header"]);
}

kn func invoke コマンドを使用して、この関数にアクセスできます。

コマンドの例

$ kn func invoke --target 'http://example.function.com'

出力例

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"some-value"}

12.2.7.5. HTTP 要求

方法
HTTP 要求メソッドを文字列として返します。
httpVersion
HTTP バージョンを文字列として返します。
httpVersionMajor
HTTP メジャーバージョン番号を文字列として返します。
httpVersionMinor
HTTP マイナーバージョン番号を文字列として返します。

12.2.8. 次のステップ

Red Hat logoGithubRedditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

© 2024 Red Hat, Inc.