Helidon 2.0 and CORS

原文はこちら。
The original article was written by Tim Quinn (Oracle).
https://medium.com/helidon/helidon-2-0-and-cors-14f34e2b1d17

新たにリリースされたHelidon 2.0から、簡単にCORSサポートをアプリケーションや、Health、Metrics、OpenAPIというHelidonの組み込みサービスに追加できるようになりました。

Helidon
https://helidon.io

ブラウザやその他のよくあるWebクライアントに実装されている、同一オリジンポリシー (same-origin policy) は、あるオリジン(URLスキーム、ホスト、ポート)のページやアプリが他のオリジンのリソースにアクセスすることを制限するものです。

Same Origin Policy
https://www.w3.org/Security/wiki/Same_Origin_Policy

しかし特定のケースでは、この制限を緩和することに意味がある場合があります。クロスオリジンリソース共有 (Cross-origin resource sharing, CORS) は、HTTPヘッダーを使用した標準的なアプローチで、Webクライアントとサーバーが、別のオリジンのリソースに代わって、あるオリジンからのリソースへの管理されたアクセスを許可(または拒否)するように要求するものです。

Fetch
https://www.w3.org/TR/cors/

最新のHelidon 2.0で、Helidon SEやHelidon MPのアプリケーションのエンドポイントや、Health、Metrics、OpenAPI などのHelidon組み込みサービスのエンドポイントにCORSサポートを簡単に追加できるようになりました。

About CORS in Helidon SE
https://helidon.io/docs/latest/#/se/cors/01_introduction
About CORS in Helidon MP
https://helidon.io/docs/latest/#/mp/cors/01_introduction

以下のサンプルアプリはHelidonのgreetingというサンプルアプリに触発されたものです。

Helidon SE CORS Example
https://github.com/oracle/helidon/tree/release-2.0.1/examples/cors
Helidon MP CORS Example
https://github.com/oracle/helidon/tree/release-2.0.1/examples/microprofile/cors

この例では、 http://foo.comhttp://there.com のリソースからのサンプルアプリへのPUT、DELETEアクセスを許可する一方で、その他の全てのオリジンに対してはGETやHEADなどのシンプルなアクセスを許可します。

CORS in Helidon SE

pom.xmlに依存関係を追加します。

<dependency>
  <groupId>io.helidon.webserver</groupId>
  <artifactId>helidon-webserver-cors</artifactId>
</dependency>

コードにCorsSupportインスタンスを作成する

アプリのリソースに必要なCORSの動作を表す、CorsSupportオブジェクトを作成します。2つのCrossOriginConfigオブジェクトを使用しますが、一方はPUTとDELETEアクセス用、もう一方はその他のすべてのアクセス用です。

CorsSupport corsSupport = CorsSupport.builder()
    .addCrossOriginConfig(CrossOriginConfig.builder()
        .allowOrigins("http://foo.com", "http://there.com")
        .allowMethods("PUT", "DELETE")
        .build())
    .addCrossOriginConfig(CrossOriginConfig.create())
        .build();

CorsSupportインスタンスの利用

アプリケーションのパスへのルーティングを構成する、同じregisterメソッドの呼び出しでCorsSupportインスタンスを使います。

return Routing.builder()
    .register(JsonSupport.create())
    .register(health)                  // Health at "/health"
    .register(metrics)                 // Metrics at "/metrics"
    .register("/greet", corsSupport, greetService)
    .build();

アプリケーションのリビルド、再起動でおしまいです。アプリで実際に CORS サポートを確認する簡単な方法を以下でご紹介します。


CORS in Helidon MP

pom.xmlに依存関係を追加します。

<dependency>
  <groupId>io.helidon.microprofile</groupId>
  <artifactId>helidon-microprofile-cors</artifactId>
</dependency>

@CrossOriginアノテーションの利用

JAX-RSリソースクラスで、HTTP OPTIONSリクエスト用のno-opメソッドを追加し、そこに注釈を付けます。

@OPTIONS
@CrossOrigin(
    allowMethods = {"PUT", "DELETE"}, 
    allowOrigins = {"http://foo.com", "http://there.com"})
public void optionsForGreeting() {}

その後、アプリをリビルド、再起動します。


Trying it out (SE and MP)

cURLを使って、アプリのエンドポイントに対するHelidonのCORSサポートを実際に試してみましょう。以下のコードスニペットでは、CORS関連のヘッダーを強調しています。

GETやHEADのような簡単なオペレーションでは、CORSは常のHTTPリクエストにヘッダーを追加するだけです。

curl -i -X GET \
   -H "Origin: http://foo.com" -H "Host: here.com" \
   http://localhost:8080/greet

そのレスポンスは以下のようです。

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json
Date: Thu, 30 Apr 2020 17:25:51 -0500
Vary: Origin
connection: keep-alive
content-length: 27
{"greeting":"Hello World!"}

いわゆるシンプルでない、アプリケーションのサーバー側の状態が変化する可能性のあるオペレーションの場合、CORSはpre-flightリクエストを使用して、クライアントが宣言した希望のアクセスをサーバーに「事前承認」させます。通常ブラウザはpre-flightリクエストの送信(とレスポンスのチェック)を見えないように実施しますが、以下のcURLコマンドではこのステップをシミュレートしています。

curl -i -X OPTIONS \
    -H "Access-Control-Request-Method: PUT" \
    -H "Origin: http://foo.com" \
    -H "Host: here.com" \
    http://localhost:8080/greet/greeting

リクエストされたCORSに問題がないことを示しています。

HTTP/1.1 200 OK
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Origin: http://foo.com
Date: Thu, 30 Apr 2020 17:30:59 -0500
transfer-encoding: chunked
connection: keep-alive

この時点で、クライアントは所望のPUTリクエストを発行します。この例では挨拶のことばを変更するためにPUTリクエストを発行しています。

curl -i -X PUT \
    -H "Origin: http://foo.com" \
    -H "Host: here.com" \
    -H "Access-Control-Allow-Methods: PUT" \
    -H "Access-Control-Allow-Origin: http://foo.com" \
    -H "Content-Type: application/json" \
    -d "{ \"greeting\" : \"Cheers\" }" \
    http://localhost:8080/greet/greeting

サーバーは通常通り応答します。

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://foo.com
Date: Thu, 30 Apr 2020 17:32:55 -0500
Vary: Origin
connection: keep-alive

Bottom Line

わずかな追加コードで、Helidon SEやHelidon MPのアプリケーションのエンドポイントがCORSプロトコルに参加できます。そして、ここでは重要なポイントだけを紹介しますが、設定を使用して、CORS関連の変更がさらに簡単にできます。

さらに、アプリケーションにエンドポイントを追加するHelidonの組み込みサービス(health、metrics、OpenAPI)のCORSも簡単に有効化して制御できます。

完全な情報は以下のドキュメントをご覧ください。

About CORS in Helidon SE
https://helidon.io/docs/latest/#/se/cors/01_introduction
About CORS in Helidon MP
https://helidon.io/docs/latest/#/mp/cors/01_introduction

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中