O EdgeScript permite escrever lógica personalizada executada nos pontos de presença (POPs) do Alibaba Cloud CDN, sem alterar o servidor de origem. Use o EdgeScript para controlar autenticação, cabeçalhos, reescrita de URL, valores de tempo de vida (TTL) de cache, limitação de taxa e controle de acesso na borda.
A tabela a seguir resume os cenários abordados neste tópico:
|
Cenário |
Funcionalidade |
|
Valida assinaturas de URL para requisições |
|
|
Defina |
|
|
Reescreve URIs, altera extensões de arquivo, normaliza maiúsculas e minúsculas, adiciona prefixos e executa redirecionamentos 302 |
|
|
Configure valores de TTL por padrão de URL ou código de status HTTP |
|
|
Restringe a taxa de transferência com base em parâmetros de URL |
|
|
Bloqueia requisições de regiões ou provedores de serviços de Internet (ISPs) específicos |
Personalizar regras de autenticação
A autenticação via EdgeScript abrange diversos cenários, como validação de assinatura de URL (proteção contra hotlink), aplicação de lista de permissões de IP e filtragem de User-Agent. O script abaixo implementa proteção contra hotlink baseada em assinatura de URL para requisições .ts.
O script aplica três regras em sequência:
A requisição deve incluir os parâmetros
t(tempo de expiração) ekey. Caso contrário, o POP retorna HTTP 403.O parâmetro
tdeve ser um número válido e não pode ser anterior à hora atual do POP. Se essa condição não for atendida, o POP retorna HTTP 403.O hash MD5 de
(chave privada + caminho + nome_do_arquivo.extensão)deve corresponder ao segmentodigestna URL. Em caso de divergência, o POP retorna HTTP 403.
Formato da URL de requisição: /path/digest/?.ts?key=&t=
# Only apply authentication to .ts requests
if eq(substr($uri, -3, -1), '.ts') {
# Rule 1: Reject if t or key parameters are missing
if or(not($arg_t), not($arg_key)) {
add_rsp_header('X-AUTH-MSG', 'auth failed - missing necessary arg')
exit(403)
}
# Rule 2: Reject if t is not a valid number
t = tonumber($arg_t)
if not(t) {
add_rsp_header('X-AUTH-MSG', 'auth failed - invalid time')
exit(403)
}
# Reject if the URL has expired.
# t is compared against the POP's local clock, not the client clock.
# If the client clock differs significantly from the POP clock, valid
# requests may be rejected. Add a time buffer when generating signed URLs.
if gt(now(), t) {
add_rsp_header('X-AUTH-MSG', 'auth failed - expired url')
exit(403)
}
# Rule 3: Extract path segments using a regular expression
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)
}
# Compute MD5(private_key + path + filename) and compare with digest
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)
}
}
Personalizar cabeçalhos de requisição e resposta
O script abaixo define o cabeçalho de resposta Content-Disposition para iniciar automaticamente o download de um arquivo com nome personalizado. Quando a requisição contém o parâmetro de URL filename, o navegador salva o corpo da resposta com esse nome. Na ausência desse parâmetro, o navegador usa o nome de arquivo padrão.
Cabeçalho de resposta esperado:
Content-Disposition: attachment;filename="monitor.apk"
O valor do nome do arquivo vem entre aspas duplas. A função tochar(34) converte o código ASCII 34 no caractere ", pois não é possível inserir aspas diretamente na string.
if $arg_filename {
hn = 'Content-Disposition'
hv = concat('attachment;filename=', tochar(34), $arg_filename, tochar(34))
add_rsp_header(hn, hv)
}
Personalizar reescritas e redirecionamentos
Reescrever uma URI
Reescreva /hello para /index.html. A requisição back-to-origin usa /index.html e todos os parâmetros de URL são preservados.
if match_re($uri, '^/hello$') {
rewrite('/index.html', 'break')
}
Reescrever uma extensão de arquivo
Substitua a extensão do arquivo na URI pelo valor do parâmetro de URL type. Por exemplo, /1.txt?type=mp4 torna-se /1.mp4?type=mp4 antes do encaminhamento da requisição à origem. O conteúdo recuperado é então armazenado em cache nos POPs da CDN.
if and(match_re($uri, '^/1.txt$'), $arg_type) {
rewrite(concat('/1.', $arg_type), 'break')
}
Converter extensão de arquivo para minúsculas
Normalize a extensão do arquivo para letras minúsculas. Assim, /image/Photo.JPG passa a ser /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')
}
Adicionar um prefixo à URI
Reescreva qualquer URI correspondente a ^/nn_live/(.*) adicionando /3rd no início. Dessa forma, /nn_live/stream1 transforma-se em /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')
}
Executar um redirecionamento 302
Redirecione requisições do caminho raiz / para /app/movie/pages/index/index.html.
if eq($uri, '/') {
rewrite('/app/movie/pages/index/index.html', 'redirect')
}
Redirecionar para uma URL HTTPS
Redirecione requisições ao caminho raiz — tanto via HTTP quanto HTTPS — para uma URL HTTPS específica. Substitua https://demo.aliyundoc.com/index.html pela URL de destino.
if eq($uri, '/') {
rewrite('https://demo.aliyundoc.com/index.html', 'redirect')
}
Personalizar o controle de cache
O script a seguir defina o TTL para recursos em cache com base em padrões de URL e códigos de status HTTP.
# For /image URLs: cache 301 responses for 10 s, 302 responses for 5 s
if match_re($uri, '^/image') {
set_cache_ttl('code', '301=10,302=5')
}
# For .mp4 files: TTL = 5 s
if eq(substr($uri, -4, -1), '.mp4') {
set_cache_ttl('path', 5)
}
# For /201801/mp4/ paths: TTL = 50 s
if match_re($uri, '^/201801/mp4/') {
set_cache_ttl('path', 50)
}
# For /201802/flv/ paths: TTL = 10 s
if match_re($uri, '^/201802/flv/') {
set_cache_ttl('path', 10)
}
A função set_cache_ttl aceita dois modos:
'code'— defina o TTL por código de status HTTP, usando o formato'<code>=<seconds>[,<code>=<seconds>]''path'— defina o TTL em segundos para todas as respostas que correspondem ao padrão de URI
Personalizar políticas de limitação de taxa
Este script lê os parâmetros sp (limite de velocidade) e unit da URL de requisição e aplica a limitação de taxa por meio de limit_rate(). Ambos os parâmetros devem estar presentes para que a limitação tenha efeito.
|
Parâmetro |
Descrição |
Valores válidos |
|
|
Taxa máxima de transferência antes da aplicação da limitação |
Inteiro positivo |
|
|
Unidade da taxa |
|
if and($arg_sp, $arg_unit) {
# Validate that sp is a positive integer
sp = tonumber($arg_sp)
if not(sp) {
add_rsp_header('X-LIMIT-DEBUG', 'invalid sp')
return false
}
# Validate that unit is k (KB) or 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
}
Controle de acesso por região e ISP
O script abaixo restringe o acesso com base na região e no provedor de serviços de Internet (ISP) do endereço IP do cliente. Requisições de regiões ou ISPs fora da lista de permissões são bloqueadas com HTTP 403.
A função client_region() retorna o código da região do IP do cliente, enquanto client_isp() fornece o código do ISP. Para obter a lista completa de códigos de região e ISP, consulte Funções de lógica de requisição.
# Block requests from regions not in the allowlist
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)
}
# Block requests from ISPs not in the allowlist
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)
}
Substitua '440000|370000' e '100017|100025' pelos códigos de região e ISP adequados à sua política de acesso.