🌐

【Shopify.dev和訳】Apps/Online store/App proxies

2021/09/11に公開約6,500字

この記事について

この記事は、Apps/Online store/App proxiesの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://apps.shopify.com/shopify-application-314?locale=ja&from=daniel

Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。

https://apps.shopify.com/font-picker-1?locale=ja&from=daniel

アプリプロキシによる動的なストアデータの表示

アプリプロキシは、オンラインストアのオリジンにある設定可能なルートへのリクエストを外部オリジンへ転送し、ストアページにデータを表示します。たとえば、アプリプロキシは、https://johns-apparel.myshopify.com/admin/themes/app/my-app からのリクエストをアプリサーバーに転送することができます。アプリプロキシを使用すると、CORS(Cross-origin Security Concerns)を気にせずにオンラインストアとデータを共有することができます。

アプリプロキシのレスポンスの内容は、CSS、JavaScript、画像などの静的なアセットから、Liquid テンプレートや JSON データなどの動的なレスポンスまで、あらゆるものが対象となります。

アプリを公開する前に、アプリプロキシを設定する必要はありません。アプリを公開した後にアプリプロキシを追加すると、そのアプリの既存のインストールが自動的に更新されます。リクエストが転送される URL は、Partner Dashboard でいつでも設定できます。つまり、オンラインストアの URL を更新することなく、URL を変更することができます。

アプリプロキシの追加

  1. Partner Dashboard」で「Apps」をクリックします。
  2. アプリの名前をクリックします。
  3. App setupをクリックします。
  4. App proxyセクションに移動します。
  5. App proxyセクションで、「Subpath prefix」ドロップダウンリストからプレフィックスを選択します。
  6. Subpath フィールドにサブパスを入力します。

これらの設定は、Shopify へのどの HTTP リクエストが次のステップで入力されたプロキシ URL にプロキシされるかを決定します。例えば、サブパスのプレフィックスが apps で、サブパスが store-pickup の場合、オンラインストアの https://johns-apparel.myshopify.com/apps/store-pickup 以降のパスはすべて、指定されたプロキシ URL にプロキシされます。 7. Proxy URLの欄に、プロキシサーバーの URL を入力します。これは、前のステップで入力したパスからプロキシされる URL です。

  1. 設定が完了したら、「Save」をクリックします。

以下のようなアプリプロキシの設定を考えてみましょう。

  • サブパスのプレフィックス:apps
  • サブパス名:my-app-proxy
  • プロキシ URL: https://my-app-proxy.com/app_proxy

この例では、https://johns-apparel.myshopify.com/apps/my-app-proxy/app_pathhttps://my-app-proxy.com/app_proxy/app_path のプロキシ URL に転送されます。リクエストに含まれる後続の子ルートも同様に転送されるため、https://johns-apparel.myshopify.com/apps/my-app-proxy/child-route https://my-app-proxy.com/app_proxy/child-route に転送されます。

アプリプロキシを利用したマーチャントの体験

マーチャントは、アプリプロキシのサブパスやサブパスのプレフィックスを変更することができます。マーチャントは Shopify が提供する一連の値(/apps, /a, /community, or /tools)を切り替えることで、サブパスのプレフィックスを変更します。サブパスプレフィックスとサブパスの組み合わせは、アプリプロキシがマーチャントのショップからどこにアクセスされるかを定義します。マーチャントはこの情報を変更することで、マーチャントのドメインから発信されているように見えるフレンドリーな URL を得ることができます。サブパスは、Proxy URL フィールドで指定するプロキシ URL の位置には影響しません。

プロキシリクエストの処理

以下にアプリのプロキシ定義の例を示します。

  • プロキシ URL: https://proxy-domain.com/proxy
  • クライアント IP: 123.123.123.123
  • シェアードシークレット: hush
    クライアントから以下のような HTTP リクエストが送信されると、Shopify は指定されたプロキシ URL を使ってリクエストを転送します。
GET /apps/awesome_reviews/extra/path/components?extra=1&extra=2 HTTP/1.1
  Host: shop-domain.com
  Cookie: csrftoken=01234456789abcdef0123456789abcde;
  _session_id=1234456789abcdef0123456789abcdef;
  _secure_session_id=234456789abcdef0123456789abcdef0

