4

我们的网站是一个图像存储库。每个图像都有一个外部 URL 和一个内部 URL 的概念。客户可以看到外部 URL,并且在我们尝试 SEO 时它们会发生变化。内部 URL 是指向我们的图像托管服务的永久 URL。我们使用我们的 Ruby on Rails 应用程序来提供 URL 翻译。下面是一个请求示例:

--------           -----     -------     -------          ------------
|      | --eURL--> |   | --> |     | --> |     | -iURL--> |          |
|client|           |CDN|     |Nginx|     | RoR |          |Image Host|
|      | <-------- |   | <-- |     | <-- |     | <-IMG--- |          |
--------           -----     -------     -------          ------------

该架构正在运行,但通过 RoR 流式传输图像效率低下。我想让 Nginx 做代理。这就是它的用途。提议的架构看起来像这样:

--------           -----     -------         -------
|      | --eURL--> |   | --> |     | ------> | RoR |
|client|           |CDN|     |Nginx| <-????- |     |
|      | <-------- |   | <-- |     |         -------
--------           -----     |     |         ------------
                             |     | -iURL-> |Image Host|
                             |     | <-IMG-- |          |
                             -------         ------------

我可以向 Nginx 发送什么响应以使其代理数据?我不介意将 Nginx 模块添加到我的基础架构中,当然我愿意更改我的 nginx.conf。

X-Sendfile是我发现的最接近的东西,但它只允许从本地文件系统流式传输。也许还有其他一些我不知道的模糊 HTTP 响应标头或状态代码。

4

1 回答 1

4

X-Accel-Redirect标头与特殊的 Nginx 结合使用location以使 Nginx 代理远程文件。

这是location要添加到您的 Nginx 配置中的内容:

# Proxy download 
location ~* ^/internal_redirect/(.*?)/(.*) {
  # Do not allow people to mess with this location directly
  # Only internal redirects are allowed
  internal;

  # Location-specific logging
  access_log logs/internal_redirect.access.log main;
  error_log logs/internal_redirect.error.log warn;

  # Extract download url from the request
  set $download_uri $2;
  set $download_host $1;

  # Compose download url
  set $download_url http://$download_host/$download_uri;

  # Set download request headers
  proxy_set_header Host $download_host;
  proxy_set_header Authorization '';

  # The next two lines could be used if your storage 
  # backend does not support Content-Disposition 
  # headers used to specify file name browsers use 
  # when save content to the disk
  proxy_hide_header Content-Disposition;
  add_header Content-Disposition 'attachment; filename="$args"';

  # Do not touch local disks when proxying 
  # content to clients
  proxy_max_temp_file_size 0;

  # Download the file and send it to client
  proxy_pass $download_url;
}

现在您只需X-Accel-Redirect在对 Nginx 的响应中设置标题:

# This header will ask nginx to download a file 
# from http://some.site.com/secret/url.ext and send it to user
X-Accel-Redirect: /internal_redirect/some.site.com/secret/url.ext

# This header will ask nginx to download a file 
# from http://blah.com/secret/url and send it to user as cool.pdf
X-Accel-Redirect: /internal_redirect/blah.com/secret/url?cool.pdf

在这里找到了完整的解决方案。我建议在实施之前阅读它。

于 2013-01-16T07:22:22.833 回答