Not an expert on regexs,
working on a nginx project, and we are looking for a way to map the first two (2) directories levels of a uri
map $uri $my_uri {
~^(?<base_uri>.*)/[^/]+$ $base_uri;
default $uri;
}
So far this code return the base_uri without the domain/server or any filenames
But I need this original request :
http://example.com/level1/level2/file.ext
http://example.com/level1/level2/level3/file.ext
http://example.com/level1/level2/level3/level4/[...more levels...]/file.ext
to return only the first 2 levels, regex should return
/level1/level2
Please note:
sub-folders (lavel1, lavel2) will be dynamic folder names, not static.
nginx's $url variable does not include protocol/server/port from the original request. so regex is performed against /level1/level2/level3/[...]/file.ext
any help will be appreciated.
Related
Those are my two nginx rules :
rewrite ^(/v1/foobar)(.*)$ /final$2 permanent;
rewrite ^(/v1/foobar-tow)(.*)$ /final$2 permanent;
I expect that /v1/foobar-two/foo will use the second rule and then will redirect to /final/foo but I doesn't : since the URL starts with foobar, the first rule will be used and finally will redirect to final-two/foo : the concatenation of the first target and the difference between the first and second rule !
To solve the problem I've just inversed the rules, but I wonder if there is a better solution !
To sum up, this is what I'm looking for :
/v1/foobar -> /final
/v1/foobar/hello -> /final/hello
/v1/foobar-tow -> /final
/v1/foobar-tow/hola -> /final/hola
To avoid surprises with NGINX, and increase configuration scalability, you should, generally:
try to live without rewrite directive; as per NGINX author it simply appeared before location and in many cases you can now use location with capture groups in lieu of rewrite
design your regular expressions in the way that the order of matching is not important, if possible
use exact matching, where applicable
isolate regular expression locations under a prefixed one
Putting all things together:
location /v1/ {
location = /v1/foobar {
return 301 /final;
}
location ~ ^/v1/foobar/(\w+)$ {
return 301 /final/$1;
}
location = /v1/foobar-tow {
return 301 /final;
}
location ~ ^/v1/foobar-tow/(\w+)$ {
return 301 /final/$1;
}
}
I need to parse out a subdomain and add it to end of the url, for example:
subdomain.mysite.com needs to rewrite to subdomain.mysite.com/subdomain
subdomain.mysite.com/login needs to rewrite to subdomain.mysite.com/subdomain/login
Trouble arises because I have a set of reserve words that I don't want to match, for example the various different environments.
dev-web.mywebsite.com should not map to mywebsite.com/dev-web
This is what I have so far... am struggling with the nginx syntax and regex in general.
if ($host ~ ^([^.]+)\.(.+)) {
set $subdomain $1;
}
if ($subdomain ~* ^(dev-web|uat-web)$) {
rewrite ^ $scheme://$host/$subdomain$request_uri permanent;
}
The various errors I get are too many redirects or it is just not redirecting at all.
ERR_TOO_MANY_REDIRECTS
subdomain.mysite.com/subdomain/subdomain/subdomain/subdomain...
I am unable to match location with below mentioned pattern, I want to set expires header to 24 hrs. but it is not working. It works if I just use below mentioned regex :
location ~* .*abc\.php.* {
expires 24h;
}
Below example does not work.
location ~* .*abc\.php.*xyz=detail.*login_something=.* {
expires 24h;
}
There is lot of content in between and after of "abc.php" & "xyz=detail" & "login_something=" so I have to use .* only.
Thanks in advance!
There are multiple ways to achieve what you are trying to do, but the simplest method is to apply your mega regex to a variable that contains the entire URI (including the query string). This would be $request_uri
The second problem is how to manipulate expires and again, rather than use multiple blocks and have to reimplement PHP directives in each one, just use the map directive as detailed in the expires documentation.
For example:
map $request_uri $expires {
default off;
~*abc\.php.*xyz=detail.*login_something= 24h;
}
server {
...
expires $expires;
...
}
I'm trying to get a param(h=1500 for example) via regex in a server block in an nginx server but it's not working. My last try was this:
location ~ "^/app/events/(?<eventid>\d+)/(?<image>.+)?h=(?<height>\d+)$" { ...... }
Here you can check and it works: https://regex101.com/r/kP9eY9/1
But in my server block file it does't.
If I try something like this, it works:
location ~ "^/app/events/(?<eventid>\d+)/(?<image>.+)/(?<height>\d+)$" { ...... }
Instead a param like "h=300", I just use a "/300" and I can get the value in my server block file.
I'm not a expert using regex so I can't see if there is something wrong. I need your help guys! Thank you!
From the documentation:
locations of all types test only a URI part of request line without
arguments
which means the ? and anything that follows it.
As #Richard mentioned, you can't use request arguments in locations regexps.
If you need to work with request arguments in your nginx config you might use $arg_ and/or $args syntax:
http://nginx.org/en/docs/http/ngx_http_core_module.html#var_arg_
http://nginx.org/en/docs/http/ngx_http_core_module.html#var_args
I.e
location / {
if ($arg_param = 'someval') {
# some code here
}
}
I'm trying to use a Filter to force my users to login if they want to access some pages.
So my Filter has to redirect them to an error page in there's no session.
But I don't want this to happen when they visit index.html, because they can login in the index page.
So I need an URL Pattern that matches all the pages excluding / and index.xhtml.
How can I do that? Can I use regex in my web.xml ?
EDIT:
After reading this
I thought that I can make something like :
if (!req.getRequestURI().matches("((!?index)(.*)\\.xhtml)|((.*)\\.(png|gif|jpg|css|js(\\.xhtml)?))"))
in my doFilter() method, but it still processes everything.
I'm sure that the regex works because I've tested it online and it matches the files that doesn't need to be filtered, but the content of the if is executed even for the excluded files!
EDIT 2 :
I'm trying a new way.
I've mapped the Filter to *.xhtml in my web.xml, so I don't need to exclude css, images and javascript with the regex above.
Here's the new code (into the doFilter())
if (req.getRequestURI().contains("index")) {
chain.doFilter(request, response);
} else {
if (!userManager.isLogged()) {
request.getRequestDispatcher("error.xhtml").forward(request, response);
} else {
chain.doFilter(request, response);
}
}
but it still doesn't because it calls the chain.doFilter() (in the outer if) on every page.
How can I exclude my index page from being filtered?
The web.xml URL pattern doesn't support regex. It only supports wildcard prefix (folder) and suffix (extension) matching like /faces/* and *.xhtml.
As to your concrete problem, you've apparently the index file defined as a <welcome-file> and are opening it by /. This way the request.getRequestURI() will equal to /contextpath/, not /contextpath/index.xhtml. Debug the request.getRequestURI() to learn what the filter actually retrieved.
I suggest a rewrite:
String path = request.getRequestURI().substring(request.getContextPath().length());
if (userManager.isLogged() || path.equals("/") || path.equals("/index.xhtml") || path.startsWith(ResourceHandler.RESOURCE_IDENTIFIER)) {
chain.doFilter(request, response);
} else {
request.getRequestDispatcher("/WEB-INF/error.xhtml").forward(request, response);
}
Map this filter on /*. Note that I included the ResourceHandler.RESOURCE_IDENTIFIER check so that JSF resources like <h:outputStylesheet>, <h:outputScript> and <h:graphicImage> will also be skipped, otherwise you end up with an index page without CSS/JS/images when the user is not logged in.
Note that I assume that the FacesServlet is mapped on an URL pattern of *.xhtml. Otherwise you need to alter the /index.xhtml check on path accordingly.