nginx pass rewritten URL to web server - nginx

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.

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

Nginx forwarding to different app's different path using `#` symbol

Quick question. We have two apps. Ports 3001 and 3002. Our domain is www.domain.com.
What we want to have it once person enters www.domain.com/pathname we want them to be redirected into another app's specific path.
How to do it?
We already came up to this in my nginx
location /pathname/ {
proxy_pass http://127.0.0.1:3002/;
}
It nearly works. However, our app under 3002 works on path /#/pathname.
We can access it by typing www.domain.com/pathname/#/pathname. We want to access same link by typing www.domain.com/pathname.
How to shorten it? What do I miss?
(upd) Just redirect /pathname to /pathname/#/pathname
According to your comment, you want just redirect from /pathname to /pathname/#/pathname
Try these combined directives:
rewrite to append # and fragment identifier
and proxy_pass to reverse proxy to the app.
E.g.:
location /short_path_name/ {
rewrite ^ /pathname/#/$uri permanent;
break;
}
location /pathname/ {
proxy_pass http://127.0.0.1:3002/;
}
And use www.domain.com/short_path_name/ link for your app.
Unfortunately, nginx can't see the fragment identifier
Unfortunately, you can't. Because server never get the fragment identifier from browser.
The fragment identifier functions differently to the rest of the URI: its processing is exclusively client-sided with no participation from the web server
Naming a bit amusing, but it has a long history. See TBL (1997): Fragment Identifiers on URIs:
The URI reference is a thing you build by taking a URI for an information object, adding a "#" sign and then a Fragement identifier. (The last term is historical, so try not to thinl of it necessarily identifying a fragment).
Workarounds
There are workarounds, e.g. encode hashtag symbol into %23 but I'm not sure is it your way.
Handle request arguments with nginx
Note: rewriting url, nginx can preserve request arguments if you add ? at the end of rewrite directive.
See Nginx rewrite manual:
If a replacement string includes the new request arguments, the previous request arguments are appended after them. If this is undesired, putting a question mark at the end of a replacement string avoids having them appended, for example:
rewrite ^/users/(.*)$ /show?user=$1? last;

Rewriting URLs from PHP Slim in Nginx Web Server

I have a question here. I am developing a PHP SLIM framework application hosted for example on mydomain.com and one of my routes is grouped "api" like this:
$app->group(
'/api',
function () {
// All my API routes are here
}
);
I am able to access all my API routes by calling mydomain.com/api/{endpoint}. After deploying my application to production running Nginx, I was asked to convert all my URLs to: api.mydomain.com/{endpoint}. So I created a subdomain and used the code below that I have placed into my nginx configuration file:
location ^~ / {
rewrite ^/(.*$) mydomain.com/api/$1 last;
}
It is supposed to map any calls to api.mydomain.com to mydomain.com/api. However, it only works when an API call is one level for example, the following will work:
api.mydomain.com/resource1
api.mydomain.com/resource2
It will fail when using 2 levels, for example the following will fail. I get a "Method Not Allowed" error.
api.mydomain.com/resource1/inresource1
However when I call mydomain.com/api/resource1/inresource1 i get a successful request. I am not sure what I am doing wrong. I figure it has something to do with my rewrite script and the arguments. I am hoping someone can point me into the right direction.
Regards
The solution was pretty simple (works for me). All I had to do was change my location script to:
location / {
proxy_pass mydomain.com/api;
}
That way it forwards all requests (GET and POST) approriately.

IIS to handle request transfer to other server (without url rewrite)

I want my website to serve static contents by different server and if possible even javascripts files as well from another server. I know it can be achieved using url rewrites but it gives 301 errors (i.e. extra round trip to browser). I asked similar question here but did not get any satisfactory response as it seems my question was not correct.
Can some one suggest how to achieve this without extra round trip to browser? I have seen other teams achieving this in Apache server but not able to find how to do it in IIS.
Have you tried "Rewrite" instead of "Redirect"? These are at least two viable options of rewriting where Redirect means 301/302 and rewrite operates silently at the server.
From your other question, it seems that you tried with "Redirect", this explains the 301. Change Redirect to Rewrite then.
The only important thing is that if you want your rewrites act between different servers, you will need the ARR (Application Request Routing) installed on a front-end server. While URL Rewrite handles only local rewrites, ARR can act as a transparent proxy to other servers.
ARR is a free add-on to IIS
http://www.iis.net/downloads/microsoft/application-request-routing

