On 23/01/25 11:20, Lévai, Dániel wrote:
> Hi all,
> 
> I was trying to do a basic path rewrite in httpd(8) on 7.2-stable, and I just 
> can't see what I'm missing:
> 
> httpd.conf:
> server "host" {
>         listen on egress port 12345
> 
>         root "/htdocs"
> 
>         location "/" {
>                 request rewrite "/to/"
>         }
>         location "/*" {
>                 directory auto index
>         }
> }
> 
> 
> Using http://host:12345/ slaps me with 500:
> 
> server_response: rewrote /? -> /to/?
> "GET / HTTP/1.1" 500 0
> , /to/ (500 Internal Server Error)
> 
> 
> Accessing http://host:12345/to/ directly works, however:
> 
> "GET /to/ HTTP/1.1" 200 538
> "GET /favicon.ico HTTP/1.1" 404 0
> , /favicon.ico (404 Not Found)
> 
> 
> I though maybe it was iffy because of the location containing only a slash 
> (/), but using anything else like...:
>         location "/from/" {
>                 request rewrite "/to/"
>         }
> 
> ... gives 500 too when accessing http://host:12345/from/
> Tried playing around with (adding/removing) the trailing '/' from the paths, 
> but still no luck. I even tried the example at the end of httpd.conf(5) with 
> "location match" and pattern/captures, but still the same.
> 
> But "request rewrite" must be clearly working somehow, I just can't see 
> what's missing.
> 
> Any tips would be greatly appreciated!
> 
> 
> Daniel
> 

If you're curious about the lower level details behind my explanation,
/usr/src/usr.sbin/httpd/server_file.c and /usr/src/usr.sbin/httpd/server_http.c
are enlightening here (though I might add that I don't actually know C; I pieced
this together by reading httpd(8) and httpd.conf(5), and using my more general
programming knowledge to infer some things).

The first thing I have to say is this: what reason is there for using "request
rewrite" over "block return"? httpd has distinct behavior for both, and that
means certain things may work differently from how you expect them to.

When using "request rewrite", that path is exact, and a final authority in a
sense. httpd is trusting that you know precisely where you're sending the
client. That means it's going to interpret what you tell it very literally,
since modifying a rewritten request carries more risk, and perform a file access
test. If httpd doesn't like the results of that test because the place you
pointed it to is actually a directory, it'll throw a 500 Internal Server Error.
This is one rewritten request, followed by one response.

When using "block return" with a destination URI, httpd does more than this. It
will immediately close the connection and send an error page along with an HTTP
Location header. This is the first request, followed by the first response. Then
the client may honor the Location header in the response and follow the
redirection. This is the second request, soon followed by a second response. 

Due to differences in the way that "block return" operates, one thing httpd can
do is append the "directory index file" to the location or path if there's a
trailing slash ("index.html" is the default, so "/to/" would result in
"/to/index.html" for instance). It can also do directory auto indexing.

All of this is to say that if you don't have a specific reason to use "request
rewrite" instead of "block return", let a redirection handle it by using "block
return" with either a 301 Moved Permanently or a 302 Found. If you don't know
the difference, use a 302 Found for now.

Something like this could work depending on what you want to do (change the
server and listen statements to reflect your setup. If you need auto-indexing,
add it back in).

server "localhost" {
        listen on 127.0.0.1 port 80
        location match "/from/(.*)" {
                block return 302 "$REQUEST_SCHEME://$HTTP_HOST/to/%1"
        }
}

Note that the default root is "/htdocs", so if that's where you want your stuff
to be, you can leave that out. I prefer to create a separate directory since
/var/www/htdocs/bgplg exists by default, but that's just me.

-- 
https://www.anthes.is/

Reply via email to