diff --git a/httpbin/core.py b/httpbin/core.py index 166065f..8fd904f 100644 --- a/httpbin/core.py +++ b/httpbin/core.py @@ -17,7 +17,7 @@ from werkzeug.datastructures import WWWAuthenticate from . import filters from .helpers import get_headers, status_code, get_dict, check_basic_auth, check_digest_auth, H - +from .utils import weighted_choice ENV_COOKIES = ( '_gauges_unique', @@ -80,7 +80,6 @@ def view_get(): @app.route('/post', methods=('POST',)) - def view_post(): """Returns POST Data.""" @@ -173,6 +172,25 @@ def view_status_code(code): return status_code(code) +@app.route('/random-status/') +def view_random_status_code(codes): + """Return random status code from given status codes.""" + + choices = [] + for choice in codes.split(','): + if not ':' in choice: + code = choice + weight = 1 + else: + code, weight = choice.split(':') + + choices.append((int(code), float(weight))) + + code = weighted_choice(choices) + + return status_code(code) + + @app.route('/cookies') def view_cookies(hide_env=True): """Returns cookie data.""" diff --git a/httpbin/utils.py b/httpbin/utils.py new file mode 100644 index 0000000..35161a6 --- /dev/null +++ b/httpbin/utils.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +""" +httpbin.utils +~~~~~~~~~~~~~~~ + +Utility functions. +""" + +import random +import bisect + +def weighted_choice(choices): + """Returns a value from choices chosen by weighted random selection + + choices should be a list of (value, weight) tuples. + + eg. weighted_choice([('val1', 5), ('val2', 0.3), ('val3', 1)]) + + """ + values, weights = zip(*choices) + total = 0 + cum_weights = [] + for w in weights: + total += w + cum_weights.append(total) + x = random.uniform(0, total) + i = bisect.bisect(cum_weights, x) + return values[i] \ No newline at end of file