使用 CADDY 重定向媒体请求至 CDN 以减小带宽

2019-06-01

背景

静态博客下,在 markdown 文件中插入图片时,会写下:

![image](/media/img/example.png)

但此时,客户端请求时请求的是服务器上的资源,并不走 CDN。想直接写明去 CDN 寻找资源还需要写一大段, 很不方便(如下)。

![image](cdn.example.com/media/img/example.png)

解决方案

使用 Caddy 的 redir 模块,将请求重定向至 CDN,并在 CDN 指向的服务器资源内软链接媒体文件夹。鉴于 Caddy 的 redir 模块只有 / 才可以通配,其他(如我想要匹配的 /media)都只能精确匹配,这时就需要用到条件语句了。

redir {
    if {path} starts_with /media
    / https://cdn.example.com:443{uri}
}

{path}/media 开头时通配重定向至 CDN(注意此处 {uri} 包含 /media 字段,因为它是通过通配 / 得来的)

接下来,在 CDN 指向的服务器资源内软连接媒体文件夹:

ln -s /path/to/media

测试

$ curl -L -e '; auto' -i https://caddy.example.com/media/img/example.png
> HTTP/2 301
> content-type: text/html; charset=utf-8
> location: https://cdn.example.com:443/caddy/media/img/example.png
> server: Caddy
> content-length: 89
> date: Sat, 01 Jun 2019 07:52:10 GMT
>
> HTTP/1.1 200 OK
> Server: Tengine
> Content-Type: image/png
> Content-Length: 20255
> Connection: keep-alive
> Date: Sat, 01 Jun 2019 07:13:07 GMT
> Accept-Ranges: bytes
> Access-Control-Allow-Origin: *
> Access-Control-Expose-Headers: X-Log, X-Reqid
> Access-Control-Max-Age: 2592000
> Cache-Control: public, max-age=31536000
> Content-Disposition: inline; filename="example.png"; filename*=utf-8' 'example.png

成功