NGINX subdomain Redirect issue - nginx

I am trying to redirect my new site subdomin in nginx
www.test.com/video/ >>> www.test.com/v/
want to rewrite /video/ to /v/ though
so i tried this in nginx conf.d
server {
server_name www.test.com/video/;
return 301 http://www.test.com/v/$request_uri;
}
and
server {
server_name www.test.com/video/;
rewrite ^(.*) http://www.test.com/v/ permanent;
}
even this
server {
listen 80;
server_name www.test.com/video/;
location / {
proxy_pass http://www.test.com/v/;
}
}
but its always redirect to a fix url
curl -I http://www.test.com/v/
HTTP/1.1 301 Moved Permanently
Server: awselb/2.0
Date: Mon, 10 Oct 2022 12:14:03 GMT
Content-Type: text/html
Content-Length: 134
Connection: keep-alive
Location: https://www.test.com:443/v/
Can anyone help me with this ? What is wrong here ?
Any help would be appreciated.

So, /v is the real name and you want to tunnel /video calls to it.
Maybe a configuration like this could match :
server {
listen 8022; # so 74014922;
server_name www.test.com; # here your server name
root D:/WEB; # and here the root path of your site (I'm under Windows, sorry ^^)
location /video { # the path from root directive value
proxy_pass http://www.test.com/v;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
EDIT : alternative - nginx redirection
Finally, I think there is no need to look further a native redirection, as follow :
location /video {
rewrite /video(.*)$ /v$1 redirect;
}
As far as we can hope, it should do the job, please let me know.

Related

Nginx Https Redirect with Trailing Slash and Query Parameters

I have an Nginx server config that already redirects http requests to https, but I'm trying to figure out the proper way to modify this code or completely change it to redirect http requests to https and add a trailing forward slash /, when the url does not contain one. These redirects should also ensure that query parameters still exist despite the redirect. I have seen where most answers to similar questions to mine have referenced ^/(.*)/$ as the code for adding a forward slash, but I'm not sure how to use it and if I should use a rewrite over an if. Can anyone help clear up my confusion?
nginx.config:
upstream nodejs {
server 127.0.0.1:8081;
keepalive 256;
}
server {
listen 8080;
if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; }
location / {
proxy_pass http://nodejs;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
gzip on;
gzip_comp_level 4;
gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
}
Goal:
http://www.example.com/page-one -> http://example.com/page-one/
http://example.com/page-two -> https://www.example.com/page-two/
https://www.example.com/page-three?page=2 -> https://www.example.com/page-three/?page=2
The three steps in your goals are each performed in different ways. The first step is best achieved using separate server blocks. The second step you already have in your question. The third step uses a rewrite statement.
For example:
server {
listen 8080 default_server;
return http://example.com$request_uri;
}
server {
listen 8080;
server_name example.com;
if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; }
rewrite ^(.*[^/])$ $1/ permanent;
...
}
The existing query string is also appended to the rewritten URL. See this document for details.

Nginx Content disposion - Trim file name

I will briefly tell my problem, I need to trim the first 14 characters (0-9 and -), when downloading a file, it is just about header Content-Disposition, how to achieve something like that?
I want the file to look like this:
1235467890123-FileName.txt
for such
FileName.txt
Config file:
upstream oxide_io {
ip_hash;
server 127.0.0.1:xxx;
server 127.0.0.1:xxx;
server 127.0.0.1:xxx;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name oxidepolska.pl;
error_log /var/log/nginx/forum-error.log error;
ssl ***
proxy_hide_header X-Powered-By;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
gzip ***
location #oxide {
proxy_pass http://oxide_io;
}
location ~ ^/assets/(.*) {
root /var/www/forum/;
try_files /build/public/$1 /public/$1 #oxide;
}
location /plugins/ {
root /var/www/forum/build/public/;
try_files $uri #oxide;
}
location ~ ^/public/uploads/files/(.*)$ {
root /var/www/forum/public/uploads/files/;
add_header Content-Disposition 'inline; filename="$1"';
}
location / {
proxy_pass http://oxide_io;
}
error_page 502 503 /503.html;
location = /503.html {
root /var/www/forum/public/;
}
}
server {
if ($host = oxidepolska.pl) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name oxidepolska.pl;
}
As I finally understand, you are trying to get rid of timestamp prefix added to files uploaded on some forum? Here is the another config, manually adding Content-Disposition header:
map $uri $content_disposition {
'~/\d{13}-([^/]+)$' 'attachment; filename="$1"';
}
server {
...
location <uploaded_files_location> {
add_header Content-Disposition $content_disposition;
}
...
}
When requested file is not matching the pattern \d{13}- (13 digits and "-" sign before the rest of filename), $content_disposition variable evaluated as empty string, so Content-Disposition header is not added to response.
➜ ~ curl -I https://ddl.oxidepolska.pl/1544820059040-lootconfig.zip
HTTP/2 200
server: nginx
date: Fri, 14 Dec 2018 21:54:56 GMT
content-type: application/zip
content-length: 7138
last-modified: Fri, 14 Dec 2018 20:40:59 GMT
etag: "5c14155b-1be2"
accept-ranges: bytes
Disclaimer: This answer is about modifying existing Content-Disposition header, which is not what required by OP.
map $upstream_http_content_disposition $content_disposition {
default $upstream_http_content_disposition;
'~^(.*filename="?)[-\d]{14}(.+?)("?$)' $1$2$3;
}
server {
...
location #oxide {
proxy_pass http://oxide_io;
proxy_hide_header Content-Disposition;
add_header Content-Disposition $content_disposition;
}
...
location / {
proxy_pass http://oxide_io;
proxy_hide_header Content-Disposition;
add_header Content-Disposition $content_disposition;
}
...
}
(assuming first 14 characters can be only 0-9 and '-')

