How do I reverse proxy the homepage/root using nginx? - nginx

I'm interested in sending folks who go to the root/homepage of my site to another server.
If they go anywhere else (/news or /contact or /hi.html or any of the dozens of other pages) they get proxied to a different server.
Since "/" is the nginx catchall to send anything that's not defined to a particular server, and since "/" also represents the homepage, you can see my predicament.
Essentially the root/homepage is its own server. Everything else is on a different server.
Thoughts?

location =/ {
# only "/" requests
}
location / {
# everything else
}
More information: http://nginx.org/en/docs/http/ngx_http_core_module.html#location

Related

Nginx reverse proxy with IP in the request

am struggling finding a solution with reverse proxy.
The goal is to be able to dynamically reroute, based on URI path, the incoming requests, e.g :
https://a.b.c/23432/IP.IP.IP.IP.IP/Path should be proxied to https://IP.IP.IP.IP:23432/Path
While it is working at first sight with
location ~ ^/(?<targetport>([0-9]+)?)/(?<targethost>[^/]+) {
proxy_pass http://$targethost:$targetport;
[...]
in the end, only the first element (index.html) is served correctly. The requests made by this page (let's say js/my.js) obviously forget the return path, and are generated to access https://a.b.c/js/my.js, and fail to be served.
I tried setting http_referer (even reverse_proxying the request to it) but it doesn't help as am unable to reparse it correctly
What am I missing here ?
Thanks for your help
Problem solved, the proxied site was prefixing all the resources with /, killing the initial path

Caddy reverse proxy to /dir/ to localnet:port

I got Caddy from official repo on docker hub all up and running with automatic https on several subdomains. So far so good.
sub1.domain.com {
respond "Test"
}
https://sub1.domain.com:3333 {
reverse_proxy 192.168.7.6:3000
}
https://sub1.domain.com:4444 {
reverse_proxy 192.168.7.6:4000
}
sub2.domain.com {
respond "Test"
}
There are two things I do not understand.
1) I would rather have the proxy working on subdirs forwarding to ports, but this fails, as the dir seems to be maintained as well while proxying. Example:
https://sub1.domain.com:4444 {
reverse_proxy /dir/ 192.168.7.6:4000
}
So eventually I end up at 192.168.7.6:4000/dir/ instead of only 192.168.7.6:4000
2) When I call sub2.domain.com combined with a port from sub1 it shows a blank page (source empty as well). So for example sub2.domain.com:4444. I would rather expect a timeout or error page?
Many thanks for hints and suggestions in advance!
Matching requests does not rewrite them. So, matching on /dir/ does not change the URI of the request. It's simply a filter.
To strip a path prefix, you can do:
uri strip_prefix /dir
Since this is pretty common, there's some work to make this even easier in the future: https://github.com/caddyserver/caddy/pull/3281
For more help, feel free to ask on our forums, the audience there is much better targeted for Caddy users: https://caddy.community

getting a refused connection error when trying to do HTTP->HTTPS in lighttpd.config

