概要
ICOS にオブジェクトをアップロードすると、特に何もしなければ Content-Type
が application/octet-stream
に設定され、ただのバイナリ扱いになります。
今回はサーバーレスサービスを使って、アップロードされるオブジェクトの拡張子から適切な Content-Type
に自動修正します。
この操作を行うことで、ブラウザからアクセスするときに画像や HTML などが正しく認識され、コンテンツが正しく表示されます。
Content-Type
の修正には、「Object operations - Copy an object」(ICOS サーバーサイドでのコピー処理)を活用し、Functions (クライアント)に一度ダウンロードして再アップロードするといった動作はさせません
また、Functions からは ICOS プライベートエンドポイントを経由してオペレーションがおこなえます。
事前準備
CLI プラグインインストール
ibmcloud plugin install cloud-functions
ibmcloud plugin show cloud-functions
CLI ログイン
export REGION="jp-tok"
export RESOURCE_GROUP="khayama-rg"
ibmcloud login -a cloud.ibm.com -r $REGION -g $RESOURCE_GROUP
環境設定
export FN_NAMESPACE="khayama-fn"
export COS_INSTANCE_NAME="khayama-cos" # 既存の ICOS インスタンスを使います
Functions Namespace 設定
namespace
を作成してプロパティをセットします。
ibmcloud fn namespace create $FN_NAMESPACE
ibmcloud fn namespace target $FN_NAMESPACE
Functions から ICOS へのアクセスを許可
ICOS の変更通知を受信してトリガーできるように以下の許可設定をおこないます。
ibmcloud iam authorization-policy-create \
functions \
--source-service-instance-name $FN_NAMESPACE \
cloud-object-storage \
--target-service-instance-name $COS_INSTANCE_NAME \
"Notifications Manager"
Functions ServiceID に Writer 権限を付与
namespace
を作成すると、ServiceID (API Key) が自動で発行されます。
Functions では、__OW_IAM_NAMESPACE_API_KEY
の環境変数にセットされるので、これを使って他のサービス認証をおこなうことができます。
その ServiceID (API Key) に Writer 権限を付与して Functions からオブジェクトを書き込めるようにします。
export COS_INSTANCE_ID=$(ibmcloud resource service-instance --output JSON $COS_INSTANCE_NAME | jq -r '.[].guid')
echo $COS_INSTANCE_ID
ibmcloud iam service-id-unlock $FN_NAMESPACE -f
ibmcloud iam service-policy-create $FN_NAMESPACE \
--roles "Writer" \
--service-name cloud-object-storage \
--service-instance $COS_INSTANCE_ID
ibmcloud iam service-id-lock $FN_NAMESPACE -f
GitHub からダウンロード
GitHub にあるファイルをダウンロードします。
git clone https://github.com/khayama/fn-setCosContentType.git
cd fn-setCosContentType
今回の Functions デプロイ用 yaml では以下のように定義しています。
Functions 実行パラメータは、環境変数の値を取得して埋め込む形で定義しています。
packages:
setCosContentType:
version: 1.0
license: Apache-2.0
actions:
setCosContentType:
version: 1.0
description: replace with reference content type
docker: openwhisk/dockerskeleton
function: setCosContentType.sh
inputs:
triggers:
cos-object-write:
feed: /whisk.system/cos/changes
inputs:
bucket: $MY_BUCKET # The COS bucket must be regional and exist in the same location as the namespace
event_types: write # https://cloud.ibm.com/docs/openwhisk?topic=openwhisk-pkg_obstorage#pkg_obstorage_ev_ch_ref_trig
rules:
cos-object-write-setCosContentType:
description: Action is triggered by object-write operation
action: setCosContentType
trigger: cos-object-write
Functions デプロイ
環境変数セット
以下のように環境変数をセットします。
export MY_BUCKET=khayama-mime
yaml ファイルを指定してデプロイ
ibmcloud fn deploy --manifest setCosContentType.yml
# 削除するには ibmcloud fn undeploy --manifest setCosContentType.yml
動作確認
実際に ICOS にファイルアップロードをおこない、Functions がトリガーされたかは以下の Monitor
画面で確認できます。
- 1回のオブジェクトアップロードで2回トリガーが起動したことが確認できます。
- アクションのスクリプト内で、
REF_CONTENT_TYPE
と照合し、修正済みかどうかを判断した上で処理が実行されます。 - そのため、1 度目のアクションで
Content-Type
が修正され、その書き込みによって 2 度目が起動しますが、処理は実行されず終了します。 -
REF_CONTENT_TYPE
に存在しない拡張子については、スクリプト内で何も実行されません。
https://cloud.ibm.com/functions/dashboard
Content-Type を確認する
AWS CLI を使ってオブジェクトとコンテンツタイプの一覧を確認できます。
export BUCKET_NAME=khayama-mime
export ENDPOINT=s3.jp-tok.cloud-object-storage.appdomain.cloud
for KEY in $(aws --endpoint-url https://$ENDPOINT s3api list-objects \
--bucket $BUCKET_NAME \
--query "Contents[].[Key]" \
--output text)
do
aws --endpoint-url https://$ENDPOINT s3api head-object \
--bucket $BUCKET_NAME \
--key $KEY \
--query "[\`$KEY\`,ContentType]" \
--output text
done
5MB.zip application/zip
ibmcloud_logo.png image/png
index.html text/html