is there a way to fallback nginx proxy_pass if header set - nginx

nginx server serves http://server1.com, http://server2.com and http://server3.com.
nginx upstreams request process to some ruby code.
server1.com, server2.com and server3.com are actually some static files stored on amazon s3.
I want to do next: find bucket name for 'server1' host, put in db some logs and notify nginx to stream from amazon.
Maybe via setting in ruby code header with url to amazon s3 bucket and using this url later by nginx.
The flow: browser -> nginx -> ruby -> nginx -> amazon_s3 -> browser
I found how i can do this on error:
http {
server {
listen 12345; #Port that my custom app was assigned
server_name mydomain.com;
location / {
proxy_intercept_errors on;
error_page 400 403 502 503 504 = #fallback;
proxy_pass http://the_old_site_domain.com;
}
location #fallback {
proxy_pass http://myfallback.domain.com;
}
}
}
But is there a way to do something similar based on header appereance?
Thanks!
UPD
This is how i can test my header:
if ($http_x_custom_header) {
....
}
If set nginx should do some internal redirect, right?
But how it can be invoked after ruby code?

There is special headers called X-Accel-....
You need X-Accel-Redirect.

Related

Can I configure nginx with proxy_pass to use an error document on the proxied server?

I've configured nginx with proxy_pass to proxy URLs like /uploads/foo.png to fetch from an S3 bucket, but obviously missing files result in ugly XML errors, and I want to return a static HTML file.
I tried using the "static website" feature of S3, but it always returns (incorrect) 403 status codes with the error doc, and it seems there's no way to alter that via proxy_pass.
For various reasons, using a local file on the nginx server isn't an option. This nginx instance only does proxying.
Can I have nginx re-request an error document from the proxied S3 bucket?
Yes. First place 404.html in your S3 bucket. Then configure your location block like this:
location /uploads {
proxy_pass YOUR_S3_BUCKET_URL;
proxy_intercept_errors on;
error_page 403 404 /uploads/404.html;
}
proxy_intercept_errors will tell nginx to handle error codes in the proxied response.
The error_page will handle the S3 error code by internally changing the request to /uploads/404.html
And finally your existing location /uploads block will fetch that 404 doc from the proxied server!
Presumably you could even fetch the error doc from a different origin:
location /uploads {
proxy_pass ORIGIN_A_URL;
proxy_intercept_errors on;
error_page 403 404 /error-docs/404.html;
}
location /error-docs {
proxy_pass ORIGIN_B_URL;
}

Nginx proxy remove spesific path and emty Post request body +HTTPS

I'm using nginx for web service proxy. I have rest service as below and i want to proxy my domain
https://www.example.com/myRestservice. Service has some method like this;
http://1.1.1.1:123/api/work/method1
http://1.1.1.1:123/api/work/method2
*By the way services publish on two server as below in nginx.conf
As result i want to access to methods of service like "https://www.example.com/Restservice/api/work/method1"..
When i try to use rewrite in nginx as below, i can access service.
But in this time Post method's request body is emty. I can see service logs.
In my nginx.config
upstream RestService {
server 1.1.1.1:123;
server 1.1.1.2:123;
}
server {
listen 443 ssl;
server name https://www.example.com;
location ~ ^/Restservice/ {
add_header Access-Control-Allow-Origin *;
rewrite ^/Restservice/(.*) /$1 break;
proxy_pass http://Restservice/;
proxy_http_version 1.1;
}
}
Bye the way i try to location part like this, result is same.
location /Restservice {
proxy_pass http://Restservice/;
}
Normally I can access soap service with config from https link.
Is it about http redirection to https ?
In nginx access log;
status : 500
request: POST /Restservice/api/work/method1 HTTP/1.1
I find the reason. Because of the endcoding.
After choosing endcoding type 'UTF-8', I could see request body.

nginx responds with 404 Not Found (Single Page App)

I have a Single Page Application with regular Browser Router (without hash). Whenever someone navigates through page and hits refresh button nginx tries to find file on this path. So if someone is on mypage.com/about nginx looks for about file and responds with 404 Not Found. How to fix this issue?
I'm thinking about specifying a location with wildcard - mypage.com/* except /api tho, because every backend endpoint in this app starts with api. How to match all paths except one? This is how my config looks like:
upstream frontend {
server frontend:3000;
}
upstream backend {
server backend:8000;
}
server {
listen 80;
location /api {
proxy_pass http://backend;
proxy_set_header Host \$http_host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
}
location / {
proxy_pass http://frontend;
proxy_redirect default;
}
}
Why do your proxy requests for frontend app ? I assume that you are using some kind of development server to serve your frontend application. It is better to build your frontend application to static files and serve them as regular static files, without any server except the nginx.
As for your question, if you will build your frontend application into static files you may configure location in nginx like this:
root /var/www/your_site;
location / {
try_files $uri /index.html;
}
where index.html is entrypoint into your application and the root path should be configured to place where it stored.
If you still want to serve frontend application from development server through nginx you may configure nginx to handle errors from upstream and point error page to root of dev server.
In this case following directives should help you:
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors
http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page

Nginx reverse proxy load upstream list from external file

I'm writing an automation to add new servers to the upstream.
Currently my upstream block is embedded in the reverse proxy configuration file with a proxy_pass http://backbones; directive in the server block.
I would like to separate the upstream block to a different file so it will be easier to parse it.
Is it possible to load the upstream block from a different file?
Thanks,
Liron
Try this:
Create a file named /etc/nginx/upstream.conf
Put you initial upstreams here:
server ip:port;
server ip:port;
Change your config (ie default.conf) to something like this:
upstream cluster {
include /etc/nginx/upstream.conf;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://cluster;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Then you can parse and edit upstream.conf and do nginx -s reload to make the configuration live.
And for proxy_pass directive?
It's possible to configure an external file ?
Thanks

How to rewrite URL to match a server using nginx?

I'm new to nginx. I have two projects, and the one is django web app which is running localhost 8000, and another is tornado which used to provide api service and running localhost 8888.
How do I config the nginx that redirects all the url requests(from 80 port) to localhost:8000 but /api requests to localhost:8888(tornado app)?
Edit your nginx config file. Add a server block and use proxy_pass in location blocks to proxy (redirect) the request.
server {
listen 80;
location / {
proxy_pass http://127.0.0.1:8000;
}
location /api {
proxy_pass http://127.0.0.1:8888;
}
}
Save it, and reload nginx.
nginx -s reload
https://gist.github.com/soheilhy/8b94347ff8336d971ad0

Resources