README.md
1# cachecontrol: HTTP Caching Parser and Interpretation
2
3[![GoDoc](https://godoc.org/github.com/pquerna/cachecontrol?status.svg)](https://godoc.org/github.com/pquerna/cachecontrol)[![Build Status](https://travis-ci.org/pquerna/cachecontrol.svg?branch=master)](https://travis-ci.org/pquerna/cachecontrol)
4
5
6
7`cachecontrol` implements [RFC 7234](http://tools.ietf.org/html/rfc7234) __Hypertext Transfer Protocol (HTTP/1.1): Caching__. It does this by parsing the `Cache-Control` and other headers, providing information about requests and responses -- but `cachecontrol` does not implement an actual cache backend, just the control plane to make decisions about if a particular response is cachable.
8
9# Usage
10
11`cachecontrol.CachableResponse` returns an array of [reasons](https://godoc.org/github.com/pquerna/cachecontrol/cacheobject#Reason) why a response should not be cached and when it expires. In the case that `len(reasons) == 0`, the response is cachable according to the RFC. However, some people want non-compliant caches for various business use cases, so each reason is specifically named, so if your cache wants to cache `POST` requests, it can easily do that, but still be RFC compliant in other situations.
12
13# Examples
14
15## Can you cache Example.com?
16
17```go
18package main
19
20import (
21 "github.com/pquerna/cachecontrol"
22
23 "fmt"
24 "io/ioutil"
25 "net/http"
26)
27
28func main() {
29 req, _ := http.NewRequest("GET", "http://www.example.com/", nil)
30
31 res, _ := http.DefaultClient.Do(req)
32 _, _ = ioutil.ReadAll(res.Body)
33
34 reasons, expires, _ := cachecontrol.CachableResponse(req, res, cachecontrol.Options{})
35
36 fmt.Println("Reasons to not cache: ", reasons)
37 fmt.Println("Expiration: ", expires.String())
38}
39```
40
41## Can I use this in a high performance caching server?
42
43`cachecontrol` is divided into two packages: `cachecontrol` with a high level API, and a lower level `cacheobject` package. Use [Object](https://godoc.org/github.com/pquerna/cachecontrol/cacheobject#Object) in a high performance use case where you have previously parsed headers containing dates or would like to avoid memory allocations.
44
45```go
46package main
47
48import (
49 "github.com/pquerna/cachecontrol/cacheobject"
50
51 "fmt"
52 "io/ioutil"
53 "net/http"
54)
55
56func main() {
57 req, _ := http.NewRequest("GET", "http://www.example.com/", nil)
58
59 res, _ := http.DefaultClient.Do(req)
60 _, _ = ioutil.ReadAll(res.Body)
61
62 reqDir, _ := cacheobject.ParseRequestCacheControl(req.Header.Get("Cache-Control"))
63
64 resDir, _ := cacheobject.ParseResponseCacheControl(res.Header.Get("Cache-Control"))
65 expiresHeader, _ := http.ParseTime(res.Header.Get("Expires"))
66 dateHeader, _ := http.ParseTime(res.Header.Get("Date"))
67 lastModifiedHeader, _ := http.ParseTime(res.Header.Get("Last-Modified"))
68
69 obj := cacheobject.Object{
70 RespDirectives: resDir,
71 RespHeaders: res.Header,
72 RespStatusCode: res.StatusCode,
73 RespExpiresHeader: expiresHeader,
74 RespDateHeader: dateHeader,
75 RespLastModifiedHeader: lastModifiedHeader,
76
77 ReqDirectives: reqDir,
78 ReqHeaders: req.Header,
79 ReqMethod: req.Method,
80
81 NowUTC: time.Now().UTC(),
82 }
83 rv := cacheobject.ObjectResults{}
84
85 cacheobject.CachableObject(&obj, &rv)
86 cacheobject.ExpirationObject(&obj, &rv)
87
88 fmt.Println("Errors: ", rv.OutErr)
89 fmt.Println("Reasons to not cache: ", rv.OutReasons)
90 fmt.Println("Warning headers to add: ", rv.OutWarnings)
91 fmt.Println("Expiration: ", rv.OutExpirationTime.String())
92}
93```
94
95## Improvements, bugs, adding features, and taking cachecontrol new directions!
96
97Please [open issues in Github](https://github.com/pquerna/cachecontrol/issues) for ideas, bugs, and general thoughts. Pull requests are of course preferred :)
98
99# Credits
100
101`cachecontrol` has recieved significant contributions from:
102
103* [Paul Querna](https://github.com/pquerna)
104
105## License
106
107`cachecontrol` is licensed under the [Apache License, Version 2.0](./LICENSE)
108