# URI re-mapping using try\_files

**URL:** <https://www.ruby-forum.com/t/uri-re-mapping-using-try-files/223626>\
**Category:** NGINX\
**Created:** [October 11, 2012, 3:19pm UTC](https://www.ruby-forum.com/t/uri-re-mapping-using-try-files/223626 "2012-10-11T15:19:54Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![aris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/258eb7/32.png) [@aris](https://www.ruby-forum.com/u/aris)\
**Post date:** [October 11, 2012, 3:19pm UTC](https://www.ruby-forum.com/t/uri-re-mapping-using-try-files/223626/1 "2012-10-11T15:19:54Z")

</div>

Hello,

I am new to nginx, and am still learning my way.

I use nginx to serve static html pages to users, and in particular, I  
want  
users who visit ‘[www.example.com/public/doc/abc123?para=data](http://www.example.com/public/doc/abc123?para=data)’ to be  
served  
with the file ‘/home/www/example/public/doc/abc123/abc123.html’ on the  
server, but ‘[www.example.com/public/doc/abc123?para=data](http://www.example.com/public/doc/abc123?para=data)’ stays in the  
user’s browser address bar.

So there are two issues here: 1. map URI pattern ‘/public/doc/blah’ to  
file  
‘/home/www/example/public/doc/blah/blah.html’ on the server; 2. keep  
query  
string ‘?parap=data’ in the address bar.

I wonder if these can be solved by using `try_files` within a location  
block. For example, substring the $uri to take out ‘/blah’ part, and  
append  
it to the $uri followed by ‘.html’. And possibly append $args after  
‘.html’?  
How exactly do we do this in nginx? Thanks!

Posted at Nginx Forum:

> **[URI re-mapping using try\_files](https://forum.nginx.org/read.php?2,231672,231672#msg-231672)**
>
> Hello, I am new to nginx, and am still learning my way. I use nginx to serve static html pages to users, and in particular, I want users who visit 'www.example.com/public/doc/abc123?para=data' to be served with the file...

---

<div class="post-metadata">

**Author:** ![mrtn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/b4bc9f/32.png) [@mrtn](https://www.ruby-forum.com/u/mrtn)\
**Post date:** [October 11, 2012, 6:58pm UTC](https://www.ruby-forum.com/t/uri-re-mapping-using-try-files/223626/2 "2012-10-11T18:58:25Z")

</div>

On Thu, Oct 11, 2012 at 09:19:23AM -0400, mrtn wrote:

Hi there,

> I use nginx to serve static html pages to users, and in particular, I want  
> users who visit ‘[www.example.com/public/doc/abc123?para=data](http://www.example.com/public/doc/abc123?para=data)’ to be served  
> with the file ‘/home/www/example/public/doc/abc123/abc123.html’ on the  
> server, but ‘[www.example.com/public/doc/abc123?para=data](http://www.example.com/public/doc/abc123?para=data)’ stays in the  
> user’s browser address bar.

For this sort of thing, “rewrite” ([Module ngx\_http\_rewrite\_module](http://nginx.org/r/rewrite)) is  
probably  
the directive you want.

```
    rewrite (.*)/(.*) $1/$2/$2.html break;

```

can do what you want in this case.

What do you want to happen if the user asks for any of:

[http://www.example.com/public/doc/abc123](http://www.example.com/public/doc/abc123)  
[http://www.example.com/public/doc/abc123?para=nodata](http://www.example.com/public/doc/abc123?para=nodata)  
[http://www.example.com/public/doc/abc123/abc123.html](http://www.example.com/public/doc/abc123/abc123.html)  
[http://www.example.com/public/doc/one/two](http://www.example.com/public/doc/one/two)

The rewrite directive above may or may not do what you want for those.

> So there are two issues here: 1. map URI pattern ‘/public/doc/blah’ to file  
> ‘/home/www/example/public/doc/blah/blah.html’ on the server; 2. keep query  
> string ‘?parap=data’ in the address bar.

1. is in the rewrite (or any similar configuration which maps url to  
file)

2. is by virtue of not doing an external rewrite, which is a  
redirection.

## f

Francis D. removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![mrtn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/b4bc9f/32.png) [@mrtn](https://www.ruby-forum.com/u/mrtn)\
**Post date:** [October 11, 2012, 10:00pm UTC](https://www.ruby-forum.com/t/uri-re-mapping-using-try-files/223626/3 "2012-10-11T22:00:09Z")

</div>

Hi Francis,

Thanks for introducing me to rewrite directive. Just to confirm, this is  
how  
I should use your rewrite:

root /home/www/example;

location /public/doc/ {  
rewrite (._)/(._) $1/$2/$2.html break;  
}

Ideally, for the other cases you raised, I want the following to happen:

> [http://www.example.com/public/doc/abc123](http://www.example.com/public/doc/abc123)  
> [http://www.example.com/public/doc/abc123?para=nodata](http://www.example.com/public/doc/abc123?para=nodata)

when the query string (e.g. ?para=blah) part is missing or incomplete, I  
want to serve a generic error page (e.g. /error.html)

> [http://www.example.com/public/doc/abc123/abc123.html](http://www.example.com/public/doc/abc123/abc123.html)

when the user tries to access the actual html page directly, I want to  
block  
it by either returning a 404 or serving a generic error page as above

> [http://www.example.com/public/doc/one/two](http://www.example.com/public/doc/one/two)

when the user queries an URI that has no corresponding .html file on the  
server, I want to simply return a 404.

Can all these be implemented using rewrite only? Thanks.

Posted at Nginx Forum:

> **[Re: URI re-mapping using try\_files](https://forum.nginx.org/read.php?2,231672,231682#msg-231682)**
>
> Hello, I am new to nginx, and am still learning my way. I use nginx to serve static html pages to users, and in particular, I want users who visit 'www.example.com/public/doc/abc123?para=data' to be served with the file...

---

<div class="post-metadata">

**Author:** ![mrtn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/b4bc9f/32.png) [@mrtn](https://www.ruby-forum.com/u/mrtn)\
**Post date:** [October 11, 2012, 10:32pm UTC](https://www.ruby-forum.com/t/uri-re-mapping-using-try-files/223626/4 "2012-10-11T22:32:52Z")

</div>

On Thu, Oct 11, 2012 at 03:59:24PM -0400, mrtn wrote:

Hi there,

> Thanks for introducing me to rewrite directive. Just to confirm, this is how  
> I should use your rewrite:
> 
> root /home/www/example;
> 
> location /public/doc/ {  
> rewrite (._)/(._) $1/$2/$2.html break;  
> }

It can work outside of all locations, or else in the one location that  
handles this request.

So this config can work.

> Ideally, for the other cases you raised, I want the following to happen:
> 
> > [http://www.example.com/public/doc/abc123](http://www.example.com/public/doc/abc123)  
> > [http://www.example.com/public/doc/abc123?para=nodata](http://www.example.com/public/doc/abc123?para=nodata)
> 
> when the query string (e.g. ?para=blah) part is missing or incomplete, I  
> want to serve a generic error page (e.g. /error.html)

The above rewrite pays no attention to query strings.

So you’ll want to do something based on $arg\_para – maybe an “if”  
or something involving “map”.

I guess (without testing):

```
if ($arg_para != data) { return 404; }

```

inside that location{} would probably work.

> > [http://www.example.com/public/doc/abc123/abc123.html](http://www.example.com/public/doc/abc123/abc123.html)
> 
> when the user tries to access the actual html page directly, I want to block  
> it by either returning a 404 or serving a generic error page as above

The above rewrite does that (assuming that the “rewritten” file is  
absent).

> > [http://www.example.com/public/doc/one/two](http://www.example.com/public/doc/one/two)
> 
> when the user queries an URI that has no corresponding .html file on the  
> server, I want to simply return a 404.

The above rewrite does that; but which html file should it look for  
here?

/home/www/example/public/doc/one/two/two.html, or  
/home/www/example/public/doc/one/two/one/two.html?

(As in: do you repeat everything after /public/doc, or do you repeat  
just the final after-slash part?)

> Can all these be implemented using rewrite only? Thanks.

With the extra “if” above, I think so.

Your testing should be able to show any problems, or unexpected  
behaviour.

## f

Francis D. removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![mrtn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/b4bc9f/32.png) [@mrtn](https://www.ruby-forum.com/u/mrtn)\
**Post date:** [October 12, 2012, 12:13am UTC](https://www.ruby-forum.com/t/uri-re-mapping-using-try-files/223626/5 "2012-10-12T00:13:22Z")

</div>

On Thu, Oct 11, 2012 at 05:22:54PM -0400, mrtn wrote:

Hi there,

> > I guess (without testing):
> > 
> > if ($arg\_para != data) { return 404; }
> > 
> > inside that location{} would probably work
> 
> Hmm, I read on nginx website and elsewhere that if statement may not work  
> consistently within a location directive, and is generally discouraged.  
> Should I worry in this case?

What precisely did you read? And does it apply here?

(I think I know the answers to those; but there’s no reason for you to  
believe my words instead of words written elsewhere. If the words are  
all consistent, then you can choose to believe them all. If the words  
are  
contradictory, then you must choose which source to consider incorrect.)

> > (As in: do you repeat everything after /public/doc, or do you repeat  
> > just the final after-slash part?)
> 
> I only want to repeat the final after-slash part, so any  
> ‘/public/doc/blahA/blahB’ should only look for  
> ‘/public/doc/blahA/blahB/blahB.html’. Would that change anything in the  
> config proposed here?

What happened when you tried it?

mkdir -p /home/www/example/public/doc/blahA/blahB/blahA  
echo This is in blahB \>  
/home/www/example/public/doc/blahA/blahB/blahB.html  
echo This is in blahA \>  
/home/www/example/public/doc/blahA/blahB/blahA/blahB.html  
curl -i [http://www.example.com/public/doc/blahA/blahB](http://www.example.com/public/doc/blahA/blahB)

As it happens, the rewrite suggested should end up fetching the “in  
blahB”  
file, because it only repeats the part after the last slash.

When you understand _why_ it does that, you’ll have a better chance of  
writing your own regex-based rewrites.

Good luck with it!

## f

Francis D. removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![mrtn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/b4bc9f/32.png) [@mrtn](https://www.ruby-forum.com/u/mrtn)\
**Post date:** [October 11, 2012, 11:23pm UTC](https://www.ruby-forum.com/t/uri-re-mapping-using-try-files/223626/6 "2012-10-11T23:23:07Z")

</div>

Hi Francis,

> I guess (without testing):
> 
> if ($arg\_para != data) { return 404; }
> 
> inside that location{} would probably work

Hmm, I read on nginx website and elsewhere that if statement may not  
work  
consistently within a location directive, and is generally discouraged.  
Should I worry in this case?

> The above rewrite does that; but which html file should it look for here?
> 
> /home/www/example/public/doc/one/two/two.html, or  
> /home/www/example/public/doc/one/two/one/two.html?
> 
> (As in: do you repeat everything after /public/doc, or do you repeat  
> just the final after-slash part?)

I only want to repeat the final after-slash part, so any  
‘/public/doc/blahA/blahB’ should only look for  
‘/public/doc/blahA/blahB/blahB.html’. Would that change anything in the  
config proposed here?

Thanks again!

Mrtn

Posted at Nginx Forum:

> **[Re: URI re-mapping using try\_files](https://forum.nginx.org/read.php?2,231672,231685#msg-231685)**
>
> Hello, I am new to nginx, and am still learning my way. I use nginx to serve static html pages to users, and in particular, I want users who visit 'www.example.com/public/doc/abc123?para=data' to be served with the file...
