From 43fbea50f20c5007161f672ab716f8f02663a226 Mon Sep 17 00:00:00 2001 From: Nick Presta Date: Sun, 18 Jan 2015 18:46:31 -0500 Subject: [PATCH] Add example and documentation for request-hash. --- README.md | 12 ++++++++++++ example/app.py | 17 +++++++++++++++++ example/testing_data/foo_bar_hash | 20 ++++++++++++++++++++ example/testing_data/spec.json | 15 +++++++++++++++ example/tests.py | 11 +++++++++++ handlers.go | 1 - 6 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 example/testing_data/foo_bar_hash diff --git a/README.md b/README.md index 5a68718..6cd47a8 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,18 @@ The directory `httpbin` must already exist before running. See `chameleon -help` for more information. +### Specifying custom hash + +There may be a reason in your tests to manually create responses - perhaps the backing service doesn't exist yet, or in test mode a service behaves differently than production. When this is the case, you can create custom responses and signal to chameleon the hash you want to use for a given request. + +Set the `chameleon-request-hash` header with a unique hash value (which is a valid filename) and chameleon will look for that hash in the `spec.json` file and for all subsequent requests. + +This allows you to not only have total control over the response for a given request but also makes your test code easier to reason about -- it is clear where the "special case" response is coming from. + +### Getting the hash for a given request + +All responses from chameleon will have a `chameleon-request-hash` header set which is the hash used for that request. This header is present even if you did not set it on the incoming request. + ### Preseeding the cache If you want to configure the cache at runtime without having to depend on an external service, you may preseed the cache diff --git a/example/app.py b/example/app.py index e48c7ec..9a27cb8 100644 --- a/example/app.py +++ b/example/app.py @@ -86,6 +86,23 @@ def do_SEEDED(self): self.end_headers() self.wfile.write(resp.read()) + def do_REQUESTHASH(self): + content_len = int(self.headers.getheader('content-length', 0)) + body = self.rfile.read(content_len) + + req = urllib2.Request(POST_SERVICE_URL, body, self.headers) + req.get_method = lambda: 'POST' + try: + resp = urllib2.urlopen(req) + except urllib2.HTTPError as exc: + resp = exc + + self.send_response(200) + for k, v in resp.headers.dict.viewitems(): + self.send_header(k, v) + self.end_headers() + self.wfile.write(resp.read()) + def main(): print('Serving on port {}'.format(TEST_APP_PORT)) diff --git a/example/testing_data/foo_bar_hash b/example/testing_data/foo_bar_hash new file mode 100644 index 0000000..80a24d9 --- /dev/null +++ b/example/testing_data/foo_bar_hash @@ -0,0 +1,20 @@ +{ + "args": {}, + "data": "{\"foo\": \"bar\"}", + "files": {}, + "form": {}, + "headers": { + "Accept-Encoding": "identity", + "Chameleon-Request-Hash": "foo_bar_hash", + "Content-Length": "14", + "Content-Type": "application/json", + "Host": "httpbin.org", + "User-Agent": "Python-urllib/2.7", + "X-Forwarded-Ssl": "on" + }, + "json": { + "foo": "bar" + }, + "origin": "99.245.54.15", + "url": "http://httpbin.org/post" +} diff --git a/example/testing_data/spec.json b/example/testing_data/spec.json index 927611d..6b5f45f 100644 --- a/example/testing_data/spec.json +++ b/example/testing_data/spec.json @@ -110,5 +110,20 @@ } }, "key": "9835adf25e3ecc09431cdf3079bb822a" + }, + { + "response": { + "status_code": 200, + "content": "foo_bar_hash", + "headers": { + "Access-Control-Allow-Credentials": "true", + "Access-Control-Allow-Origin": "*", + "Content-Length": "452", + "Content-Type": "application/json", + "Date": "Sun, 18 Jan 2015 23:30:57 GMT", + "Server": "nginx" + } + }, + "key": "foo_bar_hash" } ] \ No newline at end of file diff --git a/example/tests.py b/example/tests.py index 126a08d..d919f75 100644 --- a/example/tests.py +++ b/example/tests.py @@ -109,6 +109,17 @@ def test_preseed(self): self.assertEqual(942, resp.getcode()) self.assertEqual({'key': 'value'}, json.loads(resp.read())) + def test_specify_hash_in_request(self): + url = 'http://localhost:{}/post'.format(TEST_APP_PORT) + req = urllib2.Request(url, json.dumps({'foo': 'bar'}), { + 'Content-type': 'application/json', 'chameleon-request-hash': 'foo_bar_hash'}) + req.get_method = lambda: 'REQUESTHASH' + resp = urllib2.urlopen(req) + content = resp.read() + parsed = json.loads(content) + self.assertEqual({'foo': 'bar'}, parsed['json']) + self.assertEqual('foo_bar_hash', resp.headers['chameleon-request-hash']) + if __name__ == '__main__': unittest.main() diff --git a/handlers.go b/handlers.go index 96c45ef..9f2fec3 100644 --- a/handlers.go +++ b/handlers.go @@ -91,7 +91,6 @@ func CachedProxyHandler(serverURL *url.URL, cacher Cacher, hasher Hasher) http.H hash := r.Header.Get("chameleon-request-hash") if hash == "" { - log.Printf("-> Hashing Request %v", r.URL) hash = hasher.Hash(r) } response := cacher.Get(hash)