B
B
betterthanyouthink2020-04-20 10:43:30
PHP
betterthanyouthink, 2020-04-20 10:43:30

How to make routing in pure php, redirecting absolutely all requests to index.php?

I am writing a site in pure php, I ran into routing. The problem is this: .htaccess does not redirect all requests to index.php. For example, it processes requests like site.com, site.com/about, site.com/offers correctly, but if you enter a subfolder + an existing file in the url, the request will not be redirected to index.php and the file will open.

Those. request site.com/components/test.php - will not be processed and the page will be shown to the user. At the same time, if you enter a non-existent request with the same subfolder, then the request will be processed correctly: site.com/components/test_1.php - will redirect to the 404 page.

On the one hand, this behavior suits me, because all ajax requests go through without additional processing of routes. But on the other hand, I think it's bad from a security point of view. Tell me how to do it right or in which direction to dig. I plan to switch to Laravel as soon as I finish my project on pure php :)

.htaccess

AddDefaultCharset UTF-8
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php [QSA,L]


index.php

//url
$request_url = rtrim(ltrim(urldecode(parse_url($_SERVER['REQUEST_URI'],5)), '/'), '/');
$params = array_filter(explode("/", $request_url)); 
//если в url передано 2 параметра
if (count($params) == 2) {
    $dynamic_routes = [
        'offers' =>  'pages/offer.php',
    ];
    if (isset($dynamic_routes[$params[0]])) {
        $get = $params[1];
        require_once $dynamic_routes[$params[0]];
    }
    else require_once ('pages/404.php');
}
//если в url передано меньше двух параметров
elseif (count($params) < 2) {
    $routes = [
        '' => 'pages/main.php',
        'offers' => 'pages/offers.php',
        'about' => 'pages/about.php',
        'guarantees' => 'pages/guarantees.php',
    ];
    if (isset($routes[$request_url])) require_once $routes[$request_url];
    else require_once ('pages/404.php');
}

else require_once ('pages/404.php');

Answer the question

In order to leave comments, you need to log in

3 answer(s)
N
nokimaro, 2020-04-20
@betterthanyouthink

shorten .htaccess to this

AddDefaultCharset UTF-8
RewriteEngine on
RewriteRule !index\.php$ index.php [L]

The two crossed out lines just mean that if an existing file or an existing folder is transferred, then do not rewrite index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

I don't see any problems, from a security point of view, that existing files are given directly, without rewriting. Just don't have any scripts other than secure scripts or index.php in the root of your web server. Move all other scripts above the root of the web server (so that in principle they cannot be opened via url)
An important nuance: if you rewrite absolutely all requests to index.php, then all static files (css, jpg, js) that were previously given directly, they will be redirected to index.php and there you will have to resolve their return yourself, read the contents of the file, set the mime-type, and so on.

F
FanatPHP, 2020-04-20
@FanatPHP

There is such a proverb, "a bad head does not give peace to the feet."

I think it's bad from a security point of view.

With what fright?
If there are files that do not need to be exposed, they are simply placed behind the document root
. And such "routing" will give nothing but a headache.

A
Andrey, 2020-04-20
@AndryG

I'll add it for posterity. The single entry point can be built on a simpler module, 99% already in use, mod_dir

It is often desirable to have a single file or resource handle all requests for a particular directory, except those requests that match an existing file or script. This is often referred to as a "front controller".
In earlier versions of HTTPD, this effect was generally required by mod_rewrite, and the use of -f and -d tests for file and directory existence. Now it only requires one line of configuration.
FallbackResource / index . PHP
Existing files such as images, CSS files, etc. will be served normally.
Use the disabled argument to disable this feature if inheritance from the parent directory is not desired.

Example from a live site:
...
    <Directory "$base/$proj/www/i">
      FallbackResource disabled  - в папке картинок отключаем обработчик
      Header set Cache-Control "public, max-age=31536000"
    </Directory>

    <Directory "$base/$proj/www">
        Options -Indexes
        Require all granted
        DirectoryIndex disabled
        DirectorySlash Off
        FallbackResource /entry.php
    </Directory>
</Macro>

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question