首页 \ 问答 \ 无法获得prerender.io nginx配置以使用https重写(Having trouble getting prerender.io nginx config to work with https rewrite)

无法获得prerender.io nginx配置以使用https重写(Having trouble getting prerender.io nginx config to work with https rewrite)

我想我可能已经咬了这个nginx配置我想要写的东西。 我是nginx configs的新手,我正在尝试写一个非常复杂的配置(至少对我而言)。 任何帮助将非常感激。

配置需要:

  1. 将http $ http_x_forwarded_proto重定向到https(https切断ec2负载均衡器)
  2. 使用prerender.io的nginx中间件(seo用于可抓取的单页应用程序)
  3. 将任何查询参数( _escaped_fragment_= )从http传递给https
  4. 将所有子域请求重定向到https://example.com/c/ $ subdomain
  5. 允许http://example.com/healthcheck.txt通过http(负载均衡器运行状况检查)

这是我目前的配置

server {
    listen 80;
    server_name example.com;

    root   /var/www/html/dist;
    index  index.html;

    error_log  /var/log/mysite/error.log;
    access_log /var/log/mysite/access.log;

    location /healthcheck.txt {
        break;
    }

    location / {
        try_files $uri @prerender;

        if ($http_x_forwarded_proto != "https") {
            set $urltest N;
        }

        if ($query_string) {
            set $urltest "${urltest}Y";
        }

        if ($urltest = N) {
            rewrite ^(.*)$ https://example.com$1 permanent;
        }

        if ($urltest = NY) {
            rewrite ^(.*)$ https://example.com$1?$query_string permanent;
        }
    }

    location @prerender {
        proxy_set_header X-Prerender-Token MY_TOKEN;

        set $prerender 0;
        if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
            set $prerender 1;
        }
        if ($args ~ "_escaped_fragment_") {
            set $prerender 1;
        }
        if ($http_user_agent ~ "Prerender") {
            set $prerender 0;
        }
        if ($uri ~ "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff)") {
            set $prerender 0;
        }

        #resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
        resolver 8.8.8.8;

        if ($prerender = 1) {

            #setting prerender as a variable forces DNS resolution since nginx caches IPs and doesnt play well with load balancing
            set $prerender "service.prerender.io";
            rewrite .* /$scheme://$host$request_uri? break;
            proxy_pass http://$prerender;
        }
        if ($prerender = 0) {
            rewrite .* /index.html break;
        }
    }
}

server {
    listen 80;
    server_name ~^(?<sub>.+)\.example\.com$ ;

    rewrite ^ https://example.com/c/$sub;
}

这适用于第1项和第4项,但第2项和第3项不起作用

  1. 使用prerender.io的nginx中间件

这根本不起作用,但是没有https重定向它确实有效

  1. 将任何查询参数( _escaped_fragment_= )从http传递给https

它工作,但重复查询参数,如下所示: ?_escaped_fragment_=&_escaped_fragment_=


有人可以提供任何建议吗?


I think I may have bitten off more than I can chew with this nginx config I am trying to write. I am a novice at nginx configs and I am trying to write a pretty complex config (at least to me). Any help would be very appreciated.

The config needs to:

  1. redirect http $http_x_forwarded_proto to https (https cuts off at the ec2 load balancer)
  2. work with prerender.io's nginx middleware (seo for crawlable single page application)
  3. pass any query parameters (_escaped_fragment_=) from http to https
  4. redirect all subdomain requests to https://example.com/c/$subdomain
  5. allow http://example.com/healthcheck.txt to pass through http (load balancer health check)

Here is my current config

server {
    listen 80;
    server_name example.com;

    root   /var/www/html/dist;
    index  index.html;

    error_log  /var/log/mysite/error.log;
    access_log /var/log/mysite/access.log;

    location /healthcheck.txt {
        break;
    }

    location / {
        try_files $uri @prerender;

        if ($http_x_forwarded_proto != "https") {
            set $urltest N;
        }

        if ($query_string) {
            set $urltest "${urltest}Y";
        }

        if ($urltest = N) {
            rewrite ^(.*)$ https://example.com$1 permanent;
        }

        if ($urltest = NY) {
            rewrite ^(.*)$ https://example.com$1?$query_string permanent;
        }
    }

    location @prerender {
        proxy_set_header X-Prerender-Token MY_TOKEN;

        set $prerender 0;
        if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
            set $prerender 1;
        }
        if ($args ~ "_escaped_fragment_") {
            set $prerender 1;
        }
        if ($http_user_agent ~ "Prerender") {
            set $prerender 0;
        }
        if ($uri ~ "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff)") {
            set $prerender 0;
        }

        #resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
        resolver 8.8.8.8;

        if ($prerender = 1) {

            #setting prerender as a variable forces DNS resolution since nginx caches IPs and doesnt play well with load balancing
            set $prerender "service.prerender.io";
            rewrite .* /$scheme://$host$request_uri? break;
            proxy_pass http://$prerender;
        }
        if ($prerender = 0) {
            rewrite .* /index.html break;
        }
    }
}

server {
    listen 80;
    server_name ~^(?<sub>.+)\.example\.com$ ;

    rewrite ^ https://example.com/c/$sub;
}

This works for items 1 4 & 5, however items 2 & 3 do not work

  1. work with prerender.io's nginx middleware

this does not work at all, however it does work without the https redirect

  1. pass any query parameters (_escaped_fragment_=) from http to https

it works, but duplicates the query parameters like so: ?_escaped_fragment_=&_escaped_fragment_=


Anyone have any advice they could offer?


原文:https://stackoverflow.com/questions/34776580
更新时间:2023-04-27 08:04

最满意答案

Ajax调用是异步的 - 意味着它们会被激活,并且将来某个时候会响应。 代码不等待响应。 如果您在此之前离开页面,则从请求下拉出地毯。

要么使调用同步,要么添加一些“onbeforeunload”事件处理程序以检查您的ajax调用是否已完成,然后再允许用户离开页面。

或者:只是不刷新页面!


Ajax calls are asynchronous - meaning they fire off and sometime in the future a response will come. The code does not wait for the response. If you navigate away from the page before this happens, you pull the rug out from under the request.

Either make the call synchronous, or add some "onbeforeunload" event handler to check if your ajax call has completed before allowing the user to navigate away from the page.

or: just don't refresh the page!

相关问答

更多
  • 我认为这应该做的伎俩(未经测试): Page.Response.Redirect(Page.Request.Url.ToString(), true); I think this should do the trick (untested): Page.Response.Redirect(Page.Request.Url.ToString(), true);
  • Ajax调用是异步的 - 意味着它们会被激活,并且将来某个时候会响应。 代码不等待响应。 如果您在此之前离开页面,则从请求下拉出地毯。 要么使调用同步,要么添加一些“onbeforeunload”事件处理程序以检查您的ajax调用是否已完成,然后再允许用户离开页面。 或者:只是不刷新页面! Ajax calls are asynchronous - meaning they fire off and sometime in the future a response will come. The code ...
  • 这在没有页面提交的情况下是不可能的! 除非你以某种方式将表单字段提交回服务器,即不使用jQuery等进行页面刷新等一些自动保存表单脚本。 如果这用于验证检查,则不需要建议的会话。 用户填写表单并提交回自我服务器端验证失败 $ _GET 验证消息,结束。 或者按照建议在会话中保存整篇文章,类似这样的内 ...
  • 您应该使用JavaScript发送表单,以下是jQuery的示例:
    Send