17

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
13
  • 1
    Have you tried encoding your strings ? Example: status.encode() Commented Jan 17, 2016 at 12:47
  • Under Python 3, a WSGI application must return a byte string as the variable 'output'. It cannot be a Unicode object or some other type. <--- I didn't try, didn't use mod_wsgi with Apache in a while. Commented Jan 17, 2016 at 12:49
  • @Rolbrok: I did actually, forgot to mention. Now I get TypeError: expected unicode object, value of type bytes found. Commented Jan 17, 2016 at 12:49
  • status.encode('utf-8') ? Commented Jan 17, 2016 at 12:50
  • Sounds like you need to change some of them back, yes? See which ones the error is referring to. Experiment. Read the docs if all else fails :) Commented Jan 17, 2016 at 12:50

2 Answers 2

40

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.)

Sign up to request clarification or add additional context in comments.

2 Comments

This one made me grow some gray hairs tonight! I stumbled upon the solution right before coming here at 4:00 AM. Got to be at work in about 3 hours. Just wondering why this is required is there any further reading on this?
Why is that? I makes things unnecessary complicated.
17

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.