Tampilkan postingan dengan label Apache Web Server. Tampilkan semua postingan
Tampilkan postingan dengan label Apache Web Server. Tampilkan semua postingan

Minggu, 29 Mei 2011

How Does Apache Server Work With PHP Module?

Q: How the HECK does Apache server work with PHP module? What is the flow in which an HTTP request makes through a PHP-enabled Apache web server?

Problem
I have WAMP (Version 2.0) installed on my Windows 7 operating system. For those who don't know, WAMP is an acronym that stands for Windows Apache MySQL PHP. Just so you know this versino of WAMP comes with the following versions of Apache, MySQL, PHP:

- Apache version 2.2.11
- PHP version 5.3.0
- MySQL version 5.1.36

I need to enable the rewrite module of Apache to process URL rewrite rules, so I have the following line in httpd.conf:

LoadModule rewrite_module modules/mod_rewrite.so
I enable rewrite logging at "C:\wamp\logs\rewrite.log" so I can see how rewriting is done via adding the following line in httpd.conf right after Loadmodule:

RewriteLog "C:\wamp\logs\rewrite.log"
RewriteLogLevel 9

I also have the following line in httpd.conf to enable PHP processing:

LoadModule php5_module "c:/wamp/bin/php/php5.3.0/php5apache2_2.dll"
Now an HTTP request goes through Apache, which hands it to the rewrite module to process URL rewrite handling, and has the resulting URL go through PHP engine. But how does Apache rewrite module supposed to know when it should stop rewriting the URL and hand it to PHP module? Is there any way we can control when the processing goes to PHP engine through rewrite rules? Let's answer these questions below.

By the way if you need to know how Apache server variables including %{DOCUMENT_ROOT}, %{REQUEST_URI}, %{REQUEST_FILENAME} work refer to Test Whether a Server Variable is Empty in Popular Web Servers.

Questions?

My Answers
Simply by having the line 'LoadModule php5_module "c:/wamp/bin/php/php5.3.0/php5apache2_2.dll"' in httpd.conf, PHP is enabled to handle pages with extension 'php' (e.g. black-jacket.php) after Apache passes the page through to PHP module. By the way if you'd like PHP to also be able to handle pages with other extensions add the following line after LoadModule in httpd.conf (so PHP handles .html too):

AddType application/x-httpd-php .html
Now here's the interesting part. How the HECK does Apache rewrite module know when to pass through the request to PHP module? The answer is ONLY if and ONLY when the request is NOT matched by ANY rewrite rule, the request is passed through to PHP handler. Even funnier is that there is absolutely NO control you have in the rewrite rules to tell Apache to pass through to PHP handler right away! If you don't agree let me know.

I've tried [L] and [PT] on the RewriteRule directive but when the request matches that particular directive, the request is "internally redirected" to rewrite module again and it's processed by the rewrite module again! In rewrite log it looks like this:

127.0.0.1 - - [29/May/2011:22:26:46 +0800] [localhost/sid#d33140][rid#2254c80/initial/redir#1] (4) [perdir C:/repository/trunk-php/] RewriteCond: input='C:/repository/trunk-php/cache/index.php' pattern='-f' => matched
127.0.0.1 - - [29/May/2011:22:26:46 +0800] [localhost/sid#d33140][rid#2254c80/initial/redir#1] (2) [perdir C:/repository/trunk-php/] rewrite 'index.php' -> '/cache/index.php' # this rule has [L] but it's still internally redirected to rewrite module as the following log statement suggests
127.0.0.1 - - [29/May/2011:22:26:46 +0800] [localhost/sid#d33140][rid#2254c80/initial/redir#1] (1) [perdir C:/repository/trunk-php/] internal redirect with /cache/index.php [INTERNAL REDIRECT]
127.0.0.1 - - [29/May/2011:22:26:46 +0800] [localhost/sid#d33140][rid#2351398/initial/redir#2] (3) [perdir C:/repository/trunk-php/] strip per-dir prefix: C:/repository/trunk-php/cache/index.php -> cache/index.php
127.0.0.1 - - [29/May/2011:22:26:46 +0800] [localhost/sid#d33140][rid#2351398/initial/redir#2] (3) [perdir C:/repository/trunk-php/] applying pattern '(.+)$' to uri 'cache/index.php'
...

The log statement in RED tells you the request is internally redirected to Apache rewrite module for handling again. Only when no rewrite rules have been matched by the current request will you see the following line in the rewrite log:

127.0.0.1 - - [29/May/2011:22:27:52 +0800] [localhost/sid#d33140][rid#228b510/initial/redir#2] (1) [perdir C:/repository/trunk-php/] pass through C:/repository/trunk-php/cache/index.php
Meaning that the Apache rewrite module is finally done with handling the request, and it's the next handler's job to handle it. In this case PHP engine will simply render C:/repository/trunk-php/cache/index.php.

So how do you add a handler and control the order of the handlers? To my disappointment I have NOT found any document online that answers this question. There is "AddHandler" directive in httpd.conf that's supposed to do that but loading the PHP module does that implicitly already.

Conclusion
So the conclusion is that ONLY if and ONLY when the request is NOT matched by ANY rewrite rule, the request is passed through to PHP handler. There is absolutely NO control you have in the rewrite rules to tell Apache to pass through to PHP handler right away! Not by using 'last' option [L] or 'pass through' option [PT] at the end of RewriteRule directive. If you don't agree let me know.

Knowing this fact you may find it impossible to handle the rewrite logic you have in mind. Think deeper and the solution will come. For example you may have a rewrite rule that you'd like the rewritten URL to go straight to PHP engine right away, and you add [L] to that rule which immediately internally redirects the rewritten URL to rewrite engine again (and therefore all the server variables such as %{QUERY_STRING}, %{REQUEST_FILENAME} and %{REQUEST_URI} are updated accordingly) and make the request go through each rule again. In that case you'll have to make sure the request is NOT matched by any RewriteRule and therefore passed through to PHP handler.

If you have any questions please let me know and I will do my best to help you!

Test Whether a Server Variable is Empty in Popular Web Servers

Q: How to test whether a variable is empty in server configurations of popular web servers such as Apache and Nginx?

Problem
It is AMAZING how unfriendly server configuration syntax can be. Even tasks as small as testing whether a value is empty can be confusing. Since I've personally used Apache and Nginx for a long time allow me to unravel the mysteries of how to evaluate whether a servervariable (e.g. document root, query string, etc.) is empty in server's configuration file.

Solution for Apache
In your httpd.conf or .htaccess simply use ="" to evaluate whether an Apache server variable is empty. Use !="" to test whether an Apache server variable is NOT empty. Here's an example:

RewriteEngine on
...
RewriteCond %{DOCUMENT_ROOT}/cache%{REQUEST_URI} -f
RewriteCond %{QUERY_STRING} =""
RewriteRule (.+)$ /cache/$1 [L]
...

This block of rules basically checks whether %{DOCUMENT_ROOT}/cache%{REQUEST_URI} exists as a file and whether the HTTP request has no URL parameters. If both are true rewrite current request to /cache/{current request uri}.

Common Apache Server Variables: By the way the following is some comments that tell you how common server variables such as %{DOCUMENT_ROOT}, %{REQUEST_URI} and %{REQUEST_FILENAME} work as they are often confusing as hell:

#
# Suppose your website is http://www.mensfashionforless.com/
# and document root is set to /usr/repository/trunk (via DocumentRoot directive in httpd.conf).
#
# Now someone issues a request for
# http://www.mensfashionforless.com/2010/10/g-by-guess-grey-low-boot-cut-jeans.html
# then the following is a list of common Apache server variables and their values:
#
# %{DOCUMENT_ROOT} = /usr/repository/trunk
# %{REQUEST_URI} = /2010/10/g-by-guess-grey-low-boot-cut-jeans.html
# %{REQUEST_FILENAME} = /usr/repository/trunk/2010/10/g-by-guess-grey-low-boot-cut-jeans.html
#

Questions? Let me know!

Solution for Nginx
Nginx is a popular web server for its speed and efficiency. Simply use ='' to check whether an Nginx server variable is empty. use !='' to check whether an Nginx server variable is not empty. Here's an example:
server {
listen 80;
server_name www.mensfashionforless.com;
rewrite_log on;
...
location / {
# test whether $document_root/cache$request_uri exists
# in the file system
if (-f $document_root/cache$request_uri) {
set $test P;
}
# test whether there's no URL argument to this request
# = '' tests whether the value is empty!
if ($args = ''){
set $test "${test}C";
}
# if both of the above tests are true, do the rewrite
if ($test = PC){
rewrite ^/(.+)$ /cache/$1 last;
break;
}
...
}
...
}
This block of code checks whether $document_root/cache$request_uri exists as a file in the file system AND whether there is no URL parameter to this HTTP request. If both are true rewrite current request to /cache/{current request uri}. Refer to the post on How do I test multiple conditions in Nginx server configuration? if you are confused by the syntax of testing multiple conditions.

If you have any questions please let me know and I will do my best to help you!

Minggu, 17 April 2011

Fix 403 Error When You Go To Your Website's Web or Document Root

Q: How do you fix 403 error when you go to your website's homepage?

For example suppose your website is http://www.mensfashionforless.com/ but when you go there you see something like the following if your web server is Nginx:

403 Forbidden



nginx/0.6.32


And you see the following if your web server is Apache:

Forbidden

You don't have permission to access /
on this server.


SOLUTION
And you wonder WHY?? The answer is easy. You need to configure your web server to do two things:

1. Allow access to the document root.
2. Specify what file or script to run when document root is accessed.


If you are using Apache and the web root is C:\repository\trunk-php, then the following configuration is an example of allowing access to your document root (placed in httpd.conf):

<directory "C:\repository\trunk-php">
...
Allow from all
...
</Directory>

<IfModule dir_module>
DirectoryIndex index.php
</IfModule>


You'll have to go through Apache's tutorial to find exactly how the configuration works, but the above configuration basically says everyone is allowed to access C:\repository\trunk-php via whatever reachable name. For example if your website can be reached by 127.0.0.1, 192.168.0.33, www.mensfashionforless.com this configuration makes your site accessible by all of them. When you do go to www.mensfashionforless.com you'll see C:\repository\trunk-php\index.php as the 2nd part of the configuration suggests.

If you are using Nginx the configuration may look something like this:

server {
listen 80;
server_name www.mensfashionforless.com;
...
location / {
root /home/repository/trunk-php/;
index index.php
allow all;
}
}


This configuration means when you go to www.mensfashionforless.com you'll see /home/repository/trunk-php/index.php served and 'allow all' means it's accessible from all reachable names.

Error Reflected In The Log
By the way you can also see the 403 error reflected in your log. In nginx log you'd see:

2011/03/08 14:40:59 [error] 7659#0: *1 directory index of "/home/repository/trunk-php/" is forbidden, client: 61.218.81.34, server: www.mensfashionforless.com, request: "GET / HTTP/1.1", host: "www.mensfashionforless.com"

In Aache log you'd see:

[Tue Mar 08 23:17:25 2011] [error] [client 127.0.0.1] Directory index forbidden by Options directive: C:/repository/trunk-php/

Questions? Let me know!

Kamis, 17 Maret 2011

How Do You 301 Redirect a Naked Domain To a Subdomain such as www

QUESTION
How do you 301 redirect a naked domain to some sub domain, most commonly www, so that when someone goes to yourDomain.com they'll be 301 redirected to www.yourDomain.com?

ANSWER
For those who don't understand what 301 redirect is here's a quick answer. When your webpage has been moved to a new place you usually want to set your web server to tell whoever wanting to access your old webpage that it's been moved to a new place permanently. This behavior is realized with a 301 redirect. If the client is a search engine they'll know your web page has been moved permanently.

There are at least 2 ways to 301 redirect a naked domain to a subdomain:

1: In your IP host setting add an 'A record' with host @ and configure your web server accordingly.

2: Have your domain name registry do that for you.


Below we'll look at each method in more detail and also look at the pros and cons of each.

1. In your web host setting add an 'A record' with Host set to @ that points to your machine's IP and configure your web server accordingly.
In your web host setting add an 'A record' with Host set to @ that points to your machine's IP.

If you use GoDaddy.com here's a screen shot of that setting:

GoDaddy DNS Manager A Host Setting For Naked Domain

Once you finish the setting you may need to wait for up to 1 hour for the setting to take effect. Then configure your web server to recognize the naked domain and 301 redirect it to any subdomain you want such as www. This depends on the capabilities of your web server but it should have this feature. For example if you use Nginx and your domain is mensfashionforless.com then here's what you put in your web server's configuration file:

server {
listen 80;
server_name mensfashionforless.com;
rewrite ^/(.*) http://www.mensfashionforless.com/$1 permanent;
}


This rule simply means that the web server listens on port 80 and it responds to domain name 'mensfashionforless.com' by 301 redirecting it to 'www.mensfashionforless.com' (what 'permanent' means).

In fact, this rule exhibits a great benefit that this way offers: You have total control over how the redirect happens. In this case you'll be able to redirect http://mensfashionforless.com/some-page.html to http://www.mensfashionforless.com/some-page.html. Again you have total control.

2. Have your domain name registry do that for you.
Have your domain name registry (e.g. GoDaddy) do that for you (read http://www.printfection.com/help/article.php?articleid=41 if you use GoDaddy). Basically you'll be able to pick 'Forward Domain' option to forward your naked domain, or non-www domain, to any domain you'd like via 301 redirect. Typically you'd forward your naked domain to your www domain but you can actually forward it to any domain you want.

This depends on the abilities of the registry you registered your domain with but they usually have this functionality.

This way is very limited because you might not be able to forward your old path to your new path. For example you might want to redirect http://mensfashionforless.com/some-page.html to http://www.mensfashionforless.com/some-page.html but whether you can do this totally depends on your web host. In addition your web host, although unlikely, can alter their functionality any time they want. You are basically at their mercy.

Questions? Shoot me an email.

Minggu, 30 Januari 2011

How To Set Up Virtual Hosts On Apache

Apache is such a well known web server that it needs no introduction to any webmaster in the world. Despite its abundant resources in development and documentation many of its features are still confusing to newcomers to using Apache web server. For example, how do you set up multiple hosts on a single instance of Apache? You may know as much as using NameVirtualHost and VirtualHost directives but it's incredibly hard to find on the web easy-to-understand step-by-step instructions on setting up those directives. So I decided to write a post to tell you how those directives work and how to achieve our goal.

While going through this tutorial if you have additional questions regarding the directives simply look it up on Apache's website at http://httpd.apache.org/docs/1.3/mod/core.html.

Let's create a real life example!
1. I own two web hosts: www.mensfashionforless.com and www.oneminuteinfo.com, and they both point to one machine whose IP is 221.148.47.99.

2. I configured the DNS for both hosts to go to 221.148.47.99 correctly. This depends on the registrar you use to register those hosts. Typically they provide you with an admin user interface to manage the relevant settings for configuring your hosts such as DNS and MX record.

3. On 221.148.47.99 machine I create one web root directory for www.mensfashionforless.com which is /home/httpd/vhosts/www.mensfashionforless.com/httpdocs/ and I create one web root directory for www.oneminuteinfo.com which is /home/httpd/vhosts/www.oneminuteinfo.com/httpdocs/.

4. Now when an HTTP request is made to www.mensfashionforless.com or www.oneminuteinfo.com it's resolved to 221.148.47.99, and Apache would use the correct web root directory for the incoming request. Any request made to www.mensfashionforless.com will be served by /home/httpd/vhosts/www.mensfashionforless.com/httpdocs/ and any request made to www.oneminuteinfo.com is served by /home/httpd/vhosts/www.oneminuteinfo.com/httpdocs/.

You should be able to do step 1, 2, 3 (if not let me know). The hard part is step 4. Essentially you can have as many hosts pointing to the same machine as you like, and Apache simply uses the requested host name as a hint to know which local directory should be used to serve that request. First let's look at how the relevant directives work. You can put these directives in the Apache configuration file (default location on most Linux machines is /etc/httpd/conf/httpd.conf) or put them in other files and have the main Apache configuration file include those files.

How NameVirtualHost and VirtualHost work
NameVirtualHost: This directive defines what host or IP and/or port are considered to be virtual hosts. Hosts/IPs not matching it will not be considered and virtual hosts and thereby not treated as such.

In our example I simply use wildcard to match any IP but limit it to port 80, as follows:

NameVirtualHost *:80
VirtualHost: This directive defines host configurations for host/IP matching some specified virtual host/IP. In our example I use wildcard to match any IP and restrict to port 80, and specify that if server name is www.mensfashionforless.com use /home/httpd/vhosts/www.mensfashionforless.com/httpdocs/ as the document root. If server name matches www.oneminuteinfo.com then use /home/httpd/vhosts/www.oneminuteinfo.com/httpdocs/ as the document root, as the following:

<VirtualHost *:80>
ServerName www.mensfashionforless.com:80
ServerAlias www.mensfashionforless.com
DocumentRoot /home/httpd/vhosts/www.mensfashionforless.com/httpdocs
# ... additional config parameter such as DirectoryIndex, CustomLog, ErrorLog, etc.
</VirtualHost>

<VirtualHost *:80>
ServerName www.oneminuteinfo.com:80
ServerAlias www.oneminuteinfo.com
DocumentRoot /home/httpd/vhosts/www.oneminuteinfo.com/httpdocs
# ... additional config parameter such as DirectoryIndex, CustomLog, ErrorLog, etc.
</VirtualHost>

You MUST use fully qualified domain name in the value of ServerName and ServerAlias! For example do NOT use mensfashionforless.com:80 as the value of ServerName! As I mentioned you may put these directives in the Apache configuration file (default location on most Linux machines is /etc/httpd/conf/httpd.conf) or put them in other files and have the main Apache configuration file include those files. Restart your Apache server and try it! Typical command to do that is /etc/init.d/httpd restart :-)

Again any questions let me know!

Rabu, 18 Agustus 2010

How to Install WAMP, Java, Hibernate, and Eclipse

MenuHome
Install and Configure WAMP
Install and Configure Java
Install and Configure Hibernate
Install and Configure Eclipse
This is not an uncommon request for someone who wants to run a web server with an underlying database, backed by a server side programming language, assisted by several important one off or periodic tasks - me. Okay if it's just me then it might have been uncommon, but I have gone through a lot to finally have all these tools set up, so I'd like to share my experiences with you.

First of all I'd like to tell you why I am doing this. I'd like my web server (Apache) to serve dynamic content (PHP) driven by my database (MySQL) and dynamic content driven by one off or regular tasks (Java) with an easy way to manipulate my database content via Java objects (Hibernate), and I'd like to develop my Java code in a user friendly IDE (Eclipse). Last but not least I'd like to do ALL of these FREE, and they certainly are

Let's get right down to it! Click on the next section.

Install and Configure WAMP ▶

Senin, 01 Februari 2010

About Apache .htaccess

What is .htaccess?

Simply put, .htaccess if a file you can create in your document root to do all types of handling on a per-directory basis when your server receives a request. Such handling includes what server features are made available, password authentication, URL rewriting, URL redirecting, etc. Suppose you are a book site and your directory structure looks like this:

/book-name/chapter1/section1/...

You can have .htaccess in /, in /book-name, in /chapter1, etc. each with its own set of configurations that will override the directories higher up in the tree. This allows directory specific configurations. The most common configuration is URL rewriting and URL redirecting.


How do I change Apache .htaccess WITHOUT restarting Apache server?

You do NOT need to restart Apache after you change your .htaccess in order for your change to be reflected. I am using Apache/2.0.52 (CentOS) Server and this is true in this server. If you misconfigure .htaccess you'll see 500 Internal Server Error after you reload the page. For a comprehensive tutorial visit Apache Tutorial: .htaccess files


How do I quickly 301 redirect a page to another with .htaccess?

Easy. You simply add the following code in .htaccess:

RewriteEngine on
RewriteRule old-page.html$ http://new-site.com/new-page.html [L,R=301]


Once you save it refresh old-page.html and it should 301 redirect to http://new-site.com/new-page.html. Before you can do that you need to make sure the mod_rewrite module has been installed and enabled on your Apache server. Most likely this is true. For a comprehensive tutorial on the module visit Apache module mod_rewrite


How come my .htaccess does NOT work?

If after you edit .htaccess you don't get the desired effect, then most likely AllowOverride is messing things up. You may have "AllowOverride None" somewhere up in the hierarchy that makes Apache ignore your .htaccess in question. One quick way to find out is put junk in .htaccess and fresh your page. If you get no error, that means Apache is ignoring it and you almost certainly have "AllowOverride None" in effect. If you get errors, that means Apache is accessing it and you'll need to fix the errors. In either case check error log or ask your administrator if you don't have such access.
 
support by: infomediaku.com