Closed SteffenDE closed 3 years ago
Hmm, it's funky that they use PHP to serve JS, but okay :stuck_out_tongue:
I'll need to take a closer look at all this, I'll come back to this one this weekend. Thanks for the report!
Okay, I see what's going on. This is pretty tricky.
So, I'm comparing with the code from Caddy v1 which apparently did work correctly: https://github.com/caddyserver/caddy/blob/v1/caddyhttp/fastcgi/fastcgi.go
The actual fastcgi code is pretty much the same in v2, but the difference comes in how the request prep happens in v2 compared to v1.
In v1, this wasn't a problem because the index.php
fallback wasn't handled via a rewrite internally beforehand, it was just directly handled in ServeHTTP
without updating the requested path.
In v2, instead it works by delegating the decision for index.php
to the built-in try_files
behaviour of the php_fastcgi
directive. See the expanded form to see the stuff it's doing: https://caddyserver.com/docs/caddyfile/directives/php_fastcgi#expanded-form
As you said, we could use the original URL to solve this case with .php
being found in the URL, and this does work (tried moving the origReq
block of code up and using that instead of fpath
when splitting), but I'm pretty worried about edgecases.
I tried doing some research for documentation to figure out how PATH_INFO
is meant to be handled depending on the original URL from the browser. E.g. we know that /index.php/foo
should have PATH_INFO
set to /foo
, but should the request to /foo
also have PATH_INFO
set to /foo
, since the server rewrites it to be handled by index.php
? I'm leaning towards no, but it's unclear, and the RFC https://tools.ietf.org/html/rfc3875#section-4.1.5 is not specific about that.
Also, with that change, it would also make requests like /foo.php/foo
that get rewritten to index.php
also have /foo
in PATH_INFO
even though /index.php
is what actually gets run, not /foo.php
. I think we might need some extra logic to only split if the index file is found in the original path? ๐ค
I would have to spin up an environment with nginx and/or apache with mod_cgi to verify how they behave. My env is kinda in a state that would make that tricky right now though, so I haven't done that yet. I wouldn't mind help there if you're capable of testing that our quickly.
There's also security implications with any change we make here, so I'm extra nervous about it.
Hi @francislavoie,
Hmm, it's funky that they use PHP to serve JS, but okay
Yes, but that is a requirement due to the way Moodle (2.x+) manages (via URL routing) its own File Storage - content-driven, via hashing - and generally the "version" (i.e revision) of the files to be served, to force an "aggressive" HTTP caching on the assets but when updating Moodle to the next version, which requires the revision to be bumped i.e. any file coming from theming and front-end logic, including JS, is served in that way.
Being Moodle a PHP-only (complex) web app, file handling is just done via PHP - strictly the initial routing since when X-Sendfile
support is available, the web server could jump into serving the right "file version".
That's why PATH_INFO
is relevant in Moodle: someone uses rewriting on their (old ) setup since Moodle could provide the same "path info" data via Query Param ?file=
but it breaks some content - the HTML-based since its assets are related to the path of the HTML file.
That being said, I'll give a try on Caddy 2 and PHP-FPM, without Moodle to see how PATH_INFO
actually works there i.e. outside any web application but using a plain <?php phpinfo();
: indeed the OP is faking the "server software" using Apache - Moodle check the web server vendor and blocks those unsupported - and maybe Moodle is using some tricks valid w/ Apache but not w/ Caddy.
Refs:
HTH, Matteo
To be clear, I understand why they do it that way, I think I just find it strange that they use a separate PHP entrypoint for serving JS rather than just using index.php
for everything, as most modern PHP frameworks do these days.
At my dayjob (I'm primarily a PHP dev), we have a very similar static asset management system, but we don't serve the files the same way. We instead use manifests that point to files, plus the file checksums as query params for cache busting and such.
Most PHP frameworks I'm aware of use REQUEST_URI
which has full information instead of PATH_INFO
, and just remove the script from the URI themselves, since SCRIPT_NAME
is also passed.
We should still fix PATH_INFO
though, obviously. Best to align behaviour with that of other webservers in this area, to avoid surprises for users. As I wrote, it's just unclear how the edgecases of PATH_INFO
are meant to behave because the RFC is not specific about that, and a few hours of googling and reading nginx/apache docs didn't get me much further either.
I appreciate the help ๐ let me know what you find out!
as most modern PHP frameworks do these days.
Eh eh... Moodle is there since 18yrs and has its own (opinionated) framework since then1 , which is IMHO nice here since we've found a potential issue in considering index.php
the preferred way to manage routing.
BTW adding Caddy support in Moodle could be also a matter to code there what you quickly described, to "fix" PATH _INFO
at runtime - see here what done in the years to support those listed web servers.
let me know what you find out!
I'll do some tests in my spare time, slowly but will do ๐.
HTH, Matteo
1 There is a long and open discussion about using an "industry" one vs the current one, which is constantly, and IMHO effectively, evolving to keep up with the times.
I greatly appreciate that someone is looking into this, as I sadly don't have the time to investigate this myself. For the meantime, I'm running Caddy v1 and proxy the Moodle requests from Caddy 2 to the old Caddy instance ๐
In the past, I've been running an extra Apache just for Moodle, but after discovering that setting the environment variable to Apache saves me from doing this, Moodle was running perfectly for the last two (or so) years on Caddy. Great work and a huge thank you to both the Moodle and Caddy team!
HI @francislavoie,
looking at the debug log to get a rough idea of what could be done on the Moodle side - though I'm pretty sure we should fix it at caddy side - I see what you're saying (REQUEST_URI
- SCRIPT_NAME
):
{
"level":"debug",
// cut
},
"dial":"127.0.0.1:9000",
"env":{
// cut
"DOCUMENT_ROOT":"/datapool/www/moodle_base/moodle",
"DOCUMENT_URI":"/lib/javascript.php",
"GATEWAY_INTERFACE":"CGI/1.1",
"HTTPS":"on",
// cut
"PATH_INFO":"",
"QUERY_STRING":"",
"REQUEST_SCHEME":"https",
"REQUEST_URI":"/lib/javascript.php/1599824490/lib/requirejs/require.min.js",
"SCRIPT_FILENAME":"/datapool/www/moodle_base/moodle/lib/javascript.php",
"SCRIPT_NAME":"/lib/javascript.php",
"SERVER_NAME":"moodle.domain",
"SERVER_PROTOCOL":"HTTP/2.0",
"SERVER_SOFTWARE":"Apache",
// cut
}
}
but playing a bit - I'm completely a newbie here w/ caddy
so just trying via Caddyfile
for my very first time - using a docker compose and pointing to a <?php phpinfo(INFO_VARIABLES);
it looks like to work if I use a bit of the expanded form, with a path_regexp
instead of path
:
:80
# Set this path to your site's directory.
root * /usr/share/caddy
# https://caddyserver.com/docs/caddyfile/directives/php_fastcgi#expanded-form
# Proxy PHP files to the FastCGI responder
@phpFiles {
#path *.php
# Match what would be a PHP resource file eventually with 'PATH_INFO',
# which follows "the part that identifies the script itself" (RFC 3875 ยง4.1.5):
# PATH_INFO = "" | ( "/" path )
# path = lsegment *( "/" lsegment )
# lsegment = *lchar
# lchar = <any TEXT or CTL except "/">
path_regexp php_fastcgi ^(.+\.php)(.*)$
}
reverse_proxy @phpFiles php-fpm:9000 {
transport fastcgi {
split .php
env SERVER_SOFTWARE Apache
}
}
i.e. something like what required to setup PHP on nginx, which IMHO looks like plain and safe. Next step, I'll get a bit deeper into the expanded form before looking at the source code.
@SteffenDE would you like to give it a try just for fun?
HTH, Matteo
Yeah that's essentially as expected.
The issue really is that the file
matcher (with split_path
) -> rewrite
(the second block in the expanded form) is turning the path into /lib/javascript.php
(stripping off the rest), which the fastcgi
transport then deals with.
In Caddy v1, the "rewrite" part was essentially internal to the fastcgi
directive, but in v2, we have the file
matcher and rewrite
handler as pieces that are separate (much more modular that way, less assumptions in individual handlers) but that "hides" the real path from the fastcgi
handler (it can still be grabbed by looking at the origReq
though, which is right).
The open question is how exactly does PATH_INFO
need to behave in the various edgecases.
Oh actually I just though of an idea... since the split_path
part of the file
matcher is aware of both halves of the path, I think we can safely store the second half in a placeholder which the fastcgi
transport can later read, if available. That might do the trick...
I'll try out an implementation later this evening or tomorrow. Still would love the help confirming that it behaves the same as apache and/or nginx.
@scara your code seems to work except of course that / is not rewritten to index.php and therefore pages not ending in filename.php are broken. /lib/javascript.php/1599824490/lib/requirejs/require.min.js
returns the correct file ๐
Hi @SteffenDE; thanks for your quick try&reply: that was expected, just a small step ahead.
Next step: create a docker compose with caddy, apache and nginx serving the same sample, info.php
and index.php
(<?php phpinfo(INFO_VARIABLES);
), via the same PHP-FPM engine instance, to look for any difference among the different vendors to help @francislavoie (and @mholt).
HTH, Matteo
Hi @francislavoie,
Oh actually I just though of an idea... since the
split_path
part of thefile
matcher is aware of both halves of the path, I think we can safely store the second half in a placeholder which the fastcgi transport can later read, if available. That might do the trick...
Sounds promising... just keep an eye to query params too just in case /usr/share/caddy/somefile.php
should be the target of the relative HTTP path /web-server/vendors/caddy?p=2&no=10#top
being somefile.php
defined as the index file i.e. fully equivalent w/ calling /somefile.php/web-server/vendors/caddy?p=2&no=10#top
.
Side note: https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/#connecting-nginx-to-php-fpm give you an example of how nginx, functionally speaking, works:
PATH_INFO
data which is maybe too much instead of your split
Wondering if adding index
to the fastcgi
transport would be a better option even if it looks like both transport and file handling should be single responsibility items.
Still slowly studying what is pretty "new to my eyes" - kudos to caddy docs ๐ .
HTH, Matteo
Sounds promising... just keep an eye to query params too just in case
The file
matcher is passed {path}
, i.e. not the full URI, just the path part. {uri}
could be used instead if that was desired (but it's not, in this case).
define how to extract PATH_INFO data which is maybe too much instead of your split
Yeah, we use split_path
as a fast substring split, it should be faster than regexp, and generally should be good enough.
avoid serving everything but existing files
Here, we just fallback to index.php
if one exists, instead of returning a 404. If there's no index.php
, then the file_server
directive will return a 404 in turn.
keep knowledge of what is the index file
The file matcher handles this, and it's configurable in the php_fastcgi
directive if necessary (rarely is). I don't think fastcgi
needs to care after that point. It just needs to know the "rest of the URL" after the rewrite happens, I think. That's the only piece missing.
Alright, did a quick implementation in https://github.com/caddyserver/caddy/pull/3739 and it seems to work as expected. Basically, the file
matcher will set a placeholder if a SplitPath
happened, and the fastcgi
transport will pull from that placeholder if it didn't perform a split itself.
Here's some path -> path_info
pairs with this change (where index.php
and lib/javascript.php
are files that exist)
"/lib/javascript.php/1599824490/lib/requirejs/require.min.js" -> "/1599824490/lib/requirejs/require.min.js"
"/index.php/foo" -> "/foo"
"/foo" -> ""
"/foo.php/foo" -> ""
I think this is probably the behaviour we're expecting. I'd love if you can confirm this is how it works in nginx and/or apache @scara
Hi @francislavoie, great news!
I did some tests and I can confirm it: I'm preparing a rough test suite and will share via my GH account.
HTH, Matteo
FYI: https://github.com/scara/caddy-pathinfo-tests
HTH, Matteo
Sweet!
Do you mind posting the test results?
Edit: Ah nevermind, I see that the results are listed as fixtured in here: https://github.com/scara/caddy-pathinfo-tests/blob/master/www/tests/testsuite.php
Nice!
Hi @francislavoie,
here is the run output using the current 2.1.1 using just a bit of expanded form i.e. no php_fastcgi
directive as-is:
Testing 'http://caddy'...
=> Contacting URL: 'http://caddy/lib/javascript.php/1599824490/lib/requirejs/require.min.js'...
Done.
=> Contacting URL: 'http://caddy/index.php/foo'...
Done.
=> Contacting URL: 'http://caddy/index.php/foo?a=1&b=2'...
Done.
=> Contacting URL: 'http://caddy/foo'...
Done.
=> Contacting URL: 'http://caddy/foo.php/foo'...
Done.
=> Contacting URL: 'http://caddy/file.php/filename_UTF8_en+coded_ใใใๅไฝใใใฏใ.png'...
Done.
=> Contacting URL: 'http://caddy/index.php/some%20%20whitespaces'...
Done.
Testing 'http://httpd'...
=> Contacting URL: 'http://httpd/lib/javascript.php/1599824490/lib/requirejs/require.min.js'...
Done.
=> Contacting URL: 'http://httpd/index.php/foo'...
Done.
=> Contacting URL: 'http://httpd/index.php/foo?a=1&b=2'...
Done.
=> Contacting URL: 'http://httpd/foo'...
Done.
=> Contacting URL: 'http://httpd/foo.php/foo'...
Done.
=> Contacting URL: 'http://httpd/file.php/filename_UTF8_en+coded_ใใใๅไฝใใใฏใ.png'...
Done.
=> Contacting URL: 'http://httpd/index.php/some%20%20whitespaces'...
Done.
Testing 'http://nginx'...
=> Contacting URL: 'http://nginx/lib/javascript.php/1599824490/lib/requirejs/require.min.js'...
Done.
=> Contacting URL: 'http://nginx/index.php/foo'...
Done.
=> Contacting URL: 'http://nginx/index.php/foo?a=1&b=2'...
Done.
=> Contacting URL: 'http://nginx/foo'...
Done.
=> Contacting URL: 'http://nginx/foo.php/foo'...
Done.
=> Contacting URL: 'http://nginx/file.php/filename_UTF8_en+coded_ใใใๅไฝใใใฏใ.png'...
Done.
=> Contacting URL: 'http://nginx/index.php/some%20%20whitespaces'...
Done.
Will do an image to rebuild your PR and trying the same run but using the new binary and the "vanilla" php_fastcgi
directive.
HTH, Matteo
I just tried it out with my PR, I got this result:
Testing 'http://caddy'...
=> Contacting URL: 'http://caddy/lib/javascript.php/1599824490/lib/requirejs/require.min.js'...
Done.
=> Contacting URL: 'http://caddy/index.php/foo'...
Done.
=> Contacting URL: 'http://caddy/index.php/foo?a=1&b=2'...
Done.
=> Contacting URL: 'http://caddy/foo'...
Test 'No rewriting to the index file i.e. non existing PHP file' failed:
=> KO PATH_INFO. Expected: '<false>' vs Actual: ''.
Test 'No rewriting to the index file i.e. non existing PHP file' failed:
=> KO QUERY_STRING. Expected: '<false>' vs Actual: ''.
Done.
=> Contacting URL: 'http://caddy/foo.php/foo'...
Test 'Non existing PHP file' failed:
=> KO PATH_INFO. Expected: '<false>' vs Actual: ''.
Test 'Non existing PHP file' failed:
=> KO QUERY_STRING. Expected: '<false>' vs Actual: ''.
Done.
=> Contacting URL: 'http://caddy/file.php/filename_UTF8_en+coded_ใใใๅไฝใใใฏใ.png'...
Done.
=> Contacting URL: 'http://caddy/index.php/some%20%20whitespaces'...
Done.
That seems successful to me I think?
Hi @francislavoie,
That seems successful to me I think?
Not sure: will look my evening.
The aim is to look if redirection will add something: <false>
means I cannot process that PHP file i.e. I cannot find a match for that SERVER VARIABLE while an empty string means I'm processing that file as PHP since I've found in the the output kind of [PATH_INFO> =>
.
You can look at the actual HTTP response by opening:
since I've exposed the three web servers for debugging purposes.
At a first glance - i.e. error prone for sure :wink: - there could be an issue w/ that output:
a. no redir to the default index file (index.php
): not the expected result
b. redir to the default idex file (index.php
): not the expected result, since PATH_INFO
should be /foo
and /foo.php/foo
respectively.
I could be wrong, need spare time to look into it.
HTH, Matteo
http://localhost:8080/foo and http://localhost:8080/foo.php/foo are both giving me empty PATH_INFO, e.g.
Array
(
[PHP_EXTRA_CONFIGURE_ARGS] => --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --disable-cgi
[HOSTNAME] => ff8f136f10f4
[PHP_INI_DIR] => /usr/local/etc/php
[HOME] => /var/www
[PHP_LDFLAGS] => -Wl,-O1 -pie
[PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
[PHP_MD5] =>
[PHP_VERSION] => 7.4.10
[GPG_KEYS] => 42670A7FE4D0441C8E4632349E4FDC074A4EF02D 5A52880781F755608BF815FC910DEB46F53EA312
[PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
[PHP_ASC_URL] => https://www.php.net/distributions/php-7.4.10.tar.xz.asc
[PHP_URL] => https://www.php.net/distributions/php-7.4.10.tar.xz
[PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[PHPIZE_DEPS] => autoconf dpkg-dev file g++ gcc libc-dev make pkg-config re2c
[PWD] => /var/www/html
[PHP_SHA256] => c2d90b00b14284588a787b100dee54c2400e7db995b457864d66f00ad64fb010
[USER] => www-data
[REMOTE_HOST] => 172.18.0.1
[HTTP_CACHE_CONTROL] => max-age=0
[REQUEST_URI] => /foo.php/foo
[SERVER_PROTOCOL] => HTTP/1.1
[CONTENT_LENGTH] => 0
[HTTP_ACCEPT_LANGUAGE] => en-US,en;q=0.5
[SCRIPT_NAME] => /index.php
[REQUEST_METHOD] => GET
[AUTH_TYPE] =>
[HTTP_X_FORWARDED_PROTO] => http
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
[HTTP_X_FORWARDED_FOR] => 172.18.0.1
[SERVER_SOFTWARE] => Apache
[GATEWAY_INTERFACE] => CGI/1.1
[REMOTE_ADDR] => 172.18.0.1
[HTTP_ACCEPT_ENCODING] => gzip, deflate
[HTTP_UPGRADE_INSECURE_REQUESTS] => 1
[SCRIPT_FILENAME] => /usr/share/caddy/index.php
[CONTENT_TYPE] =>
[DOCUMENT_ROOT] => /usr/share/caddy
[SERVER_NAME] => localhost
[REMOTE_USER] =>
[HTTP_HOST] => localhost:8080
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0
[QUERY_STRING] =>
[REQUEST_SCHEME] => http
[REMOTE_PORT] => 51082
[REMOTE_IDENT] =>
[SERVER_PORT] => 8080
[DOCUMENT_URI] => index.php
[PATH_INFO] =>
[FCGI_ROLE] => RESPONDER
[PHP_SELF] => /index.php
[REQUEST_TIME_FLOAT] => 1600675588.2357
[REQUEST_TIME] => 1600675588
[argv] => Array
(
)
[argc] => 0
)
So I think this is fine. Caddy will fallback to index.php if the file doesn't exist, and I guess that's slightly different than the nginx or apache configs. But that's not a relevant difference here I think.
That's with this config:
:80
root * /usr/share/caddy
php_fastcgi php-fpm:9000 {
env SERVER_SOFTWARE Apache
}
file_server
Hi @francislavoie,
So I think this is fine. Caddy will fallback to index.php if the file doesn't exist, and I guess that's slightly different than the nginx or apache configs. But that's not a relevant difference here I think.
The key point IMHO is fallback vs redirection including the original path (strong remapping): if it is a plain fallback, yes you're right :+1:. I'm not confident w/ Caddy but if that could be the default configuration, it would be fine since I can change it and decide to get a "Not found" error.
Just a quick thought for myself: how can I obtain the same behavior e.g. in Apache? Guessing something like:
DirectoryIndex index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^[^.]+$ index.php [L]
or using FallbackResource
.
Something similar should apply to Nginx too.
(Just to align the web server configurations to keep comparing apples w/ apples).
HTH, Matteo
Adding a note to myself on my previous comment:
Array
(
[HOSTNAME] => ff8f136f10f4
// ...
[REQUEST_URI] => /foo.php/foo
// ...
[SCRIPT_NAME] => /index.php
// ...
[SERVER_SOFTWARE] => Apache
// ...
[SCRIPT_FILENAME] => /usr/share/caddy/index.php
// ...
[DOCUMENT_ROOT] => /usr/share/caddy
// ...
[DOCUMENT_URI] => index.php
[PATH_INFO] =>
// ...
[argc] => 0
)
guessing the routing strategy of modern framework to be: given SCRIPT_FILENAME
be DOCUMENT_ROOT
+ SCRIPT_NAME
, REQUEST_URI
starts with SCRIPT_NAME
? Otherwise; we've found a fallback routing.
@francislavoie, looking at your HTTP response I've found a potential issue - a regression? - based on the previous one from the debug log of @SteffenDE and/or the output from "my tests", e.g. Apache and even Caddy v2.1.1.1:
"DOCUMENT_URI":"/lib/javascript.php",
vs your:
[DOCUMENT_URI] => index.php
It looks like we're missing a leading slash. Isn't it?
HTH, Matteo
Yeah I think that's correct re Apache config. Fallback to index.php is how modern frameworks are able to have their own routing (e.g. Laravel, Symfony, etc).
Re leading slash, that's just because the rewrite in try_files
doesn't have the leading slash for the index.php fallback. It's not a regression. That path is relative to the webroot anyways, so it's not strictly necessary.
If you want to try my PR, you can grab the CI artifact for Linux (look at the GitHub actions output for the Tests, you can download the artifact from there), and use a Docker volume to replace it at /usr/bin/caddy.
If you want to try my PR, you can grab the CI artifact for Linux (look at the GitHub actions output for the Tests, you can download the artifact from there), and use a Docker volume to replace it at /usr/bin/caddy.
TNX! Will do my evening.
HTH, Matteo
Hi @francislavoie,
I've update the "test suite" by using index.php
as fallback resource in each web server instance: the only difference now in Caddy is on PATH_INFO
being always defined but empty just for both /foo
and /foo.php/foo
which looks like not an issue in PHP: those using empty()
will be fine and those using isset()
will have an empty value.
@SteffenDE, would you mind to give caddy_Linux_go1.14_3e577ef
(from https://github.com/caddyserver/caddy/actions/runs/263950314) a try in your setup w/o changing anything of your configuration but the caddy
binary? TIA!
HTH, Matteo
I can confirm that using the binary from 3e577ef works with my Moodle setup using the default php_fastcgi
directive ๐
Excellent!
It's slightly too bad about the potential edge case(s) the fix introduces, but probably a worthwhile trade-off, especially if the edge cases involves the user configuring something weird, right?
Looking forward to getting it in as one of the first commits for the 2.3 tree, after 2.2 is released, hopefully this week.
Edit: Heh, it was the last commit for the 2.3 tree.
I just tried to replace apache for caddy but didn't get it running. It's not clear for me what is the solution.
@flaviobarros Please ask your usage questions on the Caddy community forums. Don't forget to fill out the thread template so we can help you!
Hey everyone, I'm trying to move from Caddy 1 to Caddy 2 and was in the process of installing a Moodle server (PHP) when I encountered the following issue:
When doing a GET request with path
https://moodle.domain/lib/javascript.php/1599824490/lib/requirejs/require.min.js
the PATH_INFO Variable (should be/1599824490/lib/requirejs/require.min.js
) is not set correctly:While debugging I saw that the URL.Path is already just
/lib/javascript.php
here and the rest is missing: https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go#L197I temporarily fixed this by using the origRequest, but this causes other issues as the (correct) rewrite of / to /index.php fails now.
I guess there is something going on with the default rewrites as there already is a split_path option there.
(caddy versions affected: 2.1.1, 2.2.0-rc.1, master)