Serving different content from root without changing url

Hi guys,

I have a small problem. I don’t know if the topic name reflects what I want to do, but this is what I understand.

Let’s say I have a very high resource intensive PHP application under site: mysite.com
But I have opportunity to generate cache (as static html/css/js files) for it.
This system has such cache indeed, it generates static files under mysite.com/cache/public.

These are normal static files, hence I may host them directly via caddy instead passing everything to php-fpm.

I wrote such rewrite rule:

rewrite / {
                to /cache/public/{host}{uri}/index.html {path} {path}/ /index.php?{query}
        }

It works fine, however, caddy returns HTTP 301 and thus browser automatically goes to mysite.com/cache/public/{host}{uri}/ instead of mysite.com/{host}{uri}/

And here’s my question: how I can get rid out of it - this /cache/public/ part of the address?

I wanted to have solution that caddy first checks if static files exist, if yes - serves them, if not - proceed further (and pass to php-fpm request). But that without changing adres in a user browser as it looks odd. I’ve tried proxy but with no luck (but maybe I’m weak at understanding this module)

Aby suggestions how I may solve this problem?

Thanks in advance!

Try to /cache/public/{host}{uri} (without the /index.html on the end).

When Caddy gets a request (or has a request rewritten) to an index file, it will issue a 301 redirect to the directory itself, i.e. /, which is the canonical way to request an index.

@Whitestrake: thank you very much, that was what I was looking for!

Highly appreaciate your help!

1 Like

Maybe I will add this question to this thread as it fits.

@Whitestrake: regarding this rewrite I have small problem (?)

My current rewrite is:

rewrite {
                to /cache/public/{host}{uri} {path} {path}/ /index.php?{query}
        }

Everything works, however, the application (from time to time) tends to do not generate index.html file (this is the app problem, not caddy related).

But, in such case rewrite rule lead to 404 error due to no index.html at /cache/public/{host}{uri}
I was trying to “fix” it in Caddyfile but no luck - even I tried root directive modification, I thought if caddy finds no index it chains the rule further till the final index.php?{query} path which should work always.

And here’s my question: how to force caddy to pass request to index.php (last step) if first dir does not contain index.html?

The rewrite directive always tries each target, in order, until it finds a real file - so it already has the behaviour you want.

If you get a 404 with that configuration, it’s because there’s no index.php file in the web root that Caddy can read.

Yes, this is behaviour which I see and I understand, no surprise here. :slight_smile:

But my question: Is any way to “overcome” this problem? I mean something like:

  • if there is no index.html then caddy “treats” this as non existent target to rewrite and tries next rule
  • if there is 404 (because of lack of index.html), then redirect/proxy request to particular place
  • something else which prevents error 404 if there is no index.html in such case

The final target of a rewrite’s to subdirective is the “fallback” target. When Caddy finds no real files or directories, the fallback target is always what Caddy proceeds with after the rewriting is complete.

If you want Caddy to proxy somewhere if no files are found, set a proxy or a fastcgi directive to operate on the path of the fallback target.

If you want to display some specific page instead of a 404, use a fallback target that contains an index or points directly to some file that you can ensure will always be present. Alternately, use the errors directive to specify a custom error page that will be sent with the 404 status.

If you want to send a specific Status code instead of 404, set a status directive to operate on the path of the fallback target.