Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do routing without .php extension with nginx and php

Before I start, I know there are many solutions in StackOverflow regarding this issue but they are not working for my case.

I set up a docker container running Nginx instance with PHP. When I enter such URL, myapp.com/somefile without .php at the end, it cannot find the file. I need to browse this URL to make it work myapp.com/somefile.php.

Here is my configuration with Dockerfile and Nginx config.

Dockerfile

FROM php:7.4.8-fpm

RUN apt-get update -y \
    && apt-get install -y nginx

# PHP_CPPFLAGS are used by the docker-php-ext-* scripts
ENV PHP_CPPFLAGS="$PHP_CPPFLAGS -std=c++11"

RUN docker-php-ext-install pdo_mysql \
    && docker-php-ext-install opcache \
    && apt-get install libicu-dev -y \
    && docker-php-ext-configure intl \
    && docker-php-ext-install intl \
    && apt-get remove libicu-dev icu-devtools -y
RUN { \
        echo 'opcache.memory_consumption=128'; \
        echo 'opcache.interned_strings_buffer=8'; \
        echo 'opcache.max_accelerated_files=4000'; \
        echo 'opcache.revalidate_freq=2'; \
        echo 'opcache.fast_shutdown=1'; \
        echo 'opcache.enable_cli=1'; \
    } > /usr/local/etc/php/conf.d/php-opcache-cfg.ini

COPY nginx-site.conf /etc/nginx/sites-enabled/default
COPY entrypoint.sh /etc/entrypoint.sh

COPY --chown=www-data:www-data . /var/www/html

WORKDIR /var/www/html

EXPOSE 80 443

ENTRYPOINT ["sh", "/etc/entrypoint.sh"]

nginx-site.conf

server {
    root    /var/www/html;

    include /etc/nginx/default.d/*.conf;

    index index.php index.html index.htm;

    client_max_body_size 30m;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ [^/]\.php(/|$) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        # Mitigate https://httpoxy.org/ vulnerabilities
        fastcgi_param HTTP_PROXY "";
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
}

How can I solve this issue? Any help would be appreciated!

Note: I tried to add this lines of code to the nginx config but i ended up downloading files instead of executing them :

location / {
    try_files $uri $uri.html $uri/ @extensionless-php;
    index index.html index.htm index.php;
}

location ~ \.php$ {
    try_files $uri =404;
}

location @extensionless-php {
    rewrite ^(.*)$ $1.php last;
}
like image 816
Gürkan Güran Avatar asked Nov 02 '25 06:11

Gürkan Güran


1 Answers

Yes, you cannot force nginx to force serving PHP script via PHP location handler with something like try_files $uri $uri.php .... You can try this config instead (yes, I know that some if blocks are evil, but don't worry, this one isn't):

location / {
    index index.html index.htm index.php;
    try_files $uri $uri.html $uri/ @extensionless-php;
}

location ~ \.php$ {
    # default PHP handler here, e.g.
    fastcgi_pass 127.0.0.1:9000;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

location @extensionless-php {
    if ( -f $document_root$uri.php ) {
        rewrite ^ $uri.php last;
    }
    return 404;
}

If you want to redirect all the not found requests to index.php, use this one instead:

location @extensionless-php {
    if ( -f $document_root$uri.php ) {
        rewrite ^ $uri.php last;
    }
    fastcgi_pass 127.0.0.1:9000;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}

Update @ 2025.03.05

To make URIs with trailing slashes workable too - e.g., both /somefile and /somefile/ - the named location should be changed as follows:

location @extensionless-php {
    rewrite ^(/.*)/$ $1;
    if ( -f $document_root$uri.php ) {
        rewrite ^ $uri.php last;
    }
    return 404;
}

for the first configuration example, and as follows:

location @extensionless-php {
    rewrite ^(/.*)/$ $1;
    if ( -f $document_root$uri.php ) {
        rewrite ^ $uri.php last;
    }
    break;
    fastcgi_pass 127.0.0.1:9000;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}

for the second one.

Note: Only URIs that do not correspond to physical directories under the web server root will be processed with the above configurations.

like image 98
Ivan Shatsky Avatar answered Nov 04 '25 23:11

Ivan Shatsky



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!