I'm trying to remove trailing slash on http post method, when i try to re-write the URL using rewrite ^/(.*)/$ /$1 permanent; it doesn't work for me
The upstream should receive in this format /x/y if the Http POST is coming in these format
location /x/y/ ==> location /x/y
location /x/y ==> location /x/y
This is the nginx configuration
upstream backend {
server 127.0.0.1:8778;
# Number of idle keepalive connections per worker process.
keepalive 35;
}
location /x/y {
limit_except POST {
deny all;
}
proxy_pass http://backend;
proxy_buffering on;
include proxy.conf;
}
The problem here is when the upstream see the URI is in this format /x/y/ it rejected the request, what should be the correct rewrite rule for this so that if the http post comes in the format like /x/y or /x/y/ the upstream should always see /x/y
The permanent will cause the rewrite to generate a redirect with a 301 response. What you need is an internal adjustment of the URI before sending it upstream:
location /x/y {
rewrite ^/(.*)/$ /$1 break;
...
}
See this document for more.
Related
I have the following nginx config that handles serving my static website and redirecting requests to my REST backend:
server {
listen 80 default_server;
server_name _;
# Host static content directly
location / {
root /var/www/html;
index index.html;
try_files $uri $uri/ =404;
}
# Forward api requests to REST server
location /api {
proxy_pass http://127.0.0.1:8080;
}
}
If my REST backend goes offline the proxy module returns an HTTP status of "502 Bad Gateway" and I can redirect requests to a status page by adding the following:
# Rewrite "502 Bad Gateway" to "503 Service unavailable"
error_page 502 =503 #status_offline;
# Show offline status page whenever 503 status is returned
error_page 503 #status_offline;
location #status_offline {
root /var/www/html;
rewrite ^(.*)$ /status_offline.html break;
}
However, this will only work for requests that access the REST backend directly. How can I redirect requests to my static website in the same way whenever the backend is offline?
Nginx does have some health check and status monitoring capabilities that seem like they could be related, but I couldn't find a proper way to use them.
While its intended use case is actually for authorization, I found nginx's auth_request module to work for me:
# Host static content directly
location / {
# Check if REST server is online before serving site
auth_request /api/status; # Continues when 2xx HTTP status is returned
# If not, redirect to offline status page
error_page 500 =503 #status_offline;
root /var/www/html;
index index.html;
try_files $uri $uri/ =404;
}
It will call /api/status as a subrequest before serving the static content and will only continue when the subrequest returns an HTTP status in the 200 range. It seems to return status 500 when the server is offline.
This method might have some performance implications since you're now always doing an extra request, but that seems to be an inherent requirement of checking whether your service is online.
I think this is the correct answer - auth request is ideal for any situation where you want to "ping" a backend before returning the requested content.
I have used a similar scheme in the past for an nginx server where I wanted to check if an auth header was correct before proxying to an S3 bucket.
When doing curl -ILk http://192.168.0.4/app the Location header of the 301 redirect is http://my-srv.local/app/ which is a server-local address. I've put server_name_in_redirect on everywhere to get rid of it, but the result is the same.
Config:
server {
server_name my-nginx;
server_name_in_redirect on;
set $endpoint http://my-srv.local;
location / {
server_name_in_redirect on;
proxy_pass $endpoint;
}
}
Note: the nginx version that I'm using doesn't have absolute_redirect yet.
Reference: Information leak with automatic trailing slash redirect
How to make it point to the correct URL or prevent the leak at least?
So it's the my-srv.local who generates that response (that is pretty reasonable). With the nginx 1.11.8+ it will probably generate relative redirects. In the meantime, the possible fix is to overwrite that redirect:
server {
server_name my-nginx;
set $endpoint http://my-srv.local;
location / {
proxy_pass $endpoint;
proxy_redirect $endpoint http://$host;
}
}
I have used return or rewrite in Nginx to redirect, but both will redirect with the http header Location which has value of the full url, but I want it just value the path.
for example:
return 301 /test;
or
rewrite ^/$ /test permanent;
will has the Location value of
http://www.example.com/test
but I want it be just
/test
I wonder if it is possible.
Solved.
as of 1.11.8, just set the directive(Thanks to #RichardSmith):
absolute_redirect off;
before 1.11.8, I find a wonderful answer(Thanks to #xiaochen):
https://stackoverflow.com/a/39462409
May I ask Where and How to redirect
http://domain.com, http://www, https://domain.com
to
https://www
?
Where
In your Nginx config file (the main or vhost depending on your setup)
How
Try rewrite:
server {
listen 80;
server_name www.domain.com domain.com;
rewrite ^ https://www.doamin.com$request_uri? permanent;
}
or return:
server {
listen 80;
server_name www.domain.com domain.com;
return 301 https://www.domain.com$request_uri
}
Choice is your when it comes to Return vs Rewrite:
REWRITE
Only the part of the original url that matches the regex is rewritten.
Slower than a Return.
Returns HTTP 302 (Moved Temporarily) in all cases, irrespective of permanent.
Suitable for temporary url changes.
RETURN
The entire url is rewritten to the url specified.
Faster response than rewrite.
Returns HTTP 301 (Moved Permanently).
Suitable for permanent changes to the url.
No need to set permanent.
Officila Nginx Docs on return/rewrite.
Some solutions about redirection can be found. But what I want to do is redirecting part of requests to another server, specifically, only when a request url includes string "service". For example:
http://localhost/service/image-------------> http://localhost:8080/service/image
http://localhost/service/image/upload------> http://localhost:8080/service/image/upload
http://localhost/service/blog--------------> http://localhost:8080/service/blog
.....
.................................................................................................................................................................
but blow will still served by ngnix,cause no "service" included within url
http://localhost/wiki/....
http://localhost/video/....
How to do this?
You need to use location regex matching together with proxy_pass, example:
upstream apache {
server 127.0.0.1:8080;
}
# in your server block:
server{
# location matching is prioritized by accuracy and order of definition
location ~* ^/service {
proxy_pass http://apache;
proxy_redirect off;
}
}
^/service will match any request beginning with /service and forward it to Apache.
proxy_pass is transparent for the user, i.e. it will forward the request to Apache and return the output to the user.
For more info on location matching, checkout http://wiki.nginx.org/HttpCoreModule#location
If I understood you correctly:
location / {
if ($request_uri ~* "^/service/.*") {
rewrite ^ http://localhost:8080$request_uri permanent;
}
}
P.S. did not check