From 414a719b42a91306c28d72e6cb9d3ee8affe14b2 Mon Sep 17 00:00:00 2001 From: Dave Challis Date: Wed, 5 Jun 2013 17:10:56 +0100 Subject: [PATCH] Added endpoints '/bytes/:n', '/stream-bytes/:n' and '/links/:n'. '/bytes/:n' takes and optional 'seed' integer parameter, and returns n random bytes of binary data (limited to 100KB in size). '/stream-bytes/:n' is the same as above, but streams the data. As well as a 'seed' parameter, it accepts a 'chunk_size' parameter, which determines how many bytes are in each packet that is streamed. '/links/:n' generates a page containing n links, each of which links to another page containing those n links. The value of n is limited to 200. --- AUTHORS | 1 + README.md | 3 +++ httpbin/core.py | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/AUTHORS b/AUTHORS index c3a4fcf..a4561f8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -20,3 +20,4 @@ Patches and Suggestions - Bob Carroll @rcarz - Cory Benfield (Lukasa) - Matt Robenolt (https://github.com/mattrobenolt) +- Dave Challis (https://github.com/davechallis) diff --git a/README.md b/README.md index 00fff52..9686483 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,9 @@ Freely hosted in [HTTP](http://httpbin.org) & - [`/robots.txt`](http://httpbin.org/robots.txt) Returns some robots.txt rules. - [`/deny`](http://httpbin.org/deny) Denied by robots.txt file. - [`/cache`](http://httpbin.org/cache) Returns 200 unless an If-Modified-Since or If-None-Match header is provided, when it returns a 304. +- [`/bytes/:n`](http://httpbin.org/bytes/1024) Generates *n* random bytes of binary data, accepts optional *seed* integer parameter. +- [`/stream-bytes/:n`](http://httpbin.org/stream-bytes/1024) Streams *n* random bytes of binary data, accepts optional *seed* and *chunk_size* integer parameters. +- [`/links/:n`](http://httpbin.org/links/10) Returns page containing *n* HTML links. ## DESCRIPTION diff --git a/httpbin/core.py b/httpbin/core.py index 0a3cb71..65cf0ea 100644 --- a/httpbin/core.py +++ b/httpbin/core.py @@ -12,6 +12,7 @@ import json import os import time import uuid +import random from flask import Flask, Response, request, render_template, redirect, jsonify, make_response from raven.contrib.flask import Sentry @@ -366,5 +367,76 @@ def cache(): return status_code(304) +@app.route('/bytes/') +def random_bytes(n): + """Returns n random bytes generated with given seed.""" + n = min(n, 100 * 1024) # set 100KB limit + + params = CaseInsensitiveDict(request.args.items()) + if 'seed' in params: + random.seed(int(params['seed'])) + + response = make_response() + response.data = bytes().join(chr(random.randint(0, 255)) for i in xrange(n)) + response.content_type = 'application/octet-stream' + return response + + +@app.route('/stream-bytes/') +def stream_random_bytes(n): + """Streams n random bytes generated with given seed, at given chunk size per packet.""" + n = min(n, 100 * 1024) # set 100KB limit + + params = CaseInsensitiveDict(request.args.items()) + if 'seed' in params: + random.seed(int(params['seed'])) + + if 'chunk_size' in params: + chunk_size = max(1, int(params['chunk_size'])) + else: + chunk_size = 10 * 1024 + + def generate_bytes(): + chunks = [] + + for i in xrange(n): + chunks.append(chr(random.randint(0, 255))) + if len(chunks) == chunk_size: + yield(bytes().join(chunks)) + chunks = [] + + if chunks: + yield(bytes().join(chunks)) + + headers = {'Transfer-Encoding': 'chunked', + 'Content-Type': 'application/octet-stream'} + + return Response(generate_bytes(), headers=headers) + + +@app.route('/links//') +def link_page(n, offset): + """Generate a page containing n links to other pages which do the same.""" + n = min(max(1, n), 200) # limit to between 1 and 200 links + + link = "{2} " + + html = ['Links'] + for i in xrange(n): + if i == offset: + html.append("{0} ".format(i)) + else: + html.append(link.format(n, i, i)) + html.append('') + + return ''.join(html) + + +@app.route('/links/') +def links(n): + """Redirect to first links page.""" + return redirect("/links/{0}/0".format(n)) + + if __name__ == '__main__': app.run()