根据某些查询参数的存在选择服务器块

Posted

技术标签:

【中文标题】根据某些查询参数的存在选择服务器块【英文标题】:select server block based on existence of certain query parameters 【发布时间】:2015-10-10 15:06:43 【问题描述】:

我有一个单页应用程序,我想让它可以抓取,所以我生成了快照。我的应用栈是 rails + unicorn + nginx(作为反向代理)。

现在,Aws Opsworks 从 this cookbook 生成一个 nginx 配置。我通过 ssh 进入系统并修改了默认配置以包含以下行来重定向来自搜索引擎机器人的所有请求,如下所示(它们转换包含 #! 的 url 并在查询参数中发送带有 _escaped_fragment_ 的新请求) :

if ($args ~ "_escaped_fragment_=(.+)") 
  rewrite ^ /snapshots$uri$1?;

当我在浏览器中加载 url 时,一切都很好。我面临的问题是使用chef 自动化相同的事情。由于我添加的代码位于 opsworks 使用默认说明书生成的配置文件中,因此我需要一种方法来定义 nginx server 块来实现此目的。所以,我定义了以下服务器块。

server 
    listen 80;
    server_name example.com;

    if ($args ~ "_escaped_fragment_=(.+)") 
        set $foo $1;
        rewrite ^ /snapshots$uri$foo?;
    

但是 nginx 永远不会选择这个块,因为已经存在另一个具有相同 server_name 的服务器块。那么,有没有一种方法可以根据$args_escaped_fragment_ 的存在来定义一个server 块以供nginx 选择?

如下(我知道这行不通,因为正则表达式与查询参数不匹配)

server 
    listen 80;
    server_name example.com(.+)_escaped_fragment_=(.+);

    ...

【问题讨论】:

退一步说,你真的需要快照吗?大多数主要的搜索引擎(包括谷歌)都在渲染他们从网站接收到的内容,在我们(谷歌的)案例中,使用接近无头浏览器的东西,所以无论你为用户做什么,搜索引擎也会得到它。 这也是我最初的计划,但现在我没有基础设施带宽来做到这一点。我想使用github.com/prerender/prerender_rails,但我在免费 aws 计划中只​​有一个微实例,并且我不想通过运行 phantomJS 实例来增加 CPU 负载。这是我的 MVP 的临时解决方案。 【参考方案1】:

为了在 chef 中执行此操作,您需要创建一个自定义食谱(如果您还没有)和其中的一个食谱,它将用您的首选文件覆盖 opsworks 生成的文件。在食谱中,您需要 2 个文件、nginx 模板和一个用自定义模板覆盖默认模板的配方:

    mycookbook -> 模板 -> 默认 -> custom_nginx.erb mycookbook -> 食谱 -> customise_nginx.rb

(1)的内容:

无论你希望你的 nginx 配置文件是什么,所以:

server 
    listen 80;
    server_name example.com;

    if ($args ~ "_escaped_fragment_=(.+)") 
        set $foo $1;
        rewrite ^ /snapshots$uri$foo?;
    

(2)的内容:

template "/etc/nginx/sites-enabled/<nginx file name>" do
  source "custom_nginx.erb"
  user "root"
  group "root"
  mode "644"
end

service "nginx" do
  action :reload
end

然后将 mycookbook::customise_nginx 添加到层设置中的自定义设置配方部分。

如果您还没有自定义食谱,则需要进行更多设置: https://www.digitalocean.com/community/tutorials/how-to-create-simple-chef-cookbooks-to-manage-infrastructure-on-ubuntu http://docs.aws.amazon.com/opsworks/latest/userguide/workingcookbook-installingcustom-enable.html

编辑: 如果您想保留 opsworks 配置文件,您有两个选择:采用 opsworks 正在使用的模板,我猜是这个? https://github.com/aws/opsworks-cookbooks/blob/release-chef-11.10/nginx/templat‌​es/default/site.erb,创建一个副本并将您的更改放在上面的文件 1 中。或者使用 chef 修改现有的文件内容——例如使用 FileEdit 库(检查这个question的第二个答案)

【讨论】:

我已经创建了一个自定义食谱和一个厨师食谱,内容与您发布的内容相同,但以我的方式,它在 sites-enabled 文件夹下创建了一个附加文件。因为,这个配置文件是在默认生成的文件之后加载的,由于相同的特异性,nginx 永远不会选择我的server 块。您的建议是覆盖 opsworks 生成的配置文件的内容。但是我想要 opsworks 生成文件的内容加上if 条件,有没有办法实现呢?更像是 opsworks 配置生成有一个可以插入我的代码的块。 在这种情况下,您有两个选择:采用 opsworks 正在使用的模板,我猜是这个? https://github.com/aws/opsworks-cookbooks/blob/release-chef-11.10/nginx/templates/default/site.erb,创建一个副本并将您的更改放在上面的文件 1 中。或使用 chef 修改现有文件内容 - 例如使用 FileEdit 库(检查此question的第二个答案@ 这听起来很合理,您可以在答案中添加您的评论以便我接受吗?

以上是关于根据某些查询参数的存在选择服务器块的主要内容,如果未能解决你的问题,请参考以下文章

在同一列中不存在某些 ID 的大表中选择数据。加快查询

LINQ - 如何根据仅存在于某些记录中的另一个元素选择一个元素

ORA-00942: 从异构服务的表中选择某些内容时,表或视图不存在

DELL服务器RAID配置

Hive查询:根据条件选择一列,另一列值匹配某些特定值,然后将匹配结果创建为新列

在 Hibernate 命名查询中根据参数选择分组