11

I have an application with Python Bottle and I want to add Cache-Control in static files. I am new on this so forgive me if I have done something wrong.

Here is the function and how I serve static files:

@bottle.get('/static/js/<filename:re:.*\.js>')
def javascripts(filename):
   return bottle.static_file(filename, root='./static/js/')

To add Cache-Control I have included one more line (I saw it in a tutorial)

@bottle.get('/static/js/<filename:re:.*\.js>')
def javascripts(filename):
   bottle.response.headers['Cache-Control'] = 'public, max-age=604800'
   return bottle.static_file(filename, root='./static/js/')

But when I check the headers from Developer tools on Chrome: I have either Cache-Control:max-age=0 or Cache-Control:no-cache

Sfinos
  • 279
  • 4
  • 15
  • Try using `response.set_header()` instead of `response.headers` as they say in the [docs](http://bottlepy.org/docs/dev/tutorial.html?highlight=cache-control). Something like this `response.set_header('Cache-Control', 'max-age=3600,public')` – doru Jul 10 '14 at 12:05
  • @doru I've already tried it but in network tab in Chrome Developer Tools I have the same thing (Cache-Control:max-age=0). And every static file seems to load in every refresh – Sfinos Jul 10 '14 at 12:21
  • Please try with `wget` or `curl` instead of Chrome, and let us know what you see. – ron rothman Jul 10 '14 at 23:31
  • @ron.rothman I don't have wget neither curl on winders. I made a Headers request through Python and urllib2 and here is the result: `{'date': 'Fri, 11 Jul 2014 22:39:58 GMT', 'content-length': '30458', 'content-type': 'text/html; charset=UTF-8', 'server': 'WSGIServer/0.1 Python/2.7.6'}` – Sfinos Jul 11 '14 at 22:43
  • Did you notice that there's no `Cache-control` header in your response? – ron rothman Jul 12 '14 at 00:33
  • P.S., http://curl.haxx.se/download.html – ron rothman Jul 12 '14 at 00:34
  • @ron.rothman I saw it. Same thing in Chrome. Sometimes there isn't anything there too. – Sfinos Jul 12 '14 at 08:03

1 Answers1

22

I had a look at the source code for static_file() and found the solution.

You need to assign the result of static_file(...) to a variable and call set_header() on the resulting HTTPResponse object.

#!/usr/bin/env python

import bottle


@bottle.get("/static/js/<filename:re:.*\.js>")
def javascripts(filename):
    response = bottle.static_file(filename, root="./static/js/")
    response.set_header("Cache-Control", "public, max-age=604800")
    return response

bottle.run(host="localhost", port=8000, debug=True)

Basically static_file(...) creates a brand new HTTPResponse object and your modification to bottle.response has no effect here.

This does preicesly what you're after:

$ curl -v -o - http://localhost:8000/static/js/test.js
* Adding handle: conn: 0x7f8ffa003a00
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f8ffa003a00) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 8000 (#0)
*   Trying ::1...
*   Trying fe80::1...
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /static/js/test.js HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8000
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Date: Tue, 15 Jul 2014 00:19:11 GMT
< Server: WSGIServer/0.1 Python/2.7.6
< Last-Modified: Tue, 15 Jul 2014 00:07:22 GMT
< Content-Length: 69
< Content-Type: application/javascript
< Accept-Ranges: bytes
< Cache-Control: public, max-age=604800
<
$(document).ready(function () {
    console.log("Hello World!");
});
* Closing connection 0
James Mills
  • 18,669
  • 3
  • 49
  • 62
  • 4
    For those wondering, 604800 is the number of seconds in a week. `604800 / 60 / 60 / 24 = 7`. Curiosity is weird, sometimes. – tleb Aug 10 '16 at 23:45