How does url rewrite works?

How does web server implements url rewrite mechanism and changes the address bar of browsers?
I'm not asking specific information to configure apache, nginx, lighthttpd or other!
I would like to know what kind of information is sent to clients when servers want rewrite url?
There are two types of behaviour.
One is rewrite, the other is redirect.
Rewrite
The server performs the substitution for itself, making a URL like http://example.org/my/beatuful/page be understood as http://example.org/index.php?page=my-beautiful-page
With rewrite, the client does not see anything and redirection is internal only. No URL changes in the browser, just the server understands it differently.
Redirect
The server detects that the address is not wanted by the server. http://example.org/page1 has moved to http://example.org/page2, so it tells the browser with an HTTP 3xx code what the new page is. The client then asks for this page instead. Therefore the address in the browser changes!
Process
The process remains the same and is well described by this diagram:
Remark Every rewrite/redirect triggers a new call to the rewrite rules (with exceptions IIRC)
RewriteCond %{REDIRECT_URL} !^$
RewriteRule .* - [L]
can become useful to stop loops. (Since it makes no rewrite when it has happened once already).
Are you talking about server-side rewrites (like Apache mod-rewrite)? For those, the address bar does not generally change (unless a redirection is performed).
Or are you talking about redirections? These are done by having the server respond with an HTTP code (301, 302 or 307) and the location in the HTTP header.
There are two forms of "URL rewrite": those done purely within the server and those that are redirections.
If it's purely within the server, it's an internal matter and only matters with respect to the dispatch mechanism implemented in the server. In Apache HTTPD, mod_rewrite can do this, for example.
If it's a redirection, a status code implying a redirection is sent in the response, along with a Location header indicating to which URL the browser should be redirected (this should be an absolute URL). mod_rewrite can also do this, with the [R] flag.
The status code is usually 302 (found), but it could be configured for other codes (e.g. 301 or 307).
Another quite common use (often unnoticed because it's usually on by default in Apache HTTPD) is the redirection to the the URL with a trailing slash on a directory. This is implemented by mod_dir:
A "trailing slash" redirect is issued
when the server receives a request for
a URL http://servername/foo/dirname
where dirname is a directory.
Directories require a trailing slash,
so mod_dir issues a redirect to
http://servername/foo/dirname/.
Jeff Atwood had a great post about this: http://www.codinghorror.com/blog/2007/02/url-rewriting-to-prevent-duplicate-urls.html
How web server implements url rewrite mechanism and changes the address bar of browsers?
URL rewriting and forwarding are two completely different things. A server has no control over your browser so it can't change the URL of your browser, but it can ask your browser to go to a different URL. When your browser gets a response from a server it's entirely up to your browser to determine what to do with that response: it can follow the redirect, ignore it or be really mean and spam the server until the server gives up. There is no "mechanism" that the server uses to change the address, it's simply a protocol (HTTP 1.1) that the server abides by when a particular resource has been moved to a different location, thus the 3xx responses.
URL rewriting can transform URLs purely on the server-side. This allows web application developers the ability to make web resources accessible from multiple URLs.
For example, the user might request http://www.example.com/product/123 but thanks to rewriting is actually served a resource from http://www.example.com/product?id=123. Note that, there is no need for the address displayed in the browser to change.
The address can be changed if so desired. For this, a similar mapping as above happens on the server, but rather than render the resource back to the client, the server sends a redirect (301 or 302 HTTP code) back to the client for the rewritten URL.
For the example above this might look like:
Client request
GET /product/123 HTTP/1.1
Host: www.example.com
Server response
HTTP/1.1 302 Found
Location: http://www.example.com/product?id=123
At this point, the browser will issue a new GET request for the URL in the Location header.

Resources