2013-01-16 75 views
4

我们的网站是一个图像存储库的种类。每个图像都有一个外部URL和一个内部URL的概念。外部URL被客户看到,并且随着我们对SEO的实验而改变。内部网址是指向我们图片托管服务的永久性网址。我们使用我们的Ruby on Rails应用程序来提供URL翻译。以下是一个请求示例:Nginx的代理服务器重定向到另一个URI

--------   -----  -------  -------   ------------ 
|  | --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响应头或状态码,我不知道。

回答

3

使用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 

完整的解决方案被发现here 。我建议在实施之前阅读它。

+0

这是一个很好的解决方案,尽管一个小记录...你不需要构造变量来重定向,你可以这样做: proxy_set_pass http:// $ 1/$ 2; –

+0

我想这是为了可读性和可维护性的考虑。为了避免将读取该配置的下一个管理员的可能的WTF。 – Konstantin

相关问题