Rewrite nginx "rewrite block" to caddy

if (!-e $request_filename) {
    rewrite ^/(.*)$ /index.php?q=$1 last;
}

That’s it, how to write it for caddyfile?
For apache it looks like that:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

Hi @Andrey_Izotov,

While the config you gave (including the regex) could be translated literally to a Caddyfile, regex checking is completely unnecessary for something this simple - so this would be the best way to do it:

rewrite {
  to {path} /index.php?q={path}
}

https://caddyserver.com/docs/rewrite

Your example doesn’t work. :frowning:

This works:

rewrite {
        regexp ^/(.*)$
        to /index.php?q={1}
 }

The regex is unnecessary. Your working example is functionally identical to the following:

rewrite {
  to /index.php?q={uri}
}

Your working example, however, doesn’t approximate if (!-e $request_filename). To achieve that in Caddy, we add the files on disk as paths to check first: {path} {path}/ index.php?q={uri}.

Your both examples don’t work, i don’t know why as well
This works:

rewrite {
        regexp ^/(.*)$
        to {path} {path} /index.php?q={1}
    }

This also works:

rewrite {
        to {path} {path} /index.php?q={file}
    }

I’m not sure what your PHP application expects to receive from your query; it might be sensitive to the leading slash?

{uri} resolves to the entire resource, including anchors and queries, e.g. /path/to/file.jpg#anchor?query=value.

{path} is just the first part, e.g. /path/to/file.jpg.

{file} is just the filename, e.g. file.jpg.

Check out the placeholder docs for the full list; you can frequently retrieve the information you want without resorting to regex at all, which is a win for performance.

https://caddyserver.com/docs/placeholders

I figured out that there {query} should be used, but i can’t make {path} {path}/ work correctly, it’s not serving static files on my website, like /assets/theme/main/js/bootstrap.js

The rewrite will combine the web root (set by the root directive) with the requested path into an absolute filepath and then test that location on disk.

For example, for a given root /var/www/html, and a given request /assets/theme/main/js/bootstrap.js, a rewrite to {path} will check for the existence of /var/www/html/assets/theme/main/js/bootstrap.js on the host disk, and serve that if it exists.

Can “-” or “.” in root path be an issue?

Unlikely - Caddy will allow you to start with a nonexistent or inaccessible web root, but it will print a warning to the process logs.

You could set root to an absolute path to test it out anyway, just in case.

Is there any way to debug how it rewrites?

There are a few rewrite-specific placeholders that get changed when a rewrite occurs, see https://caddyserver.com/docs/placeholders.

You can use log to append them to requests logs, for example: log /path/to/caddy.log "{combined} /// {rewrite_uri}" - and look for the results.

1 Like

I just can’t get it work, i don’t know how to make it right.
Here are some examples:
Lighttpd Lighttpd Guide - Using Friendly URLs | MODX Documentation
NGINX:

if (!-e $request_filename) {
    rewrite ^/(.*)$ /index.php?q=$1 last;
}

Apache:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

How to write it on caddy? i’m ready to test on my side

Hi @Andrey_Izotov,

I’ve merged your latest post into this thread to keep the conversation on this topic in one place.

As noted above, the literal translation of your Apache example to a Caddyfile is as follows:

rewrite {
  regexp ^/(.*)$
  to {path} {path}/ /index.php?q={1}
}

If it’s not working as expected, you should look into logging to determine what’s going wrong. Your full Caddyfile and a file tree of your web root might also be helpful to troubleshoot.

I am using Ubuntu 17.10

This is my Caddyfile located in /var/www/

(friendlyurls) {
    rewrite {
        regexp ^/(.*)$
        to {path} {path} /index.php?q={1}
    }
}

(php-host) {
    fastcgi / /run/php/php7.2-fpm.sock php
    gzip
    cache
}

(http2https) {
    redir 301 {
        if {>X-Forwarded-Proto} is http
        /  https://{host}{uri}
    }
}

my-host.com {
    root /var/www/html/my-host.com
    #tls /etc/letsencrypt/live/my-host.com/fullchain.pem /etc/letsencrypt/live/my-host.com/privkey.pem
    import friendlyurls
    #import http2https
    import php-host
    tls off
    #log ./log/my-host.log "{combined} /// {rewrite_uri} // {rewrite_query}"
    log / stdout "{combined} /// URI:{rewrite_uri} // PATH:{path} // QUERY:{query} // FILE:{file}"
    #errors ./log/my-host.error
}

With your last config when i run my-host.com:2015/dynamic-css.css (dynamically generated file) it works, but when i am trying to serve static asset http://my-host.com:2015/assets/theme/main/js/bootstrap-switch.js
It returns 404 page.

Does the bootstrap-switch.js file exist and have the correct file permissions on the host’s file system?

What’s the output of ls -l /var/www/html/my-host.com/assets/theme/main/js/bootstrap-switch.js ?

-rwxrwxrwx 1 www-data www-data 14919 Mar 8 16:49

Just to confirm - if you comment out import friendlyurls, reload Caddy, and run curl -I http://my-host.com:2015/assets/theme/main/js/bootstrap-switch.js, does it work again?

Yes it does

That seems like unintended behaviour.

Could you please try:

  1. Rename your existing Caddyfile to Caddyfile.bak
  2. Create a new Caddyfile with the following content:
:2015 {
  root /var/www/html/my-host.com
  log / stdout "{combined} /// {rewrite_uri}"
  errors stdout
  rewrite {
    to {path} {path}/ /index.php?q={uri}
  }
}
  1. Post your caddy -version
  2. Run caddy -log stdout in the same directory as your new Caddyfile
  3. From another terminal, run curl -I http://localhost:2015/assets/theme/main/js/bootstrap-switch.js
  4. Post the output of both terminals (the curl command and the caddy output)