0

Due to different priorities of the parts of the PHP app, the goal here is to have one pool for general usage, and another for The /api/* URLs. To make things complicated, the app uses internal URL routing, so it's not possible to distinguish the two cases by only FilesMatch.

I've started with this:

<FilesMatch "\.php$">
    SetHandler proxy:fcgi://127.0.0.1:9000
</FilesMatch>

<LocationMatch "^/api/">
    SetHandler proxy:fcgi://127.0.0.1:9001
</LocationMatch>

This is in the global context, outside VirtualHost directives as there are multiple vhosts, all with the same requirement.

It doesn't work and all URLs are handled by the first pool (the one at :9000).

Any ideas how to create this configuration? This is for Apache 2.4.

Ivan Voras
  • 186
  • 2
  • 7
  • 1
    Do any URLs under `/api/` end with `.php`, cause if so, they're all getting matched by the first block. Try changing the order of the blocks to see if it helps. – GregL Mar 09 '16 at 15:30
  • The URL's don't end with .php's (AFAIK that's what Location matches), but the PHP files do. I.e. the URL's look like /api/whatever, and are mapped to /index.php/api/whatever by Rewrite. – Ivan Voras Mar 09 '16 at 16:42
  • That still means that all your `.php` files are going to be matched by the first block. Try changing their order. – GregL Mar 09 '16 at 16:43

2 Answers2

2

Ok, solved it with an If. Apparently something funny is going on with the translation of REQUEST_URI: at the time the If gets evaluated, it doesn't contain what I required, so I matched THE_REQUEST which contains the verbatim HTTP request. Here's how my solution looks like:

<FilesMatch "\.php$">
    # First pool, catches everything
    SetHandler proxy:fcgi://127.0.0.1:9000
    SetEnv PHP_POOL_ID "1"
</FilesMatch>

<If "%{THE_REQUEST} =~ m#/api/#">
    # Second pool, only for certain URLs
    SetHandler proxy:fcgi://127.0.0.1:9001
    SetEnv PHP_POOL_ID "2"
</If>

The SetEnv statements are for debugging only, they can be used in logs to track which pool has served the request, e.g. with:

CustomLog "/var/log/httpd/php_pool.log" "%h %l %u %t \"%r\" %>s %b php:%{PHP_POOL_ID}e" env=PHP_POOL_ID
Ivan Voras
  • 186
  • 2
  • 7
0

The URL's don't end with .php's (AFAIK that's what Location matches), but the PHP files do. I.e. the URL's look like /api/whatever, and are mapped to /index.php/api/whatever by Rewrite.

I think with such rewrites it wouldn't be possible to get what you want.

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName www.example.net

    DocumentRoot /vhosts/default/public_html

    <Directory /vhosts/default/public_html>
        DirectoryIndex index.html index.php
        Options -Indexes
        AllowOverride all
        Order allow,deny
        allow from all
    </Directory>

    SetEnv FCGI-PORT 9000

    <LocationMatch \.php$>
        SetEnv FCGI-PORT 9001
    </LocationMatch>

    <LocationMatch ^/api/>
        SetEnv FCGI-PORT 9002
        RewriteEngine On
        RewriteRule (.*) /index.php?route=%{REQUEST_URI} [R=301,L]
    </LocationMatch>

</VirtualHost>

Some basic tests

# curl http://www.example.net/
9000

# curl http://www.example.net/index.php
9001

# curl -I http://www.example.net/api/whatever
HTTP/1.1 301 Moved Permanently
Date: Wed, 09 Mar 2016 17:03:56 GMT
Server: Apache/2.2.15 (CentOS)
Location: http://www.example.net/index.php?route=/api/whatever
Connection: close
Content-Type: text/html; charset=iso-8859-1

# curl http://www.example.net/index.php?route=/api/whatever
9001

But if we comment rewrite rules - all works as expected

# curl http://www.example.net/
9000

# curl http://www.example.net/index.php
9001

# curl http://www.example.net/api/
9002

# curl http://www.example.net/api/test.php
9002

Try changing their order.

in this particular case (with rewrites) the order doesn't matter

P.S. index.php/test.php it's just a simple php script

<?php
    echo $_SERVER['FCGI-PORT'];
ALex_hha
  • 7,193
  • 1
  • 25
  • 40