Integrating Web Applications with Apache

Another option for proxying HTTP connections through Apache is mod_proxy, which provides ProxyPass, ProxyPassReverse and ProxyPassMatch among many other directives that provide more robust proxying options. I focus primarily on these three directives here. As mentioned previously, RewriteRule provides proxying of HTTP requests. Let's compare the example already given for proxying with RewriteRule and an example for ProxyPass:

ProxyPass /home http://back-end01.test:8080/

This ProxyPass statement provides roughly the same level of functionality as the RewriteRule statement with a more simplistic command. When a request comes in for any URL beginning with "/home", the request header will be rewritten so that the request will be received properly by http://back-end01.test:8080/. Consider the following first lines of an HTTP request:

From user to server:    GET /home/test/image.jpg HTTP/1.1
From server to back-end:    GET /test/image.jpg HTTP/1.1

The first line of the header contains the method (GET in this case) and the URL being requested. When the server receives the request from the client, it strips off "/home", as specified in the ProxyPass directive and forwards the request to the back-end server. If you want to proxy response packets as well as request packets, the following ProxyPassReverse statement can be paired with the previous ProxyPass statement:

ProxyPassReverse /home http://back-end01.test:8080/

The syntax is exactly the same as ProxyPass, adding to the simplicity of the mod_proxy configuration. This will take any HTTP response matching an HTTP request for /home and forward the response back to the original client. If you need to add some programmatic proxying (similar to RewriteCond), you can use the ProxyPassMatch. When implementing a forward/reverse proxy configuration, ProxyPassMatch can replace ProxyPass. Here's an example:

ProxyPassMatch "^/home/([a-z0-9]*/docs)" http://docserver01.test:8080/$1
ProxyPassReverse /home http://docserver01.test:8080/

This example suggests that within the /home folder, there are many sub-folders (let's say user names) and within each of those exists a folder named "docs". The USERNAME/docs URL exists on docserver01.test:8080 in the root of the web server, as denoted by the $1 in the server URL. The ProxyPassReverse will function in the same manner as it did in the previous example.

Securing websites with SSL in Apache is accomplished with mod_ssl. Although I won't discuss configuring SSL from the ground up, a few directives relate to proxied SSL connections: SSLProxyCheckPeerExpire, SSLProxyCheckPeerName and SSLProxyCheckPeerCN. It is a common practice to use self-signed certificates on back-end servers (provided a valid cert is in place on the user-facing server), and these directives address common issues that can arise when using self-signed certs. Any of these directives can have one of two arguments provided: "on" or "off". If set to "off", SSLProxyCheckPeerExpire will skip checking the expiration date on the SSL cert used on a back-end server. To avoid checking a certificate's common name or alternate names against the server name used to access a back end, set SSLProxyCheckPeerName to "off". In older versions of Apache, you might be able to use SSLProxyCheckPeerCN (set to "off") instead of SSLProxyCheckPeerName.

Along with rewriting URLs, it may be necessary to rewrite HTTP request or response header fields. In Apache, this is done with mod_headers. There are only two directives within this module: Header and RequestHeader. These directives are used to modify response and request header fields, respectively. Many actions can be used with either of these directives, but here, let's look at the set and edit actions—for example:

Header set ReceiveTime "%t"

This example will add and replace any existing header in an HTTP response named ReceiveTime and give it the value of the UNIX timestamp when the request was received by the server (represented by "%t").

If you need to replace the value of a header that comes from a back-end server, you would use the edit action. Consider the following example:

Header edit Location "^http://back-end01.test:8080/(.*)$"

This example will replace the Location attribute in an HTTP response, which will exist in a 301/302 redirect. If it finds http://back-end01.test:8080 at the beginning of the Location header, it replaces that part with "http://public.test" (the user-facing URL).


Andy Carlson has worked in IT for the past 13 years doing networking and server administration. He and his amazing wife have three daughters and a son, and they currently reside in Cincinnati, Ohio.