I was looking at how to redirect from HTTP to HTTPS on the Lighttpd website, and it looked really easy. (https://redmine.lighttpd.net/projects/1/wiki/HowToRedirectHttpToHttps)
$HTTP["scheme"] == "http" {
# capture vhost name with regex conditiona -> %0 in redirect pattern
# must be the most inner block to the redirect rule
$HTTP["host"] =~ ".*" {
url.redirect = (".*" => "https://%0$0")
}
}
but it doesn't reroute at all.
I have been trying to access the websites by way of www.test.com, http://www.test.com, and http://test.com but it doesnt seem to work.
It just says: ERR Connection Refused. I have confirmed that the website works in http and https without this code, but when doing this, it doesnt seem to work.
I would like to understand it more since I will have a bunch of other domains routing through here eventually.
I have also tried more specific calls as well which didnt work:
$HTTP["scheme"] == "http" {
# capture vhost name with regex conditiona -> %0 in redirect pattern
# must be the most inner block to the redirect rule
$HTTP["host"] =~ "www.test.com" {
url.redirect = (".*" => "https://%0$0")
}
}
Doing the above code in the question is actually valid. The issue is, as pointed out by #Gstrauss is that in order to have redirect capabilities, you need to make sure that module is actually enabled. I looked into the modules.conf file and noticed it was not enabled.
Upon enabling the mod_redirect, and restarting the server, no matter if i went to HTTP or HTTPS version of my site, it would forward me to the HTTPS version of the site.

nginx pass rewritten URL to web server

I'm new to nginx, and I'd like to know if there is a way to pass an edited request URL to a web server. For example, I may have a web server running (Let's say apache. Or Flask.). I want all requests to /foo/(.*)$ to go to my web server, but I want my web server to see them without the foo. But if the initial request didn't have the foo, it would go somewhere else completely.
A request to /foo/bar would be routed to my web server, which would see the request simply as "/bar". However, a request that originally was made to "/bar" would be handled differently entirely. (So I don't just want to redirect).
Is there any way to do this? My thinking is that I could use this to modularize and namespace applications I write, where I could write an application as if it were routing requests on root, but it would actually be buried deeper in my site.
Thanks!!
This should do the trick (untested):
location /foo {
rewrite /[^/](/.*) $1 break;
# Pass to web server, e.g.:
#proxy_pass http://127.0.0.1:8080;
}
Note that the regular expression within the rewrite will strip any sub-directory from the request; but only one sub-directory. You could also use:
rewrite /foo(/.*) $1 break;
Which is more readable and clearer but not as powerful. This is up to you and your regular expression skills.

Sending extra header in nginx rewrite

Right now, I am migrating the domain of my app from app.example.com to app.newexample.com using the following nginx config:
server {
server_name app.example.com;
location /app/ {
rewrite ^/app/(.*)$ http://app.newexample.com/$1;
}
}
I need to show-up a popup-banner to notify the user of the domain name migration.
And I want to this based upon the referrer or some-kind-of-other-header at app.newexample.com
But how can I attach an extra header on the above rewrite so that the javascript would detect that header and show the banner only when that header is present coz the user going directly at app.newexample.com should not see that popup-banner?
The thing is that, when you "rewrite" into URI having protocol and hostname (that is http://app.newexample.com/ in your case), Nginx issues fair HTTP redirect (I guess the code will be 301 aka "permanent redirect"). This leaves you only two mechanisms to transfer any information to the handler of new URL:
cookie
URL itself
Since you are redirecting users to the new domain, cookie is no-go. But even in the case of a common domain I would choose URL to transfer this kind of information, like
server_name app.example.com;
location /app/ {
rewrite ^/app/(.*)$ http://app.newexample.com/$1?from_old=yes;
}
This gives you the freedom to process at either Nginx or in a browser (using JavaScript). You may even do what you wanted intially, issuing a special HTTP header for JavaScript in new app server Nginx configuration:
server_name app.newexample.com;
location /app {
if ($arg_from_old) {
add_header X-From-Old-Site yes;
}
}
A similar problem was discussed here. You can try to use a third-party module HttpHeadersMore (I didn't try it myself). But even if it does not work at all, with the help of this module you can do absolutely everything. Example is here.
Your redirect is missing one thing, the redirect type/code, you should add permanent at the end of your rewrite line, I'm not sure what's the default redirect code if not explicitly mentioned.
rewrite ^/app/(.*)$ http://app.newexample.com/$1 permanent;
An even better way is using return
location /app {
return 301 $scheme://app.newexample.com$request_uri;
}
Adding a get parameter as mentioned above would also be a reliable way to do it, you can easily set a session ( flash ) and redirect again to the page it self but after removing the appended get parameter.
EDIT:
Redirecting doesn't send referrer header, if the old domain is still working you could put a simple php file that does the redirect with a header call.
header("Location: http://app.newexample.com")
One possible solution without any headers would be to check the document.referrer property:
if (document.referrer.indexOf("http://app.example.com") === 0) {
alert("We moved!");
}
Using a 301 will set the referrer to the old page. If the referrer doesn't start with the old page url, it was not directed by that page. Maybe a bit quick n dirty, but should work.

Resources