nginx remove extra trailing slash ate the end of URL - web-services

I have this configuration inside server block which redirects all http requests to the https server with a 301, moved permanently status.
The problem is that in Screaming Frog or Chrome I can see that http://kida.al is redirected to https://kida.al// and then to https://kida.al/.
How can I prevent such a thing?
Thanks!
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name kida.al;
return 301 https://$server_name$request_uri/;
}

You should remove the extra trailing slash from the end of your redirection path:
return 301 https://$server_name$request_uri;

Related

Nginx - https://www not 301 redirecting

I am moving to a new domain and have set up 301 redirects on my ec2 instance.
Currently I have the following:
server {
listen 80;
server_name olddomain.co.uk;
return 301 $scheme://www.newdomain.com$request_uri;
}
this works fine for www.olddomain.co.uk and olddomain.co.uk. However it does not work for https://www.olddomain.co.uk
I am wondering how I can make it so the redirect also works with https://www...
Thanks
Your server isn't listening to https:// i.e. 443 port. Connection to https://www.olddomain.co.uk would simply be refused. Add proper ssl configurations to your nginx file and it should be fine.
server {
listen 80;
listen 443 ssl;
server_name olddomain.co.uk;
return 301 $scheme://www.newdomain.com$request_uri;
}
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}

Nginx redirect (non-www to www) not working with Certbot

I have a website running with a Python/Django/uWSGI/Nginx setup. I also use Certbot to enable https on my site. My redirects from non-www to www (e.g. "example.com" to "www.example.com") result in a "Bad Request (400)" message even though I couldn't spot any deviations from the Nginx/Certbot documentation. Here is the relevant part of my sites-available Nginx code:
server {
listen 80;
server_name example.com www.example.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/myname/example;
}
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/activities.sock;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; #managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; #managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
if ($scheme != "https") {
return 301 https://$host$request_uri;
} # managed by Certbot
}
I found a similar StackOverflow answer (Nginx: redirect non-www to www on https) but none of the solutions worked for me. I have SSL certificates for both example.com and www.example.com. I also tried creating a separate 443 ssl server block for example.com based on the comments in that answer but it didn't work either. My sites-available and sites-enabled code is the same.
What am I doing wrong?
It seems that server_name when translated to the $host variable selects the first in the list of server_name. Let me know if that works. I can't quite test this currently.
Try swapping server_name to server_name www.example.com example.com; as well as changing return 301 https://$host$request_uri; to return 301 https://$server_name$request_uri;
server {
server_name www.example.com example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
# SSL CERT STUFF.
server_name example.com;
return 301 https://www.$server_name$request_uri;
}
server {
listen 443 ssl;
# SSL CERT STUFF.
server_name www.example.com;
# LOCATION STUFF
}
This is not an efficient configuration for Nginx request processing. It's messy, your if condition gets evaluated on every request and I don't see where your non www to www is even meant to happen.
I'd split http and https:
server {
listen 80 default_server;
return 301 https://www.example.com$request_uri;
}
Thats all non https traffic taken care of in a single redirect. Now for the https:
server {
listen 443 default_server ssl;
server_name www.example.com;
root # should be outside location blocks ideally
......
}
The default server directive means this server will handle any requests which do not have a matching server configuration. If you don't want that then add example.com after www.example.com, not before it. Any requests ending up here will display the first entry in the client browser bar.
Based on your comments you might need to add a separate block for the other domain to avoid an SSL certificate mismatch. Try this:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate .....;
ssl_certificate_key .....;
return https://www.example.com$request_uri;
}
Although the OP has accept one of the answers as the solution, I just want to point out that it may not be the best practice.
The correct way is to use $host instead of $server_name (as per Mitchell Walls' example) or hardcoded www.exmple.com (as per miknik's example). Both results an extra 443 server directive that is not necessary and messy.
server {
listen 80 default_server;
server_name www.example.com example.com;
root /var/www/html; # define your root directory here
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
# SSL CERT STUFF.
#server_name www.example.com; you don't need to specify again here
# LOCATION STUFF
}
There is a difference between $host and $server_name:
$host contains "in this order of precedence: host name from the request line, or host name from the 'Host' request header field, or the server name matching a request".
$server_name contains the server_name of the virtual host which processed the request, as it was defined in the nginx configuration. If a server contains multiple server_names, only the first one will be present in this variable.

Rewrite to another TLD for all subdomains

I want to achieve the following rewrite with nginx:
example.com -> example.io
*.example.com -> *.example.io
So anything that is related to example.com should be redirected to example.io, while preserving the subdomain if there is one.
You just need a simple server block to listen on example.com and redirect to example.io
http {
map $server_name $redirect_to {
default example.io;
"~*^(.*)\.example.com$" $1.example.io;
}
server {
listen 80;
listen 443 ssl;
server_name example.com *.example.com;
ssl_certificate ...;
ssl_certificate_key ....;
return 302 $scheme://$redirect_to$request_uri;
}

Nginx regex and wildcard for location

I am stuck with one issue. I am trying to hit
http://localhost/api/hello/somename
Now somename could be anything sam or phil,
now my config file of nginx is below.
server {
listen 80 default_server;
server_name _;
location ~ ^/api/(.*)$ {
proxy_pass http://localhost:8081/api/hello/$1;
}
}
Where I am wrong ? Can you pls help me to fix. Actually on 8081 container is running.
You don't need to make it this complex. You could just it as simple as below
server {
listen 80 default_server;
server_name _;
location /api/ {
proxy_pass http://localhost:8081/api/;
}
}
And that should pass anything starting with /api to http://localhost:8081/api/, with the request uri after /api/ appended
/ should be escaped
.* is anything. If you know there should be names and / between them say it
^https?:\/\/\w+\/api(?:\/\w+)*$
http or https then : then //, then a word, then /api, then maybe some /word
test

regex infinite subdomains in nginx

I've following nginx config that matches main domain and redirects to new one, also matches 1 level down subdomain and redirects to new domain.
I'm missing case of subdomain of subdomain. e.g. sub.sub.domain.com or sub.sub.sub.sub.domaon.com or infinite levels really.
Any ideas how to safely regex this out?
server {
listen 80;
server_name domain.de.com;
return 301 $scheme://domain.com$request_uri;
}
server {
listen 80;
server_name ~^(?<subdomain>[^.]+)\.domain\.de\.com$;
return 301 $scheme://$subdomain.domain.com$request_uri;
}