nginx with flask and memcached returns some garbled characters

Go To


I'm trying to cache Python/flask responses with memcached. I then want to serve the cache using nginx. I'm using flask code that looks something like this:

from flask import Flask, render_template
from werkzeug.contrib.cache import MemcachedCache

app = Flask(__name__)

cache = MemcachedCache([''])

def index():
    index = cache.get('request:/')
    if index == None:
        index = render_template('index.html')
        cache.set('request:/', index, timeout=5 * 60)
    return index

if __name__ == "__main__":

and an nginx site configuration that looks something like this:

server {
    listen 80;

    location / {
        set $memcached_key "request:$request_uri";

        error_page 404 405 502 = @cache_miss;

    location @cache_miss {
        uwsgi_pass   unix:///tmp/uwsgi.sock;
        include      uwsgi_params;

        error_page  404  /404.html;

However, when it pulls from the cache the html code is prefixed with a V, contains \u000a characters (line feeds) and garbled local characters, and is suffixed with "p1 ." as such:

V<!doctype html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">\u000a<head>\u000a  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />\u000a  <meta http-equiv="content-language" content="no">\u000a\u000a  <title>



Despite Content-Type being "text/html; charset=utf-8". Supposedly the V [...] p1 . thing might have something do with chunked transfer encoding something, a flag that is not present in the response header. What should I do?

2012-04-04 17:44
by jondoe
Okay, so I semi-fixed it. It, I added add_header Transfer-Encoding chunked; in the nginx configuration, but now I get Error 321 (net::ERR_INVALID_CHUNKED_ENCODING) if I load it in Chrome after having loaded it in Firefox. Is there a better way to do this type of cachine, perhaps - jondoe 2012-04-04 18:51


Yay, I fixed it! The nginx configuration was correct before I changed chunked, the python/flask code however should have been:

def index():
    rv = cache.get('request:/')
    if rv == None:
        rv = render_template('index.html')
        cachable = make_response(rv).data
        cache.set('request:/', cachable, timeout=5 * 60)
    return rv

That is, I should only cache the data, and that can only be done, afaik, if I do make_response first

2012-04-07 13:59
by jondoe