I'm trying to run a simple "hello world" application using mod_wsgi
for Python 3. I'm using Fedora 23. Here's my Apache virtual host configuration:
<VirtualHost *:80>
ServerName localhost
ServerAdmin admin@localhost
# ServerAlias foo.localhost
WSGIScriptAlias /headers /home/httpd/localhost/python/headers/wsgi.py
DocumentRoot /home/httpd/localhost/public_html
ErrorLog /home/httpd/localhost/error.log
CustomLog /home/httpd/localhost/requests.log combined
</VirtualHost>
wsgi.py:
def application(environ, start_response):
status = '200 OK'
output = 'Hello World!'
response_headers = [('Content-Type', 'text/plain'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
It works fine if I use mod_wsgi
for Python 2 (sudo dnf remove python3-mod_wsgi -y && sudo dnf install mod_wsgi -y && sudo apachectl restart
), but I get a 500 internal server error when using Python 3. Here's the error log:
mod_wsgi (pid=899): Exception occurred processing WSGI script '/home/httpd/localhost/python/headers/wsgi.py'.
TypeError: sequence of byte string values expected, value of type str found
Update
Using encode()
(or encode('utf-8')
) on str(len(output))
isn't working either. Now I get:
Traceback (most recent call last):
File "/home/httpd/localhost/python/headers/wsgi.py", line 8, in application
start_response(status, response_headers)
TypeError: expected unicode object, value of type bytes found
Apparently the variable output
itself needs to have a bytes string rather than a unicode string. And it needs to change not only for response_headers
, but for everywhere output
is used (so str(len(output)).encode('utf-8')
on line 6 wouldn't work, like I'd been trying).
So the solution in my case is:
def application(environ, start_response):
status = '200 OK'
output = b'Hello World!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
(which I found in one of the tests on the official mod_wsgi repo, as suggested by Rolbrok in comments.)
Background
The issue is caused because Python 3 defaulted UTF-8, because today, we find that there is a lot of non native English characters, and it is best to accommodate them. HTTP works only with ASCII characters. It does not handle UTF-8 well. Hence, neither Apache,nor mod_wsgi works well with UTF 8.
Solution
So, after you prepare the entire html string, you can typecast it using the inbuilt python function - bytes(). This takes a string and gives a byte string.
Sample Code
html = "This "
html += "is the code"
html = bytes(html, encoding= 'utf-8')
response_header = [('Content-type', 'text/html')]
start_response(status, response_header)
yield html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With