エッジスクリプトを使用すると、オリジンサーバーに触れることなく、Alibaba Cloud CDN のプレゼンスポイント (POP) で実行されるカスタムロジックを記述できます。エッジスクリプトを使用して、エッジで認証、ヘッダー、URL リライト、キャッシュの生存時間 (TTL) 値、速度制限、およびアクセスの制御をコントロールします。
このドキュメントで説明するシナリオの概要は、次の表をご参照ください。
| シナリオ | 機能 |
|---|---|
| 認証 | .ts リクエストの URL 署名を検証し、失敗した場合は HTTP 403 を返します |
| リクエストヘッダーとレスポンスヘッダー | Content-Disposition を設定して、名前付きファイルのダウンロードをトリガーします |
| 書き換えとリダイレクト | URI の書き換え、ファイル拡張子の変更、大文字と小文字の正規化、プレフィックスの追加、302 リダイレクトの実行を行います |
| キャッシュコントロール | URL パターンまたは HTTP ステータスコードごとに TTL 値を設定します |
| 速度制限 | URL パラメーターに基づいて転送レートを制限します |
| リージョンと ISP に基づくアクセスの制御 | 特定のリージョンまたはインターネットサービスプロバイダー (ISP) からのリクエストをブロックします |
認証ルールのカスタマイズ
エッジスクリプトの認証は、URL 署名の検証 (ホットリンク保護)、IP 許可リストの適用、User-Agent フィルタリングなど、さまざまなシナリオに対応できます。以下のスクリプトは、.ts リクエストに対して URL 署名ベースのホットリンク保護を実装します。
このスクリプトは、3 つのルールを順番に適用します。
リクエストには
t(有効期限) とkeyの両方のパラメーターが含まれている必要があります。含まれていない場合、POP は HTTP 403 を返します。tパラメーターは有効な数値であり、現在の POP の時間より前であってはなりません。そうでない場合、POP は HTTP 403 を返します。(秘密鍵 + パス + ファイル名.拡張子)の MD5 ハッシュは、URL 内のdigestセグメントと一致する必要があります。一致しない場合、POP は HTTP 403 を返します。
リクエスト URL のフォーマット: /path/digest/?.ts?key=&t=
# .ts リクエストにのみ認証を適用
if eq(substr($uri, -3, -1), '.ts') {
# ルール 1: t または key パラメーターがない場合は拒否
if or(not($arg_t), not($arg_key)) {
add_rsp_header('X-AUTH-MSG', 'auth failed - missing necessary arg')
exit(403)
}
# ルール 2: t が有効な数値でない場合は拒否
t = tonumber($arg_t)
if not(t) {
add_rsp_header('X-AUTH-MSG', 'auth failed - invalid time')
exit(403)
}
# URL の有効期限が切れている場合は拒否
# t はクライアントの時計ではなく、POP のローカル時計と比較されます。
# クライアントの時計が POP の時計と大幅に異なる場合、有効なリクエストが拒否されることがあります。
# 署名付き URL を生成する際に時間バッファーを追加してください。
if gt(now(), t) {
add_rsp_header('X-AUTH-MSG', 'auth failed - expired url')
exit(403)
}
# ルール 3: 正規表現を使用してパスセグメントを抽出
pcs = capture_re($request_uri,'^/([^/]+)/([^/]+)/([^?]+)%?(.*)')
sec1 = get(pcs, 1)
sec2 = get(pcs, 2)
sec3 = get(pcs, 3)
if or(not(sec1), not(sec2), not(sec3)) {
add_rsp_header('X-AUTH-MSG', 'auth failed - malformed url')
exit(403)
}
# MD5(秘密鍵 + パス + ファイル名) を計算し、ダイジェストと比較
key = 'b98d643a-9170-4937-8524-6c33514bbc23'
signstr = concat(key, sec1, sec3)
digest = md5(signstr)
if ne(digest, sec2) {
add_rsp_header('X-AUTH-DEBUG', concat('signstr: ', signstr))
add_rsp_header('X-AUTH-MSG', 'auth failed - invalid digest')
exit(403)
}
}リクエストヘッダーとレスポンスヘッダーのカスタマイズ
以下のスクリプトは、Content-Disposition レスポンスヘッダーを設定し、指定したファイル名で自動的にファイルがダウンロードされるようにします。リクエストに filename URL パラメーターが含まれている場合、ブラウザはその名前でレスポンスボディを保存します。パラメーターがない場合、ブラウザはデフォルトのファイル名を使用します。
期待されるレスポンスヘッダー:
Content-Disposition: attachment;filename="monitor.apk"ファイル名の値は二重引用符で囲まれます。tochar(34) は、引用符を文字列に直接埋め込むことができないため、ASCII コード 34 を " 文字に変換します。
if $arg_filename {
hn = 'Content-Disposition'
hv = concat('attachment;filename=', tochar(34), $arg_filename, tochar(34))
add_rsp_header(hn, hv)
}書き換えとリダイレクトのカスタマイズ
URI の書き換え
/hello を /index.html に書き換えます。オリジンへのリクエストは /index.html を使用し、すべての URL パラメーターは保持されます。
if match_re($uri, '^/hello$') {
rewrite('/index.html', 'break')
}ファイル拡張子の書き換え
URI のファイル拡張子を type URL パラメーターの値に置き換えます。たとえば、/1.txt?type=mp4 は、リクエストがオリジンに転送される前に /1.mp4?type=mp4 になります。取得されたコンテンツは CDN POP にキャッシュされます。
if and(match_re($uri, '^/1.txt$'), $arg_type) {
rewrite(concat('/1.', $arg_type), 'break')
}ファイル拡張子の小文字への変換
ファイル拡張子を小文字に正規化します。たとえば、/image/Photo.JPG は /image/Photo.jpg になります。
pcs = capture_re($uri, '^(.+%.)([^.]+)')
section = get(pcs, 1)
postfix = get(pcs, 2)
if and(section, postfix) {
rewrite(concat(section, lower(postfix)), 'break')
}URI プレフィックスの追加
^/nn_live/(.*) に一致する URI の先頭に /3rd を追加して書き換えます。たとえば、/nn_live/stream1 は /3rd/nn_live/stream1 になります。
pcs = capture_re($uri, '^/nn_live/(.*)')
sec = get(pcs, 1)
if sec {
dst = concat('/3rd/nn_live/', sec)
rewrite(dst, 'break')
}302 リダイレクトの実行
ルートパス / へのリクエストを /app/movie/pages/index/index.html にリダイレクトします。
if eq($uri, '/') {
rewrite('/app/movie/pages/index/index.html', 'redirect')
}HTTPS URL へのリダイレクト
HTTP または HTTPS でルートパスに到達したリクエストを、特定の HTTPS URL にリダイレクトします。https://demo.aliyundoc.com/index.html をターゲット URL に置き換えてください。
if eq($uri, '/') {
rewrite('https://demo.aliyundoc.com/index.html', 'redirect')
}キャッシュ制御のカスタマイズ
以下のスクリプトは、URL パターンと HTTP ステータスコードに基づいて、キャッシュされたリソースの TTL を設定します。
# /image URL の場合:301 応答を 10 秒、302 応答を 5 秒キャッシュ
if match_re($uri, '^/image') {
set_cache_ttl('code', '301=10,302=5')
}
# .mp4 ファイルの場合:TTL = 5 秒
if eq(substr($uri, -4, -1), '.mp4') {
set_cache_ttl('path', 5)
}
# /201801/mp4/ パスの場合:TTL = 50 秒
if match_re($uri, '^/201801/mp4/') {
set_cache_ttl('path', 50)
}
# /201802/flv/ パスの場合:TTL = 10 秒
if match_re($uri, '^/201802/flv/') {
set_cache_ttl('path', 10)
}set_cache_ttl は 2 つのモードを受け入れます。
'code'—'<code>=<seconds>[,<code>=<seconds>]'のフォーマットを使用して、HTTP ステータスコードごとに TTL を設定します'path'— URI パターンに一致するすべての応答に対して TTL を秒単位で設定します
スロットリングポリシーのカスタマイズ
以下のスクリプトは、リクエスト URL から sp (速度制限) と unit パラメーターを読み取り、limit_rate() を使用して速度制限を適用します。速度制限を有効にするには、両方のパラメーターが存在する必要があります。
| パラメーター | 説明 | 有効値 |
|---|---|---|
sp | 速度制限が有効になる前の最大転送レート | 正の整数 |
unit | レートの単位 | k (KB) または m (MB) |
if and($arg_sp, $arg_unit) {
# sp が正の整数であることを検証
sp = tonumber($arg_sp)
if not(sp) {
add_rsp_header('X-LIMIT-DEBUG', 'invalid sp')
return false
}
# unit が k (KB) または m (MB) であることを検証
if and(ne($arg_unit, 'k'), ne($arg_unit, 'm')) {
add_rsp_header('X-LIMIT-DEBUG', 'invalid unit')
return false
}
add_rsp_header('X-LIMIT-DEBUG', concat('set on: ', sp, $arg_unit))
limit_rate(sp, $arg_unit)
return true
}リージョンと ISP に基づくアクセスの制御
以下のスクリプトは、クライアント IP アドレスのリージョンとインターネットサービスプロバイダー (ISP) に基づいてアクセスを制限します。許可リストにないリージョンまたは ISP からのリクエストは、HTTP 403 でブロックされます。
client_region() はクライアント IP のリージョンコードを返します。client_isp() は ISP コードを返します。リージョンコードと ISP コードの完全なリストについては、「リクエストロジック関数」をご参照ください。
# 許可リストにないリージョンからのリクエストをブロック
ip_region_id = client_region()
if not(match_re(ip_region_id, '440000|370000')) {
add_rsp_header('X-REGION-BLOCK-DEBUG', concat('hit ip_region_id:', ip_region_id))
exit(403)
}
# 許可リストにない ISP からのリクエストをブロック
ip_isp_id = client_isp()
if not(match_re(ip_isp_id, '100017|100025')) {
add_rsp_header('X-REGION-BLOCK-DEBUG', concat('hit ip_isp_id:', ip_isp_id))
exit(403)
}'440000|370000' と '100017|100025' を、ご利用のアクセスポリシーに一致するリージョンコードと ISP コードに置き換えてください。