V2: Caddy php config help

Thanks for the details @WeidiDeng! And thank you for trying the Caddy 2 beta during its pre-release phase. :slight_smile:

@Whitestrake I wonder if there’s something a little bit wrong about how we’re setting up the php-fpm environment? It sounds like an MVC framework is complaining that a “controller index” doesn’t exist, maybe a missing file or some wrongly-rewritten URI? (Just throwing out ideas. Too late here for me to be debugging this.)

That’s what it sounds like to me, but I don’t know if it’s a php-fpm setup issue. Both the v1 and v2 PHP setups are pretty spartan on the Caddy side.

@WeidiDeng, I notice that the v2 config has no rewrites in it while the v1 rewrites to try files and then falls back to /index.php{uri}. Is the v2 config you posted the entire config you’re using?

Just a reminder that the v2 php_fastcgi directive does a rewrite under the hood: GitHub - caddyserver/caddy: Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

(not sure if relevant in this case)

1 Like

Oh, v2 setup isn’t as spartan as I’d thought, then! Might be relevant; the default doesn’t append {uri} to the end of /index.php, maybe the framework expects/requires that?

Could be. @WeidiDeng can test that: simply replace the php_fastcgi directive with the longer form in the docs (don’t do this normally! the single-line directive is usually preferred!) and then tweak the try_files line and see what happens.

1 Like

Using the long form, after some testing, I think I find what’s the problem, here is the long form

domain.com:8445 {
  tls off
  encode gzip
  root * /path/main_site
  
matcher indexFiles {
    not {
        path */
    }
    file {
        try_files {path}/index.php
    }
}
rewrite match:indexFiles {path}/ # No redirect required

# internally rewrite directory URIs to index.php files
try_files {path} {path}/ /index.php/{uri} # Last part is the problem

# proxy any requests for PHP files to backend via FastCGI
matcher phpFiles {
    path *.php
}
reverse_proxy match:phpFiles php-fpm:9000 {
    transport fastcgi {
        split .php
    }
}

  file_server
}

This time caddy emits error 404 when I request a url that should be processed by php, eg. cmd1, instead of passing /index.php/cmd1 to php, caddy tries to find the file or folder by the name. Also when in the short form, caddy invokes php-fpm, but passed an extra /index.php/ (/index.php/index.php/cmd1), causing the controller not found bug.

1 Like

@francislavoie What do you think about this? Should we append /{uri} to the last fallback of /index.php? Or is this a split_path problem?

As far as I can tell, thinkphp is a blatant fork of Laravel: GitHub - top-think/framework: ThinkPHP Framework

I don’t think any changes should be required for the fastcgi config to work, as I used the same fastcgi directive in my Caddyfile when I was testing it.

I think it’s most likely an environment issue.

Hmm, so we need to investigate more. There might be two things going on here.

This definitely needs to be fixed. Sounds like a bug on our end?

But I’m having trouble understanding now where we stand. @WeidiDeng this line here:

try_files {path} {path}/ /index.php/{uri} # Last part is the problem

To clarify: Did that make it work for you? I’m wondering because it’s not the same as what the short form does – this is the original:

try_files {path} {path}/index.php index.php

Did you find a variant that does work?

No, because I’m trying to pass the param to the index.php at the root (/index.php), but can’t do that, path resolution stops at trying to find folders.

Can you post the file structure of your app and the unredacted root path you’re using?

For Laravel apps, I typically point root to the public folder of the app. As far as I can tell, think does it the same way: think/public at 6.0 · top-think/think · GitHub

For me, this looks like root * /var/www/myapp/public

The app structure is like the following

tp5 # Thinkphp install root
├── application # Application Logic (Controller, Model, View)
│   ├── app1
│   ├── app2
│   ├── command.php
│   ├── common.php
│   ├── provider.php
│   └── tags.php
├── build.php
├── CHANGELOG.md
├── composer.json
├── config # Configuration
│   ├── app.php
│   ├── cache.php
│   ├── console.php
│   ├── cookie.php
│   ├── database.php
│   ├── log.php
│   ├── middleware.php
│   ├── session.php
│   ├── template.php
│   └── trace.php
├── extend
├── LICENSE.txt
├── public # **This is the root folder**
│   ├── favicon.ico
│   ├── index.php
│   ├── robots.txt
│   ├── router.php
│   └── static
├── README.md
├── route
│   └── route.php
├── runtime
│   ├── cache
│   ├── log
│   └── temp
├── think
├── thinkphp
│   ├── base.php
│   ├── composer.json
│   ├── CONTRIBUTING.md
│   ├── convention.php
│   ├── helper.php
│   ├── lang
│   ├── library
│   ├── LICENSE.txt
│   ├── logo.png
│   ├── phpunit.xml.dist
│   ├── README.md
│   └── tpl
├── thinkphp.md
└── vendor

Tp5 path is /path/to/tp5, the public path (i.e, the path that is served from the root) is /path/to/tp5/public, but the application is /path/to/tp5/application, which is different from laravel.

Yeah, that all looks fine. If the root in your Caddyfile is set correctly to your public dir, then it should work just fine.

My config looks like this, with a Laravel app:

:80

root * /var/www/public

encode gzip

php_fastcgi php-fpm:9000

file_server
1 Like

After reading the thinkphp document and error page, I found out that I have used thinkphp’s routing module which depends on path_info variable, however, caddy failed to pass that value, causing url resolution failed. That results in thinkphp using fallback index controller which doesn’t exist.

1 Like

Aha, now we’re getting somewhere. Sounds like the v2 implementation isn’t passing down some server params that v1 did.

@matt I’ll do some testing and I’ll let you know what I think is missing, but I think it’s a safe bet to provide the PATH_INFO var to fastcgi.

1 Like

I compared the fastcgi environment variables that Caddy v1 and v2 send over fastcgi, I see no relevant differences.

I went through the thinkphp v5 and v6 framework source code (specifically Request.php, which is where the request is bootstrapped from $_SERVER env vars).

The PATH_INFO var is not needed because there are fallbacks to use REQUEST_URI instead, which should be correctly set. You can probably test this yourself, try dumping $_SERVER in your index.php before the app is booted.

At this point I’m back to my previous answer of “it’s not Caddy, it’s your environment”. There must be something that you didn’t share with us that’s causing your issue.

Currently I’m using thinkphp 5.1, Request.php only treats REQUEST_URI as PATH_INFO when run as cli-server

The interface according to the log is CGI/1.1

Reading the code, seems like you should be able to configure pathinfo_fetch with REQUEST_URI to make it work…

But to me, it seems that thinkphp’s implementation on v5.1 seems incorrect.

Thanks, I was able to configure the configure the pathinfo_fetch was indeed the correct way to go. There are some remaining problem that I will look into.

1 Like

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