.htaccess rules on Caddy

Well, what I’m trying to do is prevent users from accessing profile.php directly (or any files that way). For example, they can access domain.net/profile/1/edit but not domain.net/profile.php

Okay, then you’ll probably need to wrap the error and rewrite in a route to make sure they run in that order – by default, directives are sorted according to this directive order: Caddyfile Directives — Caddy Documentation

route {
	error /*.php 404

	@profile path_regexp profile ^/profile/([-\w]+)/([-\w]+)$
	rewrite @profile /profile.php?id={re.profile.1}&action={re.profile.2}
}

But honestly, the way you’re doing it is not great, all modern PHP frameworks use index.php as the entrypoint, and put the webroot one directory deeper to isolate it from the rest of the actual scripts for your app. Then you can use a PHP router (there’s plenty of implementations, take a look at FastRoute for example) which would parse the path and trigger the right handler.

This approach is a security best-practice, because it’s essentially “deny everything by default, but only allow the routes I define”, whereas the way you have it, it’s the other way around, everything is allowed except for the rewrites you wrote in Caddy. It’s risky and error-prone. Some crafty individuals are more likely find ways to get past the rules you write.

1 Like

That works perfectly, you my friend are a legend. Thanks so much.

I’ll take a look at FastRoute.

Just one more question, am I missing something to get the 404 to be a php file? Currently only 404.html works, not a 404.php

handle_errors {
        @404 {
            expression {http.error.status_code} == 404
        }
        rewrite @404 /404.php
        file_server
}
1 Like

Yeah, you’d need to use php_fastcgi again in the error handler.

Hmm, yeah I tried that but if I do that I just get a default 404 page and not the 404.php.

handle_errors {
    @404 {
        expression {http.error.status_code} == 404
    }
    rewrite @404 /404.php
    file_server
    php_fastcgi unix//run/php/php7.4-fpm.sock
}

Either way, you’re probably better off implementing a router in your PHP app, then your router can make the decision to output the 404 contents if none of the routes match.

I’ve implemented PHP Router and it works exactly how I need it to. Thanks for your suggestion. Can finally move all my code to Caddy servers :grinning:

2 Likes

One last thing, any change you know what the Caddyfile would be for this .htaccess:

RewriteEngine On

# Remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]

RewriteCond %{REQUEST_URI}  !(\.png|\.jpg|\.gif|\.jpeg|\.zip|\.css|\.svg|\.js)$
RewriteCond %{REQUEST_URI} !^/app/ajax/
RewriteRule (.*) app/routes.php [QSA,L]

Want to remove the trailing slash but most importantly, forward all traffic to use routes.php except the ajax folder and those file extensions.

@excludes {
    not path /app/ajax /assets/*
}

rewrite @excludes /app/routes.php

Tried this so far (not sure about trailing slash yet).

EDIT
Resolved by using

php_fastcgi unix//run/php/php7.4-fpm.sock {
    index /app/routes.php
}

Not sure how to remove the trailing slash though.

Trailing slashes are common enough that they’re in our docs:

1 Like

I’m trying to do this for all URLs, what am I doing wrong here?

redir {path}{uri}/ {path}{uri}
redir /{path}/ /{path}
redir /{URI}/ /{URI}

This topic was automatically closed after 30 days. New replies are no longer allowed.