URL rewriting with parameters in .htaccess - php

I've been searching lot of related tutorials and so on from Google to solve this on my own, but with zero luck. Therefore I am here to ask. I am trying to 'prettify' my project URL by rewriting. I am not sure are these all achievable anyhow, because I am just starting to get my head around the subject.
I am working 'example' on localhost project folder localhost/example. File '.htaccess' is located in that folder. Where I have set the following:
RewriteEngine On
RewriteBase /example
So basically my application now generates a URL consisting at least 1 parameter all the time and another pointing current location.
Current URL: localhost/example/admin.php?e=2&p=frontpage
Fantasy: localhost/example/admin/2/frontpage
About the parameters:
p stands for selected page
e stands for event
Okay lets think this all is achievable easily, do I have to change all the attributes to match current shown url?
Now they are:
href="?e=2&p=settings"
Should they be:
href="2/settings" ?
I am checking what value GET parameter P has, then including that page into content area.
That is pretty much it, pretty too complex for me, but for education purposes I really want to understand this thru and thru. Thank you.
EDIT:
With the added
RewriteRule ^admin.php/(.*)$ /admin.php?e=$1 [L,QSA]
I am getting lot of pathing errors, whole site is without styling and js files.
EDIT 2:
RewriteEngine On
RewriteBase /example
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule /admin.php/e=?(.*)$/p=?(.*)$ /admin.php?e=$1?p=$2 [L,QSA]
Now urls are following:
http://localhost/example/admin.php/2/inc/vex/vex.css
http://localhost/example/admin.php/2/css/modestgrid.css
It is not showing the page in url and the paths are not correct.
They should be http://localhost/example/admin.php/css/modestgrid.css

Your question is a bit vague, contradictory and it is unclear how you actually want to handle (reference) your asset files. But in general I'd say this should be a starting point to get you going:
RewriteEngine On
RewriteBase /example
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/(.*)$ $1.php?e=$2&p=$3 [END]
For this to work you obviously need the apache rewriting module to be installed and loaded, you need to take care that the interpretation of dynamic configuration files is enabled at all (AllowOverride directive) and you have to place such file in the correct location with reading permission for the http server process.
In case you get an internal server error (http status 500) for that chances are that you operate a very old version of the apache http server. In that case you probably need to replace the [END] flag with the [L] flag which probably will work here too. You will find a hint on that in your http servers error log file in that case.
And a general hint: you should always prefer to place such rules inside the http servers (virtual) host configuration instead of using dynamic configuration files (.htaccess style files). Those files are notoriously error prone, hard to debug and they really slow down the server. They are only supported as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).

Related

How redirect to subfolders using .htaccess file?

I'm new in php and trying to build my website.
I have created folder structure on my server listed below.
development (folder)
admin (folder)
.htaccess ( copied from internet)
index.html (file with coming soon banner)
I want to set my .htaccess file to load index.html file by default when users open (abcd.com).
And subfolders would access with hitting the url like abcd.com/admin or abcd.com/developement.
But I did some stupid changes in .htaccess file so it redirect the users to my admin login page which i don't want them to see. ;(
Thanks in Advance.
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?abcd.com$
RewriteCond %{REQUEST_URI} !^/admin/web/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /admin/web/$1
RewriteCond %{HTTP_HOST} ^(www.)?abcd.com$
RewriteRule ^(/)?$ /admin/web/index.php [L]
It is a bit unclear why you actually ask this question...
As a web developer you surely should be able to find your way around the rewriting options the apache http server offers by looking into the documentation. But even if not: as #AmanjotKaur pointed out the default behavior of that http server is to serve the index.html file if present. If that is not the case then you should take a look at the DirectoryIndex directive offered by mod_dir... Also it should be easy to simply roll back to an older version of that dynamic configuration file you used (".htaccess"), if you are using a revision control system for your development as you certainly should. Or by using a simple backup which you hopefully have ...
A general hint here is to simplify the situation: instead of trying to implement rules to direct incoming requests simply separate the contents. Your "production site" (which I understand is not usable yet) should not host any content, but just that placeholder you already have. Development should not be done on the same site! Use a separate http server for that or at least a separate host name inside the same http server. That is much easier and offers much more reliable protection.
Anyway, there are situations where one indeed wants to redirect all incoming requests to some specific document or router script, with a few explicit exceptions. This might be what you are looking for here. Since your question is a bit vague in that (your question mentions the path /admin, but your rules implement the path /admin/web/...) we can only give you a starting point. You will have to make your way from there. For which you undoubtedly need to take a look into the documentation of the apache http server's mod_rewrite which you want to use on that dynamic configuration file.
Here is something whici I assume implements something along the lines of what you are looking for. You certainly need to adapt it to your needs, though. You'd need to revise your question and be much more precise in what you actually want if you need further help with that. There is an edit button below your question. Use it ...
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/index\.html$
RewriteCond %{REQUEST_URI} !^/admin/
RewriteCond %{REQUEST_URI} !^/development/
RewriteRule ^ /index.html [R=301]
RewriteCond %{REQUEST_URI} !^/admin/web/
RewriteRule ^/?admin/(.*)$ /admin/web/$1 [END]
RewriteCond %{REQUEST_URI} !^/development/web/
RewriteRule ^/?development/(.*)$ /development/web/$1 [END]
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
In case you receive an internal server error (http status 500) using the rule above then chances are that you operate a very old version of the apache http server. You will see a definite hint to an unsupported [END] flag in your http servers error log file in that case. You can either try to upgrade or use the older [L] flag, it probably will work the same in this situation, though that depends a bit on your setup.
This implementation will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

redirecting a dynamic url to another dynamic url in htaccess [duplicate]

This question already has answers here:
URL rewriting with PHP
(5 answers)
Closed 3 years ago.
I would appreciate if someone could help me. I’m getting so confused.
I want to redirect
https://xklsv.me/viewblog.php?title=working-plans-survey-and-demarcation-of-the-karnataka-forest-department/aranya_kfd/November-8th-2018
To:
https://xklsv.me/working-plans-survey-and-demarcation-of-the-karnataka-forest-department/aranya_kfd/November-8th-2018
but 301 moved permanantly not working giving 200 ok status code
Well, this sounds pretty straight forward, exactly as the documentation shows in examples:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^title=working-plans-survey-and-demarcation-of-the-karnataka-forest-department/aranya_kfd/November-8th-2018$
RewriteRule ^/?viewblog\.php$ /working-plans-survey-and-demarcation-of-the-karnataka-forest-department/aranya_kfd/November-8th-2018 [R=301,QSD]
RewriteRule ^/?working-plans-survey-and-demarcation-of-the-karnataka-forest-department/aranya_kfd/November-8th-2018/?$ /viewblog.php?title=working-plans-survey-and-demarcation-of-the-karnataka-forest-department/aranya_kfd/November-8th-2018 [END]
If that should be implemented in a more general way that should work:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^title=([^&]+)$
RewriteRule ^/?viewblog\.php$ /%1 [R=301,QSD]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?([^/]+)/?$ /viewblog.php?title=$1 [END,QSA]
You may need to tweak this a little, but it should point you into the right direction...
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
In case you receive an internal server error (http status 500) using the rule above then chances are that you operate a very old version of the apache http server. You will see a definite hint to an unsupported [END] flag in your http servers error log file in that case. You can either try to upgrade or use the older [L] flag, it probably will work the same in this situation, though that depends a bit on your setup.
This implementation will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

Renaming url using .htaccess or other method

I'm a beginner in PHP, there is a one thing which I haven't been able to find an answer or I just don't know what to search.
I've made a PHP script which shows user info from database using GET parameter.
The url looks like this http://127.0.0.1/user-info.php?userid=testuser what I want to do is to make the url look like this http://127.0.0.1/user-info/testuser. How is this possible, is it done with .htaccess or using php and how?
Thank you in advance.
Sure this is possible, rewriting is usually done on the protocol level, so inside the http server, it has nothing to do with the php engine:
RewriteEngine on
RewriteRule ^/?user-info/(.+)$ /user-info.php?userid=$1 [END]
This rule works likewise in the http server's host configuration or in a dynamic configuration file (".htaccess" style file). For this to work the http server's rewriting module has to be enabled, obviously. And if you decide to use a dynamic configuration script that also will have to be supported and enabled.
In case you receive an "internal server error" (http status 500) using above rule then chances are that you operate a very old version of the apache http server. In that case replace the END flag with the L flag, should work too in this case, though it depends on other rewriting rules you have. In any case you will find a definite hint on the unknown END flag in the http servers error log file.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).
I think you need something like this, give it a try. Just replace url(index.php with user-info.php)
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^([a-zA-Z]*)/?([a-zA-Z]*)?/?([a-zA-Z0-9]*)?/?$ index.php?controller=$1&action=$2&id=$3 [NC,L]
OR
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
You can get a .htaccess file from zend expressive, it has everything you need - https://github.com/zendframework/zend-expressive-skeleton/blob/master/public/.htaccess. It passes all requests to index.php file where you can do further routing and then request processing.
As a router I recommend FastRoute (https://github.com/nikic/FastRoute). Also take a look at composer - it is a must have tool for php developer.

How to call a function in class/function format from localhost

I am using Yii2 framework for my PHP development. In my view files, If I want to call any of the functions, I just use Class/Function name
Eg : www.example.com/SiteController[class name]/index[function name]
And it is calling the function.
I like to know, How to do the same in a pure php script ?.
I searched in many places and I could get the suggestions for special_autoload_register();. But I could not understand the exact practical application.
Guidance is expected and Thanks is advance.
Its easy :).
It's all based on apache module mod_rewrite. This module allows you to modify path behavior in .htaccess file.
Using this .htaccess file
RewriteEngine On
# The following rule tells Apache that if the requested filename
# exists, simply serve it.
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
# The following rewrites all other queries to index.php. The
# condition ensures that if you are using Apache aliases to do
# mass virtual hosting, the base path will be prepended to
# allow proper resolution of the index.php file; it will work
# in non-aliased environments as well, providing a safe, one-size
# fits all solution.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::$
RewriteRule ^(.*)$ - [E=BASE:%1]
RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]
you will get following behavior:
If requested file exists (/styles/style.css - styles, javascripts, images, etc) serve it (dont change anything on current behavior)
If requested file doesn't exist, go to index.php.
If you are redirected to index.php, you can find full requested url in $_SERVER['REDIRECT_URL'] or $_SERVER['REQUEST_URI']. There you can take it, parse and based on requested uri, behave.
Please take this as explanation post, not a guide on how to get this going. Mostly it requires some apache configuration because mod_rewrite is mostly disabled by default.
If you want to get things going, I would recommend this post.
To fully answer your question, you can for example explode request uri by "/" sign, save first part into $firstPart and second into $secondPart and then have
$controllerName = $firstPart."Controller";
$controller = new $controllerName;
$actionName = $secondPart."Action"
$response = $controller->$actionName();
So if you call /help/me, helpController->meAction() will be called.
I hope I helped :)
To do this, Yii 2 (and other PHP frameworks) have routers. The router in Yii 2 is the UrlManager class.
I would not advice you write a router from scratch for a solution you want to deploy. There are routing packages in PHP which you could easily use in your solution. I like Klein. It's a pure router in PHP.
However, if for academic purposes, you want to know how routing works in PHP, get to understand the $_SERVER reserved variable. It has all the details of the HTTP request coming to your script. You can then use the details from this to call the specific function you want to call.

POST request to SEO URL Forbidden

I have a basic MVC system that is sending POST data to URLs such as
admin/product/add/
But this is giving me an error
Forbidden
You don't have permission to access
/admin/product/add/ on this server.
Additionally, a 404 Not Found error was encountered while trying to
use an ErrorDocument to handle the request.
The RewriteRule is simply
RewriteRule ^(.*)/$ index.php?uri=$1
Last time I saw this on a server changing file/directory permissions to 755 seemed to fix it but not this time. I have never really understood the reason for the error so was hoping someone may be able to provide some more information?
You have 2 errors:
You don't have permission to access /admin/product/add/ on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
The 2nd one is quite certainly a consequence of the same bug. You may have something in your apache configuration which remove 404 errors from default http server handling and push it to your php application, if this php application was working we would have a nice 404, but...
The first one tells you your php application is not running at all.
So. This first error tell us that apache did try to directly access the directory /path/to/documentroot/admin/product/add/ on your server and to produce a listing of it (well a listing of the directory content would be done only if apache were authorized to do so). But of course this is not a real directory on your server. It is a virtual path in your application. So apache ends up with a 404 (which leads to error 2).
The application handles a virtual path, apache does not manage it. The RewriteRule job is to catch the requested path before apache is trying to serve it and give it to one single php file (index.php) as a query string argument.
So... this rewrite rule was not applied. Things that could prevent this rule to be applied are numerous:
mod_rewrite not activated: is the module present and enabled (RewriteEngine on)?
syntax error: mod rewrite syntax is quite hard to read, sometimes really complex. But here it seems quite simple.
The RewriteRule resulting file is maybe not a valid target for apache. If the index.php file is not present in the DocumentRoot, or not readable by the apache user, then apache will fail. Warning: having a file readable by the apache user means having read rights on the file but also execution rights on all parents directories for the apache user. This is where your classical chmod/chown solutions are fixing the problems.
The rule must be in a valid configuration file. Is this rule in a an apache configuration file, inside a Location or Directory section? Or maybe in the global scope -- this may alter the rewrite Rule syntax--. Or is it in a .htaccess file? If it's a .htacces does apache reads the .htacces files and are mod-rewrite instructions allowed there (AllowOverride None). Isn't there others .htaccess files taking precedence?
So to fix the problem:
If you have an apache version greater than 2.2.16 you can replace the RewriteRule by FallbackRessource /index.php to check that this does not come from a mod-rewrite problem.
try to directly request index.php, so that at least a direct request to this file does work
try to directly access a valid ressource on the documentRoot (a txt file, an image, something that should not be handled by the rewrite but directly served)
check that if any of your virtual paths could map real physical paths Apache is not trying to serve the physical one (like when you write a RewriteCond %{REQUEST_FILENAME}-d) but really push the path to index.php
check apache error logs.
debug mod_rewrite with RewriteLog and RewriteLogLevel
collect facts, settings and tests, and then push that to SO or Servfault.
So the problem is quite simple: the php application is not receiving the request. But there are a very big number of ways to end in this state. The message in itself is not very important. The only way to find the error is to check all parameters (or to have years of bug fixing experience and developing a pre-cognitive intuition organ for lamp bugs -- usually a beard --, like admins). And the only way for us to help you is to find strange facts in a big list of configuration details, this is why good questions contains a lot of informations, even if all theses informations looks simply "classical" for you.
EDIT
To clarify the problem you should edit your answer, track the POST requests with tools such as Chrome developpers tools or firebug (keep the network tracking in record mode to catch several POSTS) or try to replay the post with Live HTTP headers reply. You should try to isolate the problematic POST and give us details. Debug is not magical.
Now I know one magical random POST failure. It's the empty GET url bug. It could be that (or not). If you have one empty GET url hidden somewhere (<IMG SRC="">, url() in css, or an empty LINK in headers for example. As theses hidden POST are defined in HTTP as "replay-the-request-which-launched-the-source-page, and some browsers even replay the POST that gives you the page if they found one. This could lead to broken hidden POSTS.
It could be also that the POST is not sent to the right server. Hard to say. So please collect informations from your comments, add some more network analysis and edit the question which is now really containing not enough facts.
Try this:
RewriteCond %{REQUEST_METHOD} =POST
RewriteRule ^(.*)/$ index.php?uri=$1
Use this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?uri=$1 [L]
Also use only www or non-www domain but not both at the same time. Redirect users with htaccess where you would like like to...
NonWWW to WWW:
RewriteCond %{HTTP_HOST} !^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
WWW to NonWWW:
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^www\.(.*)$ http://%1/$1 [R=301,L]

Categories