転送されたリクエストは以下のようになります。

GET /proxy/extra/path/components?extra=1&extra=2&shop=shop-name.myshopify.com&path_prefix=%2Fapps%2Fawesome_reviews&timestamp=1317327555&signature=a9718877bea71c2484f91608a7eaea1532bdf71f5c56825065fa4ccabe549ef3 HTTP/1.1
  Host: proxy-domain.com
  X-Forwarded-For: 123.123.123.123

アプリはショップのドメインを通してアクセスされるため、アプリのプロキシではクッキーはサポートされていません。Shopify はリクエストから Cookie ヘッダーを取り除き、レスポンスからSet-Cookieを取り除きます。

転送されたリクエストには、以下のパラメータが追加されます。

  • shop: ショップの myshopify.com ドメイン。
  • path_prefix: ショップにアクセスした際のプロキシサブパスのプレフィックス。このケースでは、/apps/awesome_reviewsで、転送されたリクエストの URL では、プロキシアプリケーションのプロキシ URL に置き換えられています。
  • timestamp: UTC の 1970 年 1 月 1 日午前 0 時からの秒単位の時間です。
  • signature: リクエストが Shopify によって送信されたことを確認するために使用される、他のパラメータを"&"文字で分割して 16 進数でエンコードしたSHA-256 HMACです。署名はエンコードされておらず、ソートされ、連結されており、HMAC キーとしてアプリケーションの共有秘密を使用しています。
    リクエストメソッドとリクエストボディの両方が転送されるということは、フォーム送信や AJAX リクエストのコンテンツをプロキシアプリケーションで使用できるということです。この場合、ボディに URL エンコードされたパラメータが含まれていても、URL にはプロキシが追加したクエリパラメータ(shoppath_prefixtimestampsignature)が含まれています。

デジタル署名の計算

リクエストが Shopify から送られてきたことを確認するには、SHA-256 ハッシュ関数に従って HMAC ダイジェストを計算し、それをsignatureプロパティの値と比較する必要があります。値が一致すれば、リクエストは Shopify から送信されたことになります。

以下は、デジタル署名を計算するための Ruby の例です。

require 'openssl'
require 'rack/utils'
SHARED_SECRET = 'hush'

# railsでのrequest.query_stringの使用
query_string = "extra=1&extra=2&shop=shop-name.myshopify.com&path_prefix=%2Fapps%2Fawesome_reviews&timestamp=1317327555&signature=a9718877bea71c2484f91608a7eaea1532bdf71f5c56825065fa4ccabe549ef3"

query_hash = Rack::Utils.parse_query(query_string)
# => {
#   "extra" => ["1", "2"],
#   "shop" => "shop-name.myshopify.com",
#   "path_prefix" => "/apps/awesome_reviews",
#   "timestamp" => "1317327555",
#   "signature" => "a9718877bea71c2484f91608a7eaea1532bdf71f5c56825065fa4ccabe549ef3",
# }

# "signature "エントリの削除と保存
signature = query_hash.delete("signature")

sorted_params = query_hash.collect{ |k, v| "#{k}=#{Array(v).join(',')}" }.sort.join
# => "extra=1,2path_prefix=/apps/awesome_reviewsshop=shop-name.myshopify.comtimestamp=1317327555"

calculated_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), SHARED_SECRET, sorted_params)
raise 'Invalid signature' unless ActiveSupport::SecurityUtils.secure_compare(signature, calculated_signature)

Liquid 対応

アプリプロキシは Shopify のテンプレート言語であるLiquidに対応しています。Liquid を含むアプリプロキシのレスポンスは、ストアのテーマの一部であるかのように、ストアデータと共に HTML にレンダリングされます。

プロキシ URL からの HTTP レスポンスのヘッダに Content-Type: application/liquid が設定されている場合、Shopify はリクエストボディに含まれるすべての Liquid コードを、ショップのテーマを使用してショップのコンテキストでレンダリングします。それ以外の場合は、レスポンスが直接クライアントに返されます。また、30 倍のリダイレクトが行われます。

Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://apps.shopify.com/shopify-application-314?locale=ja&from=daniel

Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。

https://apps.shopify.com/font-picker-1?locale=ja&from=daniel

Discussion

ログインするとコメントできます