背景

项目需要,提供一个对外的文件下载服务,详细需求点如下:

  • 需要对接多个客户
  • 各个客户要求的数据格式不同,内容不同
  • 客户间权限隔离
  • 文件可能较大

方案

文件下载的第一方案自然想到了nginx,ip、流量控制等nginx都只要配置就可以实现,但似乎无法做好各个客户间的权限隔离(当然localtion隔离也可以,但维护成本比较大)。搜索之后了解到了nginx的X-Accel

X-accel allows for internal redirection to a location determined by a header returned from a backend.

X-Accel比较特殊的地方是利用upstream返回的头部信息进行对应处理。常见的配置方式如下:

nginx配置link
http {
....
server {
listen 80;
server_name your-domain.com;

location / {
rewrite ^/download/(.*) /down.php?path=$1 last;

proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

client_max_body_size 10m;
client_body_buffer_size 128k;

proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;

proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

}

location /files {
root /var/www;
internal;
}
}
}

注意interval保证了文件不能直接被外部访问,只能用于内部跳转,upstream的返回中通过X-Accel-Redirect指定真实的跳转文件名。

down.php
<?php
// Get requested file name
$path = $_GET["path"];

//...
// Perform any required security checks, validation
// and/or stats accounting
//...

// And redirect user to internal location
header("X-Accel-Redirect: /files/" . $path);

?>

在cgi中我们可以根据实际情况做一些安全检查、验证、统计等。如针对我们的实际场景,校验请求方ip、签名是否有效,可以对每家客户做到权限的隔离。