Proxy_pass ignoring port

I have a CentOS server running NGINX listening to 80 and a DB servering an app on 8080. I want to be able to Type
http://example.com/dev/abc
and have it actually access
http://example.com:8080/apex/abc or http://localhost:8080/apex/abc
I have used this location configuration
location /dev {
proxy_pass http://example.com:8080/apex;
}
However when I try it out the url displayed is
http://example.com/apex/apex
the page is not found and the log says:
2018/06/14 12:51:33 [error] 7209#0: *2067 open()
"/usr/share/nginx/html/apex/apex" failed (2: No such file or directory),
client: 124.157.113.187, server: _, request: "GET /apex/apex HTTP/1.1", host: "example.com"
Looks like two strange things are happening
1) Port 80 not 8080 is being used despite the proxy_pass
2) why is apex twice "/apex/apex/"
Help please :)
Adding entire Server block from config file:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location /dev {
proxy_pass http://example.com:8080/apex;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
Update - More information on what the app that might help
The app is Oracle Application Express (APEX) it listens on port 8080.
The URL works as follows:
HTTP://example.com:8080/apex/f?p=[APP]:[Page]:[Session] etc
Where [APP],[Page] and [Session] are all corrisponding numbers
The development environment url is actualy:
http://example.com:8080/apex/f?p=4550
This is the default so if I try http://example.com:8080/apex/ it defaults to http://example.com:8080/apex/f?p=4550 and takes you to the login page
Everything after the app number never changes so that is what I want to replaced by /dev/ http://example.com:8080/apex/f?p=4550:1 -> http://example.com/dev/:1
Once I have leant how this works, I plan to setup three proxy_pass's
example.com/dev ->
http://example.com:8080/apex/f?p=4550
example.com/desktop ->
http://example.com:8080/apex/f?p=1001
example.com/mobile ->
http://example.com:8080/apex/f?p=201
Where the only thing that changes is the app number.
Rewrites are working fine for all three but I don't want the rewrite to be visible in the URL
Here are the rewrites:
location ~ /dev {
rewrite ^/dev(.*) http://smallblockpro.com:8080/apex$1 last;
}
location ~ /desktop/ {
rewrite ^/desktop/(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;
}
location ~ /desktop {
rewrite ^/desktop(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;
}
location ~ /mobile/ {
rewrite ^/mobile/(.*) http://smallblockpro.com:8080/apex/f?p=201:$1 last;
}
location ~ /mobile {
rewrite ^/mobile(.*) http://smallblockpro.com:8080/apex/f?p=201:$1 last;
}
location ~ /desktop/ {
rewrite ^/desktop/(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;
}
The reason you're getting the :8080 port number shown up to the user is because you use absolute URLs in your rewrite directives, which results in NGINX producing 301 Moved responses directly to the user — your presumed expectation that it'll still go through proxy_pass after a rewrite like that is incorrect, see http://nginx.org/r/rewrite:
If a replacement string starts with “http://”, “https://”, or “$scheme”, the processing stops and the redirect is returned to a client.
If you want to just create the mapping between /desktop/$1 on the front-end and /apex/f?p=1001:$1 on the back-end of your Oracle Application Express (APEX), then the best way would be to use the following code on your nginx front-end server:
location /desktop/ {
rewrite ^/desktop/?(.*)$ /apex/f?p=1001:$1 break;
return 400;
proxy_pass http://smallblockpro.com:8080;
}
I would recommend copy-pasting it for each of /dev/, /mobile/ and /desktop/; also, I would not recommend to keep a slash-less versions, as per ServerFault's nginx-reverse-proxy-url-rewrite and how-to-remove-the-path-with-an-nginx-proxy-pass, as nginx already takes care of the requests without the trailing slash in a situation such as yours with the code as I propose above.
Here's the copy-paste from what I'm using on our ORDS / SDW ( sqldev-web ) development server.
Here's a basic example with ORDS for the REST side of the house.
The access is to:
https://xyz.oraclecorp.com/sdw/klrice/metadata-catalog/
Then it's proxied to:
https://xyz.oraclecorp.com:8083/ords/klrice/metadata-catalog/
With this config. Beside not to rewrite to an absolute URI as that will do a full browser redirect vs just rewriting the url for the proxy pass.
location /sdw/ {
rewrite /sdw/(.*) /ords/$1 break;
proxy_pass https://xyz.oraclecorp.com:8083/ords/;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
The issue you will face is this
rewrite ^/desktop/(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;
APEX will see and write links/redirects/includes ( javascript/css/...) as the .../apex/XYZ which will hit the nginx server and that will not know what to do with a /apex/
Here's an example of that based on my above setup. Notice my request to /sdw/ turns into a Location redirect to /ords/
wget -S https://xyz.oraclecorp.com/sdw/
--2018-06-21 17:10:28-- https://xyz.oraclecorp.com/sdw/
Resolving xyz.oraclecorp.com... 123.456.789.123
Connecting to xyz.oraclecorp.com|123.456.789.123|:443... connected.
HTTP request sent, awaiting response...
HTTP/1.1 302 Found
Server: nginx/1.12.1
Location: https://xyz.oraclecorp.com/ords/f?p=4550:1:375440000433:::::
Location: https://xyz.oraclecorp.com/ords/f?p=4550:1:375440000433::::: [following]
So the easiest thing to do is match up the ords deployment ( /apex/ ) to what the rewrite/redirects are and use proxy pass to internalize the :8080 stuff. So
location ~ /desktop/ {
rewrite ^/desktop/(.*) http://smallblockpro.com/apex/f?p=1001:$1 last;
}
location ~ /apex/ {
proxy_pass http://smallblockpro.com:8080/apex/;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
This option will let your users have a nice entry point of /desktop/ but then that redirect the /apex/ for the app itself.
There is another option with ORDS url-mappings.xml to keep the /desktop/ also which would be something like this to add in mappings to ords so it knows the /desktop/. Then the nginx could do the same proxy pass for each of the entry urls.
url-mapping.xml file contents
<pool-config xmlns="http://xmlns.oracle.com/apex/pool-config">
<pool name="mypool" base-path="/desktop" />
</pool-config>
then in nginx
location ~ /desktop/ {
proxy_pass http://smallblockpro.com:8080/desktop/;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Before you read further go through below SO thread which explains about the extra /apex/
Nginx proxy_pass only works partially
Two issues in your config
You need to pass the correct URL to backend service
You need to make sure you handle any redirects and replace the url correctly
Below is the config I think should work for you
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location /dev/ {
proxy_pass http://example.com:8080/apex/;
proxy_redirect http://example.com:8080/apex/ $scheme://$host/dev/;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

Jenkins - NGINX reverse proxy broken

I just moved our jenkins to a new machine behind a reverse proxy, before it was straight on the intranet. And I've started seeing the error "It appears that your reverse proxy setup is broken."
So I copied the recommended nginx config straight, modifying slightly for our needs but the warning remains, leaving me slightly confused and posting here.
upstream jenkins {
keepalive 32; # keepalive connections
server 127.0.0.1:8080; # jenkins ip and port
}
server {
listen 80; # Listen on port 80 for IPv4 requests
server_name jenkins.domain.tld;
#this is the jenkins web root directory (mentioned in the /etc/default/jenkins file)
root /usr/share/jenkins;
access_log /var/log/nginx/jenkins/access.log;
error_log /var/log/nginx/jenkins/error.log;
ignore_invalid_headers off; #pass through headers from Jenkins which are considered invalid by Nginx server.
location ~ "^/static/[0-9a-fA-F]{8}\/(.*)$" {
#rewrite all static files into requests to the root
#E.g /static/12345678/css/something.css will become /css/something.css
rewrite "^/static/[0-9a-fA-F]{8}\/(.*)" /$1 last;
}
location /userContent {
#have nginx handle all the static requests to the userContent folder files
#note : This is the $JENKINS_HOME dir
root /var/lib/jenkins/;
if (!-f $request_filename){
#this file does not exist, might be a directory or a /**view** url
rewrite (.*) /$1 last;
break;
}
sendfile on;
}
location #jenkins {
sendfile off;
proxy_pass http://jenkins;
proxy_redirect default;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_max_temp_file_size 0;
#this is the maximum upload size
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_request_buffering off; # Required for HTTP CLI commands in Jenkins > 2.54
proxy_set_header Connection ""; # Clear for keepalive
}
location / {
# Optional configuration to detect and redirect iPhones
if ($http_user_agent ~* '(iPhone|iPod)') {
rewrite ^/$ /view/iphone/ redirect;
}
try_files $uri #jenkins;
}
}
So it's reached at jenkins.domain.tld and I'm out of ideas on how to troubleshoot this. The requests log properly, nothing in the error log, jenkins seems to work in other ways....but the proxy tests gives a 404?
$: curl -iL -e http://jenkins.domain.tld/jenkins/manage http://jenkins.domain.tld/jenkins/administrativeMonitor/hudson.diagnosis.ReverseProxySetupMonitor/test
HTTP/1.1 404 Not Found
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 26 Mar 2018 06:50:30 GMT
Content-Type: text/html;charset=iso-8859-1
Content-Length: 391
Connection: keep-alive
X-Content-Type-Options: nosniff
Cache-Control: must-revalidate,no-cache,no-store
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 404 Not Found</title>
</head>
<body><h2>HTTP ERROR 404</h2>
<p>Problem accessing /jenkins/administrativeMonitor/hudson.diagnosis.ReverseProxySetupMonitor/test. Reason:
<pre> Not Found</pre></p><hr>Powered by Jetty:// 9.4.z-SNAPSHOT<hr/>
</body>
</html>
Jenkins URL in system config is also set to jenkins.domain.tld.

NGINX location directives for the same location

I have a Nexus Repository Manager OSS 3.0 running behind NGINX as a private docker registry. My Docker client (not the official docker client) is expecting a 200 OK and an empty JSON string {} to be returned from /v2/. The problem i'm running into is that Nexus returns the 200 OK but an empty string.
My work-around is to have NGINX return a file containing an empty JSON string for /v2/ requests and proxy /v2/* requests to Nexus.
server {
listen 443 ssl;
server_name nexus.example.com;
ssl_certificate ssl/server.crt;
ssl_certificate_key ssl/server.key;
location = /v2/ {
root /home/ubuntu/www;
index empty.json;
}
location /v2/ {
proxy_pass http://localhost:5000;
proxy_set_header Host $http_host; # required for docker client's sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
}
I would expect this to work, but it directs all traffic (/v2/, /v2/_catalog, /v2/myimage/manifests/latest, etc) to the proxy_pass. How can I make /v2/ requests go to the location to sever the empty.json file?
So you have placed a file at /home/ubuntu/www/v2/empty.json?
The problem is that the index directive will rewrite the URI to /v2/empty.json which is then processed by the location /v2/ block.
One solution would be to create another location to match the rewritten URI and serve it as a static file:
root /home/ubuntu/www;
location = /v2/ {
index empty.json;
}
location = /v2/empty.json {
}
Another solution is to use the error_page directive. But you will still need to specify a location and root to handle the static file(s):
location = /v2/ {
return 405;
error_page 405 =200 /static/empty.json;
}
location / {
root /home/ubuntu/www;
}

Resources