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(['127.0.0.1:11211'])
@app.route('/')
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__":
app.run()
and an nginx site configuration that looks something like this:
server {
listen 80;
location / {
set $memcached_key "request:$request_uri";
memcached_pass 127.0.0.1:11211;
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" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\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>
[...]
\u000a\u000a</body>\u000a</html>
p1
.
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?
Flask will run at a port other than http port 80 since NGINX will be running on it. We will configure NGINX with Flask such that all requests sent to NGINX are forwarded to Gunicorn (Flask).
Flask is just a web framework and not a web server. Thus to serve a flask application, a web server such as Gunicorn, Nginx or Apache is required to accept HTTP requests.
Yay, I fixed it! The nginx configuration was correct before I changed chunked, the python/flask code however should have been:
@app.route('/')
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
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