Reasons not use Apache's error handler as a default mechanism? - php

Typical web-applications call a default single server object (e.g. a PHP script) each time a request comes in. In case Apache fails to find an applicable script or resource, Apache tries to deliver an error page.
Alternatively, one may design an web-app in such a way, that no scripts or resources exist in the vHost's htdocs/root directory. Thus, each request would force Apache to deliver an error page.
If we define a server-side script as the standard error handler, any URL will trigger the script. Thus, the single script would be the single point of action.
Is anybody aware of reasons, why this approach is wrong?

It seems that the page called by the ErrorHandler statement doesn't have access to form data such as $_GET, $_POST, $_REQUEST, $_COOKIE (at least in my install of Apache/PHP).
After daring a journey into the pit of hell that is Apache mod_rewrite I eventually escaped with the following incantation, which seems to work for me:
<Directory /same/as/document/root/>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule /* index.php
</Directory>
The first line enables mod_rewrite.
The second line sets the rewrite base to the document root, i.e. so that URLs of all subdirectories are processed.
The third line sets a condition such that the rule is only activated if the requested filename ("%{REQUEST_FILENAME}") doesn't exists ("!-f").
The fourth line matches all paths starting with a "/" and redirects them to index.php.
Disclaimer: I know very, very, little about both Perl regular expressions and Apache mod_rewrite.
Just beware that the user may type in a URL path of the form:
/some_directory/ or /some_directory
so you may have to handle both cases.

My guess is that this is a penalty for the webserver.
Each time a resource is requested, it searches the filesystem for a file and if it doesn't find one, the error handler script is searched and run.
And if for some reason PHP fails, you do not get any error pages anymore and Apache will log something like an error occurred and another one while handling the error in the error handler.

You could do it, but you'd probably have to jump through some hoops to get the original URL, and to avoid sending HTTP error codes. If your goal is to use PHP for all requests, you'd probably be better off using mod_rewrite.

Related

How I can redirect when request to download a file in Apache http server

I want to redirect to another url when request come to apache http for download a file
for example, client call https://example.com/download/apps/v1.01.apk
/download/apps/v1.01.apk is a real path
I want when call url apache prevent to download it and redirect to another url
For this, you will need to use a .htaccess file.
Create a .htaccess file, in the root of your project and type this into the file:
RewriteEngine on
Options -Indexes -Multiviews
RewriteRule ^(v1\.01\.apk)$ your-new-url.php
It's worth keeping in mind that when the web server first receives a request, the URL is just a string, and the server has to decide what to do.
One of the things it can do is look for a file on disk whose name matches the URL. If it finds a file, it can decide what to do with that information, perhaps combined with other information the browser sent in the request, or information it finds about the file.
Eventually, the server will come up with a response - maybe a response with the content of the file it found; maybe the result of running a particular script; maybe a response indicating a redirect to a different URL.
With most web server software, you can configure all of these decisions, in very flexible ways. So you can say "if the URL has a v in it, look for a file in this folder; if it exists, run this PHP script with the file name as an argument; if it doesn't, issue a redirect response to a URL where the v is replaced with an x".
For Apache, you will see a lot of advice to use .htaccess files to do this. These are not the primary configuration for Apache, but they are a convenient place to put extra configuration when you are using a shared server and can't edit the main configuration for security reasons.
The specific configuration line used to trigger a redirect response in Apache looks like this:
RewriteRule pattern-to-match-against-request url-to-redirect-to [R]
The first argument is a "regular expression" which can be as general or specific as you want. Note that . means "any character", so if you want to match a dot specifically, write \.
The second argument can contain variables like $1 and $2 which refer to parts of the requested URL "captured" by putting them in brackets in the pattern.
The [R] at the end can also have a type, like [R=temp] or [R=307], which will change how the browser handles the redirect, caches it, and so on. There are also other flags your can add, like [R,NC] for "Redirect, Not Case-sensitive".
Finally, you can add any number of RewriteCond lines before a rule, such as RewriteCond -f %{REQUEST_URI} meaning "if a file exists with the same name as the requested URL.

Use slash with get request

I'm in the process of working on an error system for my site (i.e., if MySQL encounters an error, it sends them to an error page). I'm wondering, is it possible to use a "/" instead of "?err=" for a URL?
What I'd like to do is have people sent to the url "/error/404/" but display on page the content at url "/error?err=404". Is there a way to do this with HTAccess, or something of the sort?
My current way is with lots of files and iframes, and it gets really annoying when you have to update one tiny little thing.
Thanks!
What you are looking for is url rewriting. You can set it up using an .htaccess file, given that your installation of apache has mod_rewrite enabled (if not, check this question).
Here is a nice tutorial on how to do it.
Have a try with this:
RewriteEngine on
RewriteRule ^error/(\d+)$ error?err=$1 [L,QSA]
This should not end in a redirection loop, since this requires a trailing number in the URI.
Note that I removed your leading slashes from both the pattern and the result. .htaccess style files work on relative paths.
In general you should always prefer to place such rules inside your http servers host configuration instead of using .htaccess style files. Those files are notoriously error prone, hard to debug and the really slow the server down. They are only available as a last option for users who do not have access to the host configuration, for example when using a cheap hosting provider.

Handle multiple sublink depths with php with little or no mod rewrite dependency

I am trying to write a content management system and have hit a snag while trying to develop seo friendly urls. I am using php to handle urls, however I have a problem when I try to get the REQUEST_URI for more than one depth level. I am trying to avoid using .htaccess to handle this, because I would like the system to be fairly easy to set up on IIS/nginx/etc also and do not want it to be apache dependent any more than is necessary.
I have in my htaccess file
FallbackResource index.php
and then in my php I have a class that handles the REQUEST_URI slug by checking to see if a record exists in the mysql database. This works fine if the request is something like
http://example.com/foo
however throws an internal server error if the request is
http://example.com/foo/bar
This seems to occur even if I have a completely blank index.php, so I suspect the answer must be at the htaccess level. How can I get my system to handle multiple REQUEST_URI depth levels? Do I need to use a mod rewrite regex or is there a less apache dependent solution?
My bad, I needed to change my .htaccess rule from
FallbackResource index.php
to
FallbackResource /index.php
The missing slash was causing the error. -.-

mod_rewrite stripping long values from HTTP header

I'm using OpenAthensSP to return IdP metadata that can potentially access our service. OpenAthensSP returns this data in the form of environment variables in the HTTP(s) header, which we then read in PHP (from $_SERVER).
So far so good.
However, when mod_rewrite is used to rewrite the URL that is called by OpenAthens, the metadata (ie., the environment variables from OpenAthens contained in the HTTP header) is stripped out. I have shown this in side-by-side testing: directly calling a PHP script (metadata present) vs rewriting the URL to the exact same PHP (metadata stripped, but other values e.g. cookies present and unchanged). The values that are stripped out have very long values (too long to sociably paste here - more than 100k) - that's the only potential problem I can see. The values are correctly URL encoded.
I have tried setting things like LimitRequestFieldSize and LimitRequestLine in Apache but they don't have any effect, so I think the problem must lie with mod_rewrite.
So the question, essentially, is:
How can I keep very long values intact in the HTTP header while still using mod_rewrite?
The current solution I have is not great, I have had to do this (httpd.conf fragment from VirtualHost section):
# /discovery is the URL called by OpenAthens to supply us IdP metadata
RewriteCond %{REQUEST_URI} ^/discovery [NC]
RewriteRule .* - [L]
# ... other rewrites here to send (nearly) everything else to index.php ...
ErrorDocument 404 /index.php
This way, index.php receives the "/discovery" request and lo-and-behold the lengthy values in $_SERVER are present and correct, although a 404 is triggered, which needless to say is ugly and hacky.
What I can't do is simply send the output from OpenAthens directly to a valid page (e.g., discovery.php) because the metadata is needed to populate a login form that has to exist within the PHP framework being used - which has to start off with index.php.
(In case it matters: this is on CentOS 5.6 / Apache 2.2.3)
As someone who's used OpenAthensSP quite a bit, I know that the data is passed in the Apache sub-process environment, not the HTTP header - it never goes to the user's client. This also explains why LimitRequestFieldSize and LimitRequestLine don't have any effect - they only apply to the HTTP request header. I suspect what's happening is that your rewrite rules are interfering with the request in some way. If they're creating an internal request, you might have better luck using the apache_getenv function in PHP rather than relying on $_SERVER variables.

Pretty URLs without mod_rewrite, without .htaccess

Without a possibility to access .htaccess I find myself in a creative impasse. There is no mod_rewriting for me. Nevertheless, I want to be able to do the nice stuff like:
http://www.example.com/Blog/2009/12/10/
http://www.example.com/Title_Of_This_Page
What are my alternatives?
In respond to the answers:
I'm building with php5
I don't have access to .htaccess
http://www.example.com/index.php/Blog/ is a known technique but I don't prefer it. Is shows the php so to say.
How would I create extensionless PHP-files? Would this do the trick?
How much would using the custom 404 technique hurt performance?
If you've the permissions to set custom error documents for your server you could use this to redirect 404 requests.
E.g. for Apache (http://httpd.apache.org/docs/2.0/mod/core.html#errordocument)
ErrorDocument 404 /index.php
In the index.php you then can proceed your request by using data from the $_SERVER array.
You can also have urls like
http://domain.com/index.php/Blog/Hello_World
out of the box with PHP5. You can then read the URL parameters using
echo $_SERVER['PATH_INFO'];
Remember to validate/filter the PATH_INFO and all other request variables before using them in your application.
I know this question is very old but I didn't see anyone else suggest this possible solution...
You can get very close to what you want just by adding a question mark after the domain part of the URL, ie;
http://www.example.com/?Blog/2009/12/10/
http://www.example.com/?Title_Of_This_Page
Both of the above HTTP requests will now be handled by the same PHP script;
www.example.com/index.php
and in the index.php script, $_SERVER['REQUEST_URI'] for the two pages above will be respectively;
Blog/2009/12/10/
Title_Of_This_Page
so you can handle them however you want.
A quite simple way is to:
declare a 404 ErrorDocument (e.g. PHP) in .htaccess
parse the query using $_SERVER and see if it corresponds to any result
if so replace the HTTP status 404 with status 200 using header() and include index.php
If you omit a trailing slash, Apache will serve the first file [alphabetically] which matches that name, regardless of the extension, at least on the 2 servers I have access to.
I don't know how you might use this to solve your problem, but it may be useful at some point.
For example if
http://www.somesite.com/abc.html and http://www.somesite.com/abc.php both exist and http://www.somesite.com/abc is requested, http://www.somesite.com/abc.html will be served.
The only way is to use custom 404 page. You have no possibility to interpret extensionless files with PHP interpreter without reconfiguring the web server's MIME-types. But you say that you can't edit even .htaccess, so there's no other way.
You can write a URI class which parses the user-friendly URL you defined.
If the MultiViews option is enabled or you can convince whoever holds the keys to enable it, you can make a script called Blog.php that will be passed requests to example.com/Blog/foo and get '/foo' in the $_SERVER['PATH_INFO'].

Categories