Z-Car

Building a custom version of Apache 2.4 on CentOS – Support for socket.io proxying

Last year I needed a way to create a specific Apache version that would support proper handling of proxying socket.io  connections to a Node client.  I had to hunt around, however here are some notes I created to get the version I needed built.

There are a lot of threads on the Internet that point to running Apache 2.4 on RHEL 6 as being a difficult setup. It’s actually quite easy, thanks to Apache’s wonderful packaging. Since Apache builds their source packages so they can easily be compiled into RPMs. (All of these steps were performed on a fresh installation of CentOS 6.6.)

First we need to install all of the tools for building RPMs and create the directory structure –

yum -y install rpm-build
mkdir -p ~/rpmbuild/{SOURCES,SPECS,BUILD,RPMS,SRPMS}

Let’s start by downloading the Apache Httpd sources and trying to compile –

cd ~/rpmbuild/SOURCES
wget http://www.gtlib.gatech.edu/pub/apache/httpd/httpd-2.4.4.tar.bz2

Now we can identify the missing dependencies and figure out how to continue –

# rpmbuild -tb httpd-2.4.4.tar.bz2 
error: Failed build dependencies:
    autoconf is needed by httpd-2.4.4-1.x86_64
    apr-devel >= 1.4.0 is needed by httpd-2.4.4-1.x86_64
    apr-util-devel >= 1.4.0 is needed by httpd-2.4.4-1.x86_64
    pcre-devel >= 5.0 is needed by httpd-2.4.4-1.x86_64
    openldap-devel is needed by httpd-2.4.4-1.x86_64
    lua-devel is needed by httpd-2.4.4-1.x86_64
    libxml2-devel is needed by httpd-2.4.4-1.x86_64
    distcache-devel is needed by httpd-2.4.4-1.x86_64

We have packages available for autoconf, pcre-devel, openldap-devel, lua-devel, and libxml2-devel. APR is included in RHEL and CentOS, but it’s unfortunately an old version, so we’ll have to recompile that too. distcache is often the problem people are reporting when installing Apache 2.4, but continue reading for a nice trick to make this easier.

Next, we’ll download the sources of all of the custom packages we need to compile for Apache (your versions may change) –

cd ~/rpmbuild/SOURCES
wget http://www.gtlib.gatech.edu/pub/apache/apr/apr-1.4.6.tar.bz2
wget http://www.gtlib.gatech.edu/pub/apache/apr/apr-util-1.5.2.tar.bz2

Each of these can now be easily used to create RPMs for installation. Let’s start with APR –

cd ~/rpmbuild/SOURCES
# Install apr dependencies
yum -y install autoconf libtool doxygen
rpmbuild -tb apr-1.4.6.tar.bz2
# Install our freshly build apr RPMs
rpm -ivh ~/rpmbuild/RPMS/x86_64/apr-1.4.6-1.x86_64.rpm ~/rpmbuild/RPMS/x86_64/apr-devel-1.4.6-1.x86_64.rpm
# Install apr-util dependencies
yum -y install expat-devel libuuid-devel db4-devel postgresql-devel mysql-devel freetds-devel unixODBC-devel openldap-devel nss-devel
# For some reason this has failed for me once or twice, but completed successfully the next time.
rpmbuild -tb apr-util-1.5.2.tar.bz2
rpm -ivh ~/rpmbuild/RPMS/x86_64/apr-util-1.5.2-1.x86_64.rpm ~/rpmbuild/RPMS/x86_64/apr-util-devel-1.5.2-1.x86_64.rpm

Installing distcache on RHEL can be a pain, but we can take advantage of Fedora’s SRPM to get us started –

cd ~/rpmbuild/SRPMS
wget http://www.gtlib.gatech.edu/pub/fedora.redhat/linux/releases/18/Fedora/source/SRPMS/d/distcache-1.4.5-23.src.rpm
rpmbuild --rebuild distcache-1.4.5-23.src.rpm
rpm -ivh ~/rpmbuild/RPMS/x86_64/distcache-1.4.5-23.x86_64.rpm ~/rpmbuild/RPMS/x86_64/distcache-devel-1.4.5-23.x86_64.rpm

Now that we have apr and distcache taken care of, the Apache compilation and install is quite easy –

cd ~/rpmbuild/SOURCES/
# Install remaining httpd dependencies
yum -y install pcre-devel lua-devel libxml2-devel
rpmbuild -tb httpd-2.4.4.tar.bz2

Now you’re ready to install httpd, but you’ll get one last error –

$ rpm -ivh ~/rpmbuild/RPMS/x86_64/httpd-2.4.4-1.x86_64.rpm 
    error: Failed dependencies:
        /etc/mime.types is needed by httpd-2.4.4-1.x86_64

Let’s find out which package provides that file –

$ yum whatprovides "/etc/mime.types"
Loaded plugins: fastestmirror, security
Loading mirror speeds from cached hostfile
 * base: ftp.osuosl.org
 * epel: ftp.osuosl.org
 * extras: ftp.osuosl.org
 * updates: ftp.usf.edu
mailcap-2.1.31-2.el6.noarch : Helper application and MIME type associations for file types
Repo        : base
Matched from:
Filename    : /etc/mime.types

We’re finally ready to install httpd –

yum -y install mailcap
rpm -ivh ~/rpmbuild/RPMS/x86_64/httpd-2.4.4-1.x86_64.rpm

Now you’re all ready to go with Apache 2.4! And since you’ve built proper RPMs, you’re also ready to deploy the packages out to all of your servers.

ProxyPass        /    ws://localhost:8080/
ProxyPassReverse /    ws://localhost:8080/
ProxyPass        /    wss://localhost:8080/
ProxyPassReverse /    wss://localhost:8080/

ProxyPass        /  http://localhost:8080/
ProxyPassReverse /  http://localhost:8080/

 

This works

RewriteEngine on

    RewriteCond %{QUERY_STRING} transport=polling
    RewriteRule /(.*)$ http://localhost:$port/$1 [P]

    ProxyRequests off
    ProxyPass /socket.io-client/ ws://localhost:$port/socket.io-client/
    ProxyPassReverse /socket.io-client/ ws://localhost:$port/socket.io-client/

    ProxyPass / http://localhost:$port/
    ProxyPassReverse / http://localhost:$port/


PHP Code to Open Zip Files and Extract the Contents

computerGirl on sofa

I recently was working on a project for a dynamic website that presented a huge collection of files available for download. All of the files (over 25,000) were stored in the ubiquitous ZIP format.  This is great for reducing the amount of disk space required, however it can make it challenging to work with them.  What we wanted to do was allow the visitors to the site to be able to review the contents of the file, and view any of the files that are contained within the ZIP file.  PHP has some handy functions that allow you to manipulate ZIP files, however they are not well documented.  Although fairly straight-forward, I am including some example code here that will allow you to quickly copy and paste it for your requirements.

The core routines include zip_open() that opens the ZIP file for use.  zip_read then allows you to transverse the ZIP directory to identify the files contained within.   The zip_entry routines provide additional details about the file enclosed, and zip_entry_open() provides the door that allows you to open a specific file and then zip_entry_read allows you to extract the contained file.   On our site, the contained files were mostly text files that could be easily displayed.  Simply iterate through the file collecting the contents into a temporary variable.  If displaying on a webpage, use the handy nl2lbr() function to convert line feeds into HTML line breaks.

All in all, PHP’s built-in ZIP functions are a handy tool, a few simple lines of code will allow you to easily manipulate ZIP files and allow individual files to be viewed.  Leave a comment if you have any questions or suggestions.  You can see the final site at The Programmer’s Corner.

Code that will allow you to open a ZIP file, iterate through the directory, and retrieve the files contained within.

   $zip = zip_open('PCorner/' . $_GET['category'] . '/' . $_GET['file']);
    while ($zip_entry = zip_read($zip)) {
        $output.= '<tr class="' . $class . '">';
        $output.= '<td>';
        $file = strtoupper(basename(zip_entry_name($zip_entry)));
        $size = zip_entry_filesize($zip_entry);
        $csize = zip_entry_compressedsize($zip_entry);
        $type = zip_entry_compressionmethod($zip_entry);
    }

Code that will allow you to open a ZIP file, find a specific file, and extract it for viewing, or further manipulation.

   $zip = zip_open('PCorner/' . $_GET['category'] . '/' . $_GET['file']);
        while ($zip_entry = zip_read($zip)) {
            $file = basename(zip_entry_name($zip_entry));
            if (strtoupper($file) == strtoupper($_GET['operation'])) {
                if (!zip_entry_open($zip, $zip_entry)) {
                    die('');
                }
                while ($data = zip_entry_read($zip_entry)) {
                    $output.= nl2br($data);
                }

            }
        }
   echo $output;