More htaccess / rewrite woes

Trying to get Statamic to run in Caddy and am tripping up on converting the rewrite rules. Laravel Valet is able to run Statamic (with Caddy on the backend) through its “drivers” but I’m beaten.

Statamic htaccess file

`# Turn on the Rewrite Engine`
`RewriteEngine On`
`# ------------------------------------------------------------------------------`
`# Dynamic RewriteBase`
`# ------------------------------------------------------------------------------`
`# For most servers, this will be able to dynamically find your site's root,`
`# but if it doesn't for you, comment out these next two lines...`
`RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$`
`RewriteRule ^(.*)$ - [E=BASE:%1]`
``
`# ...and uncomment out the following line, then set as you need to`
`#RewriteBase /`
``
`# ------------------------------------------------------------------------------`
`# Protect System Files`
`# ------------------------------------------------------------------------------`
`RewriteRule ^_app - [F,L]`
`RewriteRule ^_config - [F,L]`
`RewriteRule ^_cache - [F,L]`
`RewriteRule ^_content - [F,L]`
`RewriteRule ^_logs - [F,L]`
`RewriteRule ^_storage - [F,L]`
`RewriteRule ^admin/themes/[^/]*/(?:layouts|templates) - [F,L]`
`RewriteRule ^.*?\.yml$ - [F,L]`
`RewriteRule ^.*?\.yaml$ - [F,L]`
`RewriteRule ^.*/?\.git+ - [F,L]`
``
`# This will prevent all .html files from being accessed.`
`# You may want to remove this line if you want to serve`
`# static files outside of Statamic`
`# RewriteRule ^(.*)?\.html$ - [F,L]`
``
``
`# ------------------------------------------------------------------------------`
`# Remove Trailing Slashes from URL`
`# ------------------------------------------------------------------------------`
`RewriteCond %{REQUEST_FILENAME} !-d`
`RewriteRule ^(.*)\/(\?.*)?$ $1$2 [R=301,L]`
``
``
`# ------------------------------------------------------------------------------`
`# Remove the Index File`
`# ------------------------------------------------------------------------------`
`RewriteCond %{REQUEST_FILENAME} !-f`
`RewriteCond %{REQUEST_FILENAME} !-d`
`RewriteRule ^(.*)$ index.php [QSA,L]`

I think I have the protected system files figured out - pretty simple, especially since there is an example.

RewriteRule ^_app - [F,L]

becomes

`rewrite {`
`    regexp ^/_app`
`    status 403`
`}`

Its the last ones holding me up - removing trailing slash and the index.php. I’ve scoured the forums and google and attempted to use the wordpress and other examples I’ve found as a base but just not getting there.

I don’t think it’s currently possible to use redir to remove trailing slashes right now. Only way I know to do that is to structure a site like this: /some-post.html
and put ext .html in the Caddyfile.

I’m assuming the app you’re using does it like this instead: /some-post/index.html which works but you get the trailing slashes. :confused:


For index.php: looks like you want to rewrite to index.php if no file/directory exists at that path.

rewrite {
    r (.*)
    to {path} {path}/ index.php?{uri}
}

Hi Jacob,

Statamic (and EE, and others) uses index.php as a controller/router and the URL rewrites strip index.php from the URLs.

rewrite { r (.*) {path} {path}/ index.php?{uri} }

This gives me a parse error – wrong argument count or unexpected line ending after ‘{path}’.

Thinking through this and digging some more, I’m wondering if this is more than a rewrite issue and leads towards a fastcgi configuration issue, or need of a plugin?

I did stumble across a NGINX config file for Statamic.

server { set $domain 'yourdomain.com'; server_name $domain; root /home/$domain/public; access_log /home/$domain/logs/access.log; error_log /home/$domain/logs/error.log;

    # Cache static files for as long as possible
    location ~* \.(?:xml|ogg|mp3|mp4|ogv|svg|svgz|eot|otf|woff|ttf|css|js|jpg|jpeg|gif|png|ico)$ {
            try_files $uri =404;
            expires max;
            access_log off;
            add_header Pragma public;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    }

    # Deny access to configuration files
    location ~* ^/_config {
            deny all;
            return 404;
    }

    location ~ (\.yaml) {
            return 404;
    }

    # Return a static file, if it exists, or pass to front controller
    location / {
            rewrite ^/admin.php.*$ /admin.php;
            try_files $uri $uri/ /index.php;
    }

    # Pass PHP requests on to PHP-FPM
    location ~* \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            include        fastcgi_params;
    }

}`

And in doing more digging, it appears Caddy is the web server behind [Laravel Valet] (Laravel Valet - Laravel - The PHP Framework For Web Artisans) - which has support for Statamic OOTB (so to speak) using a “driver”. While Valet looks to be “easy” for development, it is Mac only, for development only and doesn’t fit with the rest of the goals of Caddy.

So … here is the driver file for Statamic from the [Github repo] (valet/StatamicValetDriver.php at master · laravel/valet · GitHub) - if it helps anyone see where the issue might lie. (Its a bit over my head).

<?php class StatamicValetDriver extends ValetDriver { /** * Determine if the driver serves the request. * * @param string $sitePath * @param string $siteName * @param string $uri * @return bool */ public function serves($sitePath, $siteName, $uri) { return is_dir($sitePath.'/statamic'); } /** * Determine if the incoming request is for a static file. * * @param string $sitePath * @param string $siteName * @param string $uri * @return string|false */ public function isStaticFile($sitePath, $siteName, $uri) { if (strpos($uri, '/site') === 0 && strpos($uri, '/site/themes') !== 0) { return false; } elseif (strpos($uri, '/local') === 0 || strpos($uri, '/statamic') === 0) { return false; } elseif ($this->isActualFile($staticFilePath = $sitePath.$uri)) { return $staticFilePath; } elseif ($this->isActualFile($staticFilePath = $sitePath.'/public'.$uri)) { return $staticFilePath; } return false; } /** * Get the fully resolved path to the application's front controller. * * @param string $sitePath * @param string $siteName * @param string $uri * @return string */ public function frontControllerPath($sitePath, $siteName, $uri) { if (file_exists($staticPath = $sitePath.'/static'.$uri.'/index.html')) { return $staticPath; } $_SERVER['SCRIPT_NAME'] = '/index.php'; if (strpos($_SERVER['REQUEST_URI'], '/index.php') === 0) { $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], 10); } if ($uri === '') { $uri = '/'; } if ($uri === '/installer.php') { return $sitePath.'/installer.php'; } if (file_exists($indexPath = $sitePath.'/index.php')) { return $indexPath; } if (file_exists($indexPath = $sitePath.'/public/index.php')) { return $indexPath; } } }

Oops, I fixed it! Forgot to include “to” :confused:

rewrite {
    r (.*)
    to {path} {path}/ index.php?{uri}
}

Prop-tip: You can make a multi-line code block by putting 3 backticks above and below like this:

``` ```
1 Like

Hi Jacob,

Thanks. Tried that - with the to - and still no luck. Should have added that to the post.

And will remember the 3 backticks for future code postings. Don’t use markdown as often as I would like to remember.

Can you post the entire Caddyfile you’re trying to use?

Nothing too complicated.

http://site.com {
	root /Users/charles/Sites/site
	fastcgi /index.php 127.0.0.1:9000 {
		ext .php .html
	}
	gzip
	log /Users/charles/Sites/site/access.log
	errors /Users/charles/Sites/site/errors.log
}

And changing it to this gives you errors?

http://site.com {
    root /Users/charles/Sites/site
    rewrite {
        r (.*)
        to {path} {path}/ index.php?{uri}
    }
    fastcgi /index.php 127.0.0.1:9000 {
        ext .php .html
    }
    gzip
    log /Users/charles/Sites/site/access.log
    errors /Users/charles/Sites/site/errors.log
}

Without any rewrite rules added, I get a 404 Not Found.

Adding the rewrite rules to the caddy file as above, I get the same - 404 Not Found.

Oh okay. Just making sure you weren’t getting a parsing error still.

This is probably the issue. I’m not sure what format index.php wants requests to look like.
For example WordPress queries look like this: /index.php?_url={uri}
If you can find out what the raw query to index.php needs to look like we should be able to fix the issue.
Right now a raw query just looks like /index.php?/whatever/was/requested which is likely wrong.

If I disable htaccess running under Apache, the URLs look like

site.com/index.php/page

Did some further digging - knowing Statamic v1 is built on the Slim framework. Originally ran into the Slim docs which didn’t tell me much.
http://docs.slimframework.com/routing/rewrite/

But then I stumbled across this github page regarding PHP-FPM and Caddy issues.
https://github.com/mholt/caddy/issues/611

In the referenced caddy file were rewrite rules referring to Slim.

# Rewrite rules to work with slim framework and alike
rewrite {
    r .*
    ext /
    to /index.php?{query}
}

Looks like progress. I am getting pages to load but now seeing errors with sessions,which means I’ve got something off with PHP-FPM - probably permissions on the sessions directory, and something else about strpos empty needle - a Slim framework thing, I guess. Off to troubleshoot that.

1 Like

Good luck! Let us know when you figure it out. I’m curious what the solution is. :slight_smile:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.