I have a rule which is not working correctly.
I need it so that whenever URL xxx.com/forum/css.php is hit, it is re-written to xxx.com/forum/core/css.php.
I have written the following location block for it:
location ~^ /forum/css.php {
rewrite ^ /forum/core/css.php permanent;
}
Also needing to be taken into account is that the file is a factory so it accepts parameters, the url being hit actually looks like xxx.com/forum/css.php?x=123&y=string. Will this also be taken into account in the re-writes or does it need to be specified? Sorry if the question seems silly I am just beginning to work with servers! Thanks fellow coders!
To rewrite a single URI (with or without query string) you could use a location =:
location = /forum/css.php {
rewrite ^ /forum/core/css.php permanent;
}
The rewrite directive appends the query string (unless terminated with ?). See this and this for more.
Related
I want to rewrite an argument given via URL on my nginx server from "my_arg" to "my-arg". The problem is that I can't know how many arguments there will be in advance nor the position of these arguments.
I can only know if the arguments is there using :
if ($args ~ (.*)my_arg=(.*)) {
rewrite ....
}
But i cannot achieve to only change the name of this argument without changing every others.
Thanks by advance
For anything except HTTP 301/302 redirection you'd better just change an $args variable value:
if ($args ~ (^|.*&)my_arg=(.*)) {
set $args $1my-arg=$2;
}
If you want to generate a redirect, things will be more complicated. Since any rewrite directive performs its own URI matching against some regex pattern, all the $1, $2 and so on variables from previous matching will be overwritten, and you can't match a query part of the URI to get them re-evaluated since rewrite directive works with normalized URI that doesn't include a query part. Your only way is to use named capture groups:
if ($args ~ (?<prefix>^|.*&)my_arg=(?<suffix>.*)) {
rewrite ^ $uri${prefix}my-arg=$suffix? <redirect|permanent>;
}
Trailing question mark used intentionally since as rewrite directive documentation says,
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;
I am trying to use Nginx rewrite static file path to strip the hash added for cache busting. The hash is always 10-symbol long. For example,
/min/3rd.party.min.1234567899.js has to become /min/3rd.party.min.js
I have tried this, but it doesn't work (fails at configtest) and also looks way to complicated.
location /min/ {
root /opt/app/public;
rewrite ^.*(?<=(.))[a-z0-9]{10}[.](?=(js|css))[js|css]$ $1$3;
}
I have no idea how you arrived at your regular expression pattern, but the following seems to work:
rewrite "^(.*)\.\w{10}\.(js|css)$" $1.$2 break;
Any pattern that contains a brace, must be placed within quotes. Use the break suffix to process the rewritten URI within the same location. See this document for details, and this useful resource on regular expressions.
I have categories I'd like to rewrite.
for example:
example.com/videos?c=18
to:
example.com/category/name
I tried to do this using multiple examples, most had no effect and this example gave me only page not found to all /videos pages:
location /videos {
if ($args ~ "c=18") {
rewrite ^/videos(.*) http://$server_name/category/name$1 permanent;
}
}
Is this even doable purely via Nginx what I am trying to achieve?
As far as I got the question, currently your site has this url scheme, which you can't change:
http://example.com/videos?c=18
But you would like to present visitors with "pretty"-looking URLs like
http://example.com/category/name
That pretty URL does not really exist anywhere on the site, which is why you have to rewrite it, e.g. turn pretty virtual url into a real one that your scripts can process.
Once again, you rewrite from virtual to actual, not the other way round.
The following directive would turn /category/cars/ into /videos?c=cars
location /category {
rewrite ^/category/(.*)$ /videos?c=$1 last;
}
But your script won't understand /videos?c=cars url, it needs category ID to work. So in your case the pretty url should look like
http://example.com/category/18
which will be rewritten to
http://example.com/videos?c=18
"if" directive is not best solution, but in your case you can try "if" and $arg_name (argument name in the request line):
location /videos {
if ($arg_c = "18") {
rewrite ^/videos(.*) http://$server_name/category/cars? permanent;
}
if ($arg_c = "19") {
rewrite ^/videos(.*) http://$server_name/category/bikes? permanent;
}
# and so on
}
I'm trying to set up a permanent redirect from
http://domain.com/member/blog_post_view.php?postId=1
to
http://blog.domain.com/friendly-url-here
The source URL contains both a ? and an = which I think might be the cause but am unsure.
I've tried all sorts of nginx suggestiosn including the one below but can't seem to get the redirection to work and hoped someone can point me in the right direction.
location /blog_post_view.php?postId=1 {
rewrite "/blog_post_view.php\?postId\=1" http://blog.domain.com/friendly-url-here permanent;
}
That part of request line starting from the question mark is called query string, while the location directive matches only path part of URI.
You should use $arg_* variable instead:
location =/blog_post_view.php {
if ($arg_postId = 1) {
return 301 http://blog.domain.com/friendly-url-here;
}
}
Reference:
http://nginx.org/r/location
http://nginx.org/r/if
Embedded Variables
I have a site with two RESTful URL schemes:
foo.com/model/id and
foo.com/model/id/action
The actual pages served by these URLs are in the form of
$model.php?id=$id and
$model_$action.php?id=$id respectively.
I have a single regular expression that will match both cases ^(\w+)s/([A-z0-9]+)(?:/(\w+))?/?$ and I'd like to use a single Nginx rule to rewrite for both types of URLs, but I'm not sure how to do this. In pseudocode I imagine the rule would look something like this
rewrite ^(\w+)s/([A-z0-9]+)(?:/(\w+))?/?$ /(($3) ? $1_$3.php?$id=$2 : $1.php?$id=2)
This isn't valid syntax (so far as I know), but can something like this be done in Nginx?
Rewrite the possible urls in turn starting with the longest to the shortest to that overlapping matching strings, "/model/id" in this case, would be matched in the longer url string first.
location / {
# For "/model/id/action" to "$model_$action.php?id=$id"
rewrite ^/(.+)/(.+)/(.+)(/?)$ $1_$3.php?id=$2 last;
# For "/model/id" to "$model.php?id=$id"
rewrite ^/(.+)/(.+)(/?)$ $1.php?id=$2 last;
}
location ~ .+\.php$ {
# Handle PHP
}
The "(/?)" is just in case the urls sometimes come with an ending slash. If they never do, it can be removed. In this case, it will probably be best to specifically always add a closing slash and have "(/?)" as "/".