httpd icon indicating copy to clipboard operation
httpd copied to clipboard

Rewrite to fastcgi

Open tvlooy opened this issue 9 years ago • 6 comments

I want httpd to work like this:

  • Visit http://example.com/ => use /index.php
  • Visit http://example.com/foo => foo is not a file or directory => use /index.php
  • Visit http://example.com/bar => bar is a file => use /bar
  • Visit http://example.com/bar/baz => baz is not a file or directory => use /index.php
  • Visit http://example.com/quux1 => quux1 is a directory but listings are not allowed => 403 forbidden
  • Visit http://example.com/quux2 => quux2 is a directory and listings are allowed => 200 with listing

In Nginx you do that with a :

    location / {
        try_files $uri /index.php$is_args$args;
    }

In Apache you would do that with a:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]

I think this is not possible with httpd right now and I am trying to make a patch to support this. This would make a lot of PHP CMS'es, frameworks, ... work

tvlooy avatar Nov 16 '16 21:11 tvlooy

there is diff to achieve that.
https://marc.info/?l=openbsd-tech&m=148094767011911&w=2

i never tested it.

miraculli avatar Dec 29 '16 09:12 miraculli

Can't this be done now with rewrite?

marianielias avatar Jul 16 '18 20:07 marianielias

hello, apologies for the necro. is this patch still the way to do this, or is it possible with the current rewrite?

hexadecatrienoic avatar Apr 26 '20 02:04 hexadecatrienoic

hello, apologies for the necro. is this patch still the way to do this, or is it possible with the current rewrite?

I'm not sure, check it out, the documentation in OpenBSD is really complete: https://man.openbsd.org/httpd.conf#request https://man.openbsd.org/httpd.conf#EXAMPLES

marianielias avatar Apr 26 '20 02:04 marianielias

Using the Symfony 5 documentation as a reference, I've come up with this:

server "example.org" {
        listen on * port 80
        alias www.example.org
        root "/htdocs/example/public/"
        directory index index.php

        location found "/index.php" {
                fastcgi socket "/run/php-fpm.sock"
        }

        location found "*.php" {
                block return 403
        }

        location not found "*" {
                request rewrite "/index.php"
        }
}

I've tested it thoroughly to catch any edge cases, and it seems pretty solid.

Explanation for the location blocks:

  1. Only index.php (the front controller) goes to fastcgi.
  2. Any other PHP file is blocked
  3. Anything else not found, redirect to index.php.

UPDATE: it's missing one thing:

After you deploy to production, make sure that you cannot access the index.php script (i.e. http://example.com/index.php).

That is recommended to conceal that you're running PHP.

o-alquimista avatar Aug 02 '21 15:08 o-alquimista

New and improved :)

# application front controller
location found "/index.php" {
  fastcgi socket "/run/php-fpm.sock"
}

# fallback to front controller if the location doesn't exist
location not found "*" {
  request rewrite "/index.php"
}

# fallback to front controller if the location is an existing directory
location found "**/" {
  request rewrite "/index.php"
}

# if the requested path doesn't match any of the locations above,
# httpd will just serve the resource (e.g. images, css, js, etc.)

This handles some edge cases the older one didn't, like when you try to access an existing directory (e.g. /css/) and httpd spits out an ugly 404 response page.

I just haven't yet tested it with directory auto index enabled. I'm not sure if it's possible for us to handle this nicely. A feature request for httpd to do this for us would be nice.

o-alquimista avatar Mar 12 '22 03:03 o-alquimista