I did some .htaccess code to make PHP API route.
It's working in apache ( local server )
Options -MultiViews
RewriteEngine On
#What does this mean??
RewriteRule ^(.+)$ quizAPI.php?url=$1 [QSA,L]
But when I moved mine code to server it's not working because it not an apache.
I am trying to make API URL Like this :
example.com/users/get/
#What does this mean??
RewriteRule ^(.+)$ quizAPI.php?url=$1 [QSA,L]
Not quite sure of the difference between Apache and LiteSpeed in this respect (perhaps a difference in how the request is mapped to the filesystem?), however, this is only working on Apache arguably by "chance". The reason being, when you request /users/get/ the above rewrites as follows:
Request /user/get/
Rewrite (1st pass) to quizAPI.php?url=user/get/
Rewrite process then starts over (due to the L flag)
Rewrite (2nd pass) to quizAPI.php?url=quizAPI.php&url=user/get/ (due to the QSA flag)
Rewrite process then starts over (due to the L flag)
Rewrite (3rd pass) to quizAPI.php?url=quizAPI.php&url=user/get/ (again)
Rewriting process stops since the URL has passed through unchanged.
This still "works" (on Apache) since the url parameter (as read by your PHP script) is still user/get/ (the 2nd instance of the url param overwrites the first in the $_GET array). And there is no rewrite-loop. LiteSpeed, however, might be triggering another pass by the rewrite engine (causing a "loop").
However, we need to prevent that second pass by the rewrite engine (on Apache as well) and I would expect this would resolve the issue on LiteSpeed as well.
One way is to prevent the rewrite from occurring when quizAPI.php is requested. For example:
RewriteCond %{REQUEST_URI} !^/quizAPI\.php$
RewriteRule (.+) quizAPI.php?url=$1 [QSA,L]
However, this still rewrites all static assets (CSS, JS, images, etc.) to your script (which I'm assuming must "OK", since it "works" on Apache), but this might need further modification in the future.
Alternatively, if your URLs that you pass to quizAPI.php don't contain dots (that otherwise delimit file-extensions) then it would be simpler to only match URLs that don't contain dots instead (which avoids the need for the preceding condition). For example:
RewriteRule ^([^.]+)$ quizAPI.php?url=$1 [QSA,L]
And this naturally avoids rewriting requests for your static assets as well.
Related
On my website I want to internally execute a url like mydomain.com/dir/test as mydomain.com/dir/process.php?arg=test
I already created a htaccess file within the folder "dir", and when I try to access mydomain.com/dir/test, it displays the page of process.php, but when I try to access $_GET["arg"], it does not contain the string test but the string process.php.
My .htaccess:
RewriteEngine On
RewriteRule ^(.*)$ process.php?arg=$1 [L]
Reason for your result is a rewriting loop. You try to stop the rewriting process by using the [L] flag, but as many others you miss understand what that flag actually does. It does not end the rewriting process, but only the current run of that process. In your case the rewriting process starts another run and again rewrites your already rewritten request. In the second run the pattern ^(.*)$ matches what you have rewritten to in the first run, that explains your outcome.
You have two options to solve this.
1) use a condition to prevent the second rewriting run:
RewriteEngine On
RewriteCond %{REQEUEST_URI} !/process\.php$
RewriteRule ^(.*)$ process.php?arg=$1 [L]
2) use the END flag which is provided by newer versions of the apache http server:
RewriteEngine On
RewriteRule ^(.*)$ process.php?arg=$1 [END]
In case you receive an internal server error (http status 500) using that second 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.
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).
This URL rewriting lines work fine till the query string line, and after the query string any of them not work.
ReWriteEngine On
ReWriteRule ^home?$ /mysite/index.php
ReWriteRule ^gallery?$ /mysite/gallery.php
ReWriteRule ^([a-z0-9]+)?$ /mysite/owner.php?name=$1
ReWriteRule ^about?$ /mysite/about.php
ReWriteRule ^location?$ /mysite/location.php
The first two lines home and gallery works as expected (including the third line query string), but the other two lines about and location don't work.
If I requested those two pages with the rewritten name, the pages not comes to browser (the response is nothing, besides I am getting the same page with i am currently on - not even getting a 404 error message), but if I requested those pages with the original name with the .php extension the page comes to the browser. I tried putting those two about and location at the top of the query string line, then those two pages work fine as expected, but when they are below of the query string line then only they don't work.
Can I know what is wrong with the URL Rewriting methoed? I still can't able to figure the problem out.
There are a number of issues with your attempt, here is a slightly modified version:
ReWriteEngine On
ReWriteRule ^/?home/?$ /mysite/index.php [END]
ReWriteRule ^/?gallery/?$ /mysite/gallery.php [END]
ReWriteRule ^/?about/?$ /mysite/about.php [END]
ReWriteRule ^/?location/?$ /mysite/location.php [END]
ReWriteRule ^([a-z0-9]+)/?$ /mysite/owner.php?name=$1 [END]
The order of rules is important. The more general ones should be placed below the more specialized ones.
In case you experience a http status 500 (server internal error) with above setup 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 which should also work fine in this scenario.
Above rules will work likewise in the real http servers host configuration and in dynamic configuration file.
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).
I would change the order of these
ReWriteRule ^([a-z0-9]+)?$ /mysite/owner.php?name=$1
ReWriteRule ^about?$ /mysite/about.php
ReWriteRule ^location?$ /mysite/location.php
To
ReWriteRule ^about$ /mysite/about.php [L]
ReWriteRule ^location$ /mysite/location.php [L]
ReWriteRule ^([a-z0-9]+)$ /mysite/owner.php?name=$1 [L]
And add the last flag.
what happens is that the ^([a-z0-9]+)? is more generic and matches and changes the URL before the last 2 rules are reached.
In other words, if you had a URL with about it matches this ^([a-z0-9]+)? gets changed and then does not match the actual rule for it. So by putting the more generic rule last you can avoid this.
Also as I said in the comments, I would add the [L] flag in or Last so that it ends the rewriting once a match is done, otherwise you can get unexpected matches.
You can also combine some of these (probably)
ReWriteRule ^(about|location)$ /mysite/$1.php [L]
I am pretty sure that the ? means the preceding match is optional, but I removed it because if not then the capture group is optional. So I am not sure what the purpose you had of having it there. Because as I read it this means ^about?$ with the t being optional...
I am working on a first attempt at a RESTful API. I have designed some simple classes to represent each element of my system including a Message and Room class (it's a chat application with any amount of rooms containing any amount of messages).
I constantly see URIs in the form of, for example
/room (this would get all rooms)
/room/{room_id} (this would create, update or delete a room with this ID)
/room/{room_id}/message (this would get all messages from a room with the specified ID)
/room/{room_id}/meesage/{message_id} (this would create, update or delete a message with this id)
So I guess my two questions are:
1) How do I redirect these requested URIs to my single handling script (located in /api/api.1.0.0.php)
2) How do I request these URIs with the correct HTTP verb like put, delete, update etc.
EDIT: I should add that I am looking to do this without a framework.
Here is how to use mod_rewrite on apache to redirect all requests to a single script. You will need to use apache and have mod_rewrite installed/setup (it is installed on most shared hosting and is easy to add to a self managed system).
Create a .htaccess file in the sub-folder where the API exists under the document root. Add the following to the file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?URI=$1 [L,QSA]
The first condition will make sure the file doesn't exist so you can still load files that do exist (without it, requests for even valid files will rewrite). The second condition does the same but checks that it isn't a valid directory that is being requested. The last line, the rule, captures the URI and tells apache to load index.php instead passing the URI to the URI get parameter. At the end of the rule are flags, L and QSA. The L flag tells apache to stop processing rules if this one is satisfied and the QSA tells apache to automatically append any query string (get string) parameters that were passed.
You can then access the URI in php using $_GET['URI']. A simple $URI = explode('/', $_GET['URI']); will get you a nicely formatted array of each parameter passed.
As for directing to correct part of the app after requesting particular url you should read about routers. All of the major MVC frameworks will have advanced routing solutions. http://framework.zend.com/manual/current/en/modules/zend.mvc.routing.html
If you want to go without framework and use single scripts Apache mod_rewrite is your friend.
For creating requests using different http methods use any of the REST clients like Postman for Chrome.
EDIT:
.htaccess example:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [NC,L]
I don't even know how this method is called, I just know the behavior I want to achieve.
My example for this is Facebook. If you go to facebook.com/[username or id] you get to the profile page, but I can't imagine that they're creating a directory in their root folder and putting a index file in there for every user.
So how's the following behavior accomplished; You go to somepage.com/foo/bar/hello but actually you're requesting somepage.com/foo?bar=hello ?
Is this even possible with Apache and PHP?
I don't even know how this method is called, I just know the behavior I want to achieve.
That thing is called URI/URL and the local part of it is passed to a webserver. The webserver then processes the request.
Is this even possible with Apache and PHP?
Yes. Not even even. This is what a webserver is for. What happens on the server is entirely shielded by the HTTP protocol which knows only the URI/URL specification which does not regulate if and how that needs to match to concrete processes or files on the webserver.
For example with the Apache HTTP Server there is a famous module called Mod_Rewrite that does URL-Rewriting. Often in a fashion that the user with her browser does not take any notice of it.
Example configuration with a PHP file (Apache HTTPD):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]
</IfModule>
In a PHP script you can obtain the URI/URL by making use of special variables like $_SERVER['REQUEST_URI'] and $_SERVER['QUERY_STRING'].
Commonly this is made with mod rewrite. There you can make a "path" to a variable of a script.
E.g. http://example.com/user/1/edit could be translated with mod rewrite to http://example.com/index.php?function=edit&userid=1
Such a rule would look like this:
RewriteEngine on
RewriteRule ^/user/([0-9]+)/([a-z]+)$ index.php=function=$2&userid=$1 [L]
The first line activated the rewrite module the second line has a regular expression which must match for rewrite the url internally. If you like you can also make that externally with an [R] modifier instad of the [L].
Have a look to the whole documentation to learn more.
The stuff in the breckets are so called flags which are also well documentated.
I hope that helps!
Here's the contents of .htaccess:
Options -Indexes
RewriteEngine On
RewriteBase "/"
# Disallow direct access to PHP files.
RewriteRule ^(.*)\.php$ $1 [F,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(?<!common/dispatch\.php/)(.*)?$ common/dispatch.php/$1 [NS,L]
Essentially I have all my pages (PHP files) arranged as they would be for direct access without mod_rewrite but I also have dispatch.php in a directory called common, through to which I want all requests to be directed so that I can do some processing before the page script is executed.
It's basically the same idea as used by most frameworks, except I want the page hierarchy to be at the top level and the dispatch script to be kept out of the way with some other bits and pieces in its own subdirectory.
This script works fine on my development machine (which is running PHP as mod_php), but on the production machine it produces an error saying "No input file specified." if running under FCGI. Under normal CGI it works for the most part but if, for example, I go to /foo/bar (with trailing slash missing) and /foo/bar is a directory in the docroot, it sends me to /foo/bar/?/foo/bar. The rest of the script works fine but I don't really want my URIs getting mangled like this, and ideally I'd like to be able to use FCGI as well.
A potential fix for the problem with FCGI seems to be to put the matched $1 in the query string (i.e. after a ?), but this causes all sorts of other odd behaviour that I haven't been able to fix. Is there a straightforward way of fixing this?
Would it not be easier just to use the auto_prepend_file directive in php?