How to integrate Python WSGI Application with Apache HTTP Server

How to integrate Python WSGI Application with Apache HTTP Server

python_wsgi

Test Environment

Fedora 31 server with Python 3.7

Here in this article we will see how we can integrate a Django Application with Apache HTTP server using the python wsagi module.

Procedure

Step1: Install Apache2

[root@fedser]# dnf install httpd

Make sure to enable the http service for remote access by enabling in firewall if firewall is enabled.

[root@fedser software]# firewall-cmd --add-service=http --permanent
success
[root@fedser software]# firewall-cmd --reload
success

Access the default homepage http://localhost:80/

Step2: Install Development Tools

[root@fedser]# dnf groupinstall "Development Tools"
[root@fedser]# dnf install httpd-devel

Step3: Download the latest mod_wsgi package

URL – https://github.com/GrahamDumpleton/mod_wsgi/releases

[root@fedser]# wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.6.5.tar.gz
[root@fedser]# tar -xvzf 4.6.5.tar.gz

Step4: Configure the package

[root@fedser mod_wsgi-4.6.5]# ./configure --with-apxs=/usr/bin/apxs --with-python=/usr/bin/python
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for prctl... yes
checking Apache version... 2.4.41
configure: creating ./config.status
config.status: creating Makefile

Step5: Make and Install

[root@fedser mod_wsgi-4.6.5]# make
/usr/bin/apxs -c -I/usr/include/python3.7m -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -D_GNU_SOURCE  -Wc,-g -Wc,-O2  src/server/mod_wsgi.c src/server/wsgi_*.c -L/usr/lib64 -L/usr/lib64/python3.7/config-3.7m  -lpython3.7m -lcrypt -lpthread -ldl  -lutil -lm
/usr/lib64/apr-1/build/libtool --silent --mode=compile gcc -prefer-pic -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection  -DLINUX -D_REENTRANT -D_GNU_SOURCE -pthread -I/usr/include/httpd  -I/usr/include/apr-1   -I/usr/include/apr-1  -g -O2 -I/usr/include/python3.7m -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -D_GNU_SOURCE  -c -o src/server/mod_wsgi.lo src/server/mod_wsgi.c && touch src/server/mod_wsgi.slo
gcc: fatal error: cannot read spec file ‘/usr/lib/rpm/redhat/redhat-hardened-cc1’: No such file or directory
compilation terminated.
apxs:Error: Command failed with rc=65536

make: *** [Makefile:31: src/server/mod_wsgi.la] Error 1

[root@fedser mod_wsgi-4.6.5]# dnf install redhat-rpm-config

[root@fedser mod_wsgi-4.6.5]# make
/usr/bin/apxs -c -I/usr/include/python3.7m -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -D_GNU_SOURCE  -Wc,-g -Wc,-O2  src/server/mod_wsgi.c src/server/wsgi_*.c -L/usr/lib64 -L/usr/lib64/python3.7/config-3.7m  -lpython3.7m -lcrypt -lpthread -ldl  -lutil -lm
/usr/lib64/apr-1/build/libtool --silent --mode=compile gcc -prefer-pic -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection  -DLINUX -D_REENTRANT -D_GNU_SOURCE -pthread -I/usr/include/httpd  -I/usr/include/apr-1   -I/usr/include/apr-1  -g -O2 -I/usr/include/python3.7m -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -D_GNU_SOURCE  -c -o src/server/mod_wsgi.lo src/server/mod_wsgi.c && touch src/server/mod_wsgi.slo
In file included from src/server/mod_wsgi.c:22:
src/server/wsgi_python.h:24:10: fatal error: Python.h: No such file or directory
   24 | #include  
      |          ^~~~~~~~~~
compilation terminated.
apxs:Error: Command failed with rc=65536
make: *** [Makefile:31: src/server/mod_wsgi.la] Error 1

 [root@fedser mod_wsgi-4.6.5]# dnf install python3-devel
[root@fedser mod_wsgi-4.6.5]# make

[root@fedser mod_wsgi-4.6.5]# make install
/usr/bin/apxs -i -S LIBEXECDIR=/usr/lib64/httpd/modules -n 'mod_wsgi' src/server/mod_wsgi.la
/usr/lib64/httpd/build/instdso.sh SH_LIBTOOL='/usr/lib64/apr-1/build/libtool' src/server/mod_wsgi.la /usr/lib64/httpd/modules
/usr/lib64/apr-1/build/libtool --mode=install install src/server/mod_wsgi.la /usr/lib64/httpd/modules/
libtool: install: install src/server/.libs/mod_wsgi.so /usr/lib64/httpd/modules/mod_wsgi.so
libtool: install: install src/server/.libs/mod_wsgi.lai /usr/lib64/httpd/modules/mod_wsgi.la
libtool: install: install src/server/.libs/mod_wsgi.a /usr/lib64/httpd/modules/mod_wsgi.a
libtool: install: chmod 644 /usr/lib64/httpd/modules/mod_wsgi.a
libtool: install: ranlib /usr/lib64/httpd/modules/mod_wsgi.a
libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/sbin" ldconfig -n /usr/lib64/httpd/modules
----------------------------------------------------------------------
Libraries have been installed in:
   /usr/lib64/httpd/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the 'LD_RUN_PATH' environment variable
     during linking
   - use the '-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to '/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
chmod 755 /usr/lib64/httpd/modules/mod_wsgi.so

[root@fedser modules]# pwd
/etc/httpd/modules
[root@fedser modules]# ls -ltr mod_wsgi.so
-rwxr-xr-x 1 root root 1257448 Dec 31 23:10 mod_wsgi.so

Step6: Load the mod_wsgi module into Apache http server

[root@fedser conf]# grep wsgi httpd.conf
LoadModule wsgi_module modules/mod_wsgi.so

Step7: Restart the httpd service

[root@fedser conf]# systemctl restart httpd.service

Step8: Validate the logs for module loaded or not

[root@fedser logs]# grep wsgi error_log
[Sun Jan 12 09:26:26.987683 2020] [mpm_event:notice] [pid 11674:tid 140541302194496] AH00489: Apache/2.4.41 (Fedora) mod_wsgi/4.6.5 Python/3.7 configured -- resuming normal operations

Step9: Configure a simple hello world wsgi application

[root@fedser python]# pwd
/usr/local/www/wsgi-scripts
[root@fedser python]# cat myapp.wsgi
def application(environ, start_response):
    status = '200 OK'
    output = b'Hello World from WSGI App!'

    response_headers = [('Content-type', 'text/plain'),
                        ('Content-Length', str(len(output)))]
    start_response(status, response_headers)

    return [output]

Mount the wsgi application

[root@fedser conf]# grep -C 5 wsgi /etc/httpd/conf/httpd.conf
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
LoadModule wsgi_module modules/mod_wsgi.so
Include conf.modules.d/*.conf

#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
--
    #
    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"




    WSGIScriptAlias /myapp /usr/local/www/wsgi-scripts/myapp.wsgi

Allow the the below directory access

<directory "="" usr="" local="" www"="">
    AllowOverride None
    # Allow open access:
    Require all granted

Once the above configuration changes are completed restart your httpd service to make the changes effective.

Step10: Validate the application

URL – http://localhost/myapp

Output – Hello World from WSGI App!

Hope you enjoyed reading this article. Thank you..