patternphpMinor
As basic as routing in PHP can get
Viewed 0 times
canphpgetroutingbasic
Problem
I'd like to have neater URLs, no more and no less — I'd like to be able to write
I've looked at various PHP frameworks and routing classes to see how they did it. Since most of them come with features I don't need, I wanted to try making my own system using only what's absolutely necessary — indeed, I think this is about as basic as routing can get.
Above all, I'd like to know if I've missed something. The code works, but I'm sure there are edge cases I didn't account for (or security issues; this is PHP after all).
On a side note, is there a difference betwen "routing" and "URL rewriting"? The terminology isn't all that clear to me.
.htaccess
inc/functions/routing.php
As you can see, it's really only one function that does the work:
What you do with those is up to you — in this case, I'm simply including a file with that name.
index.php
inc/content/default.php
inc/content/users.php
```
';
}
else
{
/page/subpage instead of something like ?p=page&s=subpage.I've looked at various PHP frameworks and routing classes to see how they did it. Since most of them come with features I don't need, I wanted to try making my own system using only what's absolutely necessary — indeed, I think this is about as basic as routing can get.
Above all, I'd like to know if I've missed something. The code works, but I'm sure there are edge cases I didn't account for (or security issues; this is PHP after all).
On a side note, is there a difference betwen "routing" and "URL rewriting"? The terminology isn't all that clear to me.
.htaccess
RewriteEngine on
RewriteBase /routing_test/
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]inc/functions/routing.php
<?php
define('DEFAULT_PAGE_NAME', 'default');
function getPageName($level)
{
$requestParams = explode('/', $_SERVER['REQUEST_URI']);
$scriptPath = explode('/', $_SERVER['SCRIPT_NAME']);
// remove the base path
while ($requestParams[0] === $scriptPath[0])
{
array_shift($requestParams);
array_shift($scriptPath);
}
if ($level === 0)
{
return $requestParams[0] ?: DEFAULT_PAGE_NAME;
}
return isset($requestParams[$level]) ? $requestParams[$level] : '';
}As you can see, it's really only one function that does the work:
getPageName($level) gives the name of the "directory" at the specified level.What you do with those is up to you — in this case, I'm simply including a file with that name.
index.php
Routing Test
inc/content/default.php
This is the default pageinc/content/users.php
```
';
}
else
{
Solution
On a side note, is there a difference betwen "routing" and "URL rewriting"? The terminology isn't all that clear to me.
Yes. Generally, "routing" describes the process of mapping URLs to code in some form. The standard example would be mapping a URL to a method of a controller.
On the other hand, "rewriting" doesn't map a URL to code, but maps a URL to a different URL.
[But both terms are often not 100% clearly defined, and are sometimes used interchangably]
Security: DOS
If I visit your
You shouldn't need a while loop here, replacing the script path without the index.php file name in the request parameter should do the same thing.
Security: Directory Traversal
Your
Correctness: URL encoding
Because you use
Do note though that the URL encoding is currently all that protects you from XSS (and that the encoding happens client-side, so you should not necessarily trust it).
Approach
If it's just about mapping
If you want the URL routing functionality, I would probably go with a more extended approach, which lets me define a whitelist of allowed URLs, and maps them to a controller method.
Yes. Generally, "routing" describes the process of mapping URLs to code in some form. The standard example would be mapping a URL to a method of a controller.
On the other hand, "rewriting" doesn't map a URL to code, but maps a URL to a different URL.
[But both terms are often not 100% clearly defined, and are sometimes used interchangably]
Security: DOS
If I visit your
index.php directly, without giving any parameters, I get an infinite loop in getPageName. You shouldn't need a while loop here, replacing the script path without the index.php file name in the request parameter should do the same thing.
Security: Directory Traversal
Your
index.php file is likely open to directory traversal and LFI in Windows (I don't have a Windows machine to test right now, but using \ should work). With current PHP versions, it is restricted to PHP files, but it should probably still be fixed. Correctness: URL encoding
Because you use
REQUEST_URI, the values you get will be URL encoded. So if I visit /users/foo"bar, I would get Displaying user #foo%22bar. instead of the expected result. For the example this may be fine, but it will likely cause bugs in the future.Do note though that the URL encoding is currently all that protects you from XSS (and that the encoding happens client-side, so you should not necessarily trust it).
Approach
If it's just about mapping
/page/subpage to ?p=page&s=subpage, I would probably use Apache URL rewriting exclusively (I'm no expert, but it should certainly be possible).If you want the URL routing functionality, I would probably go with a more extended approach, which lets me define a whitelist of allowed URLs, and maps them to a controller method.
Context
StackExchange Code Review Q#124269, answer score: 5
Revisions (0)
No revisions yet.