Обслуживание статических ресурсов для одностраничного приложения с помощью nginx

Я пытаюсь понять, как заставить nginx обслуживать статические ресурсы, иметь запасной вариант index.html и перенаправлять его в API. В настоящее время у меня работает только корневой маршрут / и переадресация API.

Это поведение, которое мне нужно:

GET /          -> nginx sends s3/index.html (current)
* /api         -> nginx proxies to the puma server (current)

# Yet to figure out (and the reason for this question)
GET /sub-route    -> nginx sends s3/index.html, and routing is handled by the js framework
GET *.css|.js|etc -> nginx forwards to the s3 bucket (all relative to index.html)

Вот мой nginx.conf (в нем есть некоторые шаблоны, потому что (как часть процесса развертывания) я делаю:

envsubst '$S3_BUCKET:$NGINX_PORT' < /app/deployment/nginx.template.conf > /app/deployment/nginx.conf

pid        /app/tmp/nginx.pid;

events {  }
http {
  upstream puma {
    server unix:///app/sockets/puma.sock;
  }

  server {
    listen ${NGINX_PORT} default_server deferred;
    server_name aeonvera.com;

    gzip on;
    gzip_disable "msie6";

    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    root /app/public;
    access_log /app/log/nginx.access.log;
    error_log /app/log/nginx.error.log info;

    client_max_body_size 20M;
    keepalive_timeout 5;


    location ~ ^/api {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;

      proxy_pass http://puma;
    }

    # Send all other requests to the index.html
    # stored up on s3
    location / {
      # tell all URLs to go to the index.html
      # I got an error with this about having proxy_pass within a location...?
      # location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2|woff|ttf)$ {
      #   proxy_pass "https://s3.amazonaws.com/${S3_BUCKET}/ember/"
      #
      #   gzip_static on;
      #   expires max;
      #   add_header Cache-Control public;
      # }

      # Don't know what this does
      rewrite ^([^.]*[^/])$ $1/ permanent;

      # only ever GET these resources
      limit_except GET {
        deny all;
      }


      # use google as dns
      resolver 8.8.8.8;

      proxy_http_version     1.1;
      proxy_set_header       Host 's3.amazonaws.com';
      proxy_set_header       Authorization '';

      # avoid passing along amazon headers
      proxy_hide_header      x-amz-id-2;
      proxy_hide_header      x-amz-request-id;
      proxy_hide_header      x-amz-delete-marker;
      proxy_hide_header      x-amz-version-id;

      # cookies are useless on these static, public resources
      proxy_hide_header      Set-Cookie;
      proxy_ignore_headers   "Set-Cookie";
      proxy_set_header cookie "";

      proxy_buffering        off;

      # s3 replies with 403 if an object is inaccessible; essentially not found
      proxy_intercept_errors on;
      # error_page 500 502 503 504 /500.html;

      # the actual static files
      proxy_pass             "https://s3.amazonaws.com/${S3_BUCKET}/ember/index.html";
    }

  }
}

Обновление 1

Я добавил это выше location /

location ~ ^/(assets|fonts) {
  rewrite (.*) $1 break;
  proxy_pass "https://s3.amazonaws.com/${S3_BUCKET}/ember";

  gzip_static on;
  expires max;
  add_header Cache-Control public;
}

но выдает ошибку:

nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /app/deployment/nginx.conf:53

Идея, стоящая за этим изменением, заключается в том, что, поскольку все мои активы находятся в известных местах, я могу указать nginx проксировать это местоположение, а затем получить rewrite (.*) / permanent; для моего location /.

Обновление 2

Я подумал, может быть, я мог бы переписать URL-адрес для /dashboard, чтобы nginx прокси-пассировал index.html. Нет успеха.

  rewrite ^/(.*) / break;
  proxy_pass             "https://s3.amazonaws.com/${S3_BUCKET}/ember/index.html";

Это просто перенаправляет на маркетинговую страницу s3.

Content-Length:0
Content-Type:text/plain; charset=utf-8
Date:Thu, 08 Feb 2018 13:22:49 GMT
Location:https://aws.amazon.com/s3/
Server:nginx/1.12.0

Заголовки ответов ^


person NullVoxPopuli    schedule 07.02.2018    source источник


Ответы (1)


Я думаю, что понял это, но было бы очень полезно, если бы кто-нибудь мог проверить, так как я все еще новичок в nginx.

location / {
  # ...

  proxy_set_header       Host 's3.amazonaws.com';

  # ...

  rewrite ^/(.*) /${S3_BUCKET}/ember/index.html break;
  proxy_pass             "https://s3.amazonaws.com/${S3_BUCKET}/ember/index.html";
}

Наличие заголовка Host здесь важно, потому что без него перезапись изменит URL-адрес в браузере пользователя (чего мы не хотим делать, потому что это, скорее всего, испортит маршрутизацию SPA.

person NullVoxPopuli    schedule 09.02.2018