diff --git a/httpbin/core.py b/httpbin/core.py index 18423f5..99a1c64 100644 --- a/httpbin/core.py +++ b/httpbin/core.py @@ -14,7 +14,7 @@ import random import time import uuid -from flask import Flask, Response, request, render_template, redirect, jsonify as flask_jsonify, make_response +from flask import Flask, Response, request, render_template, redirect, jsonify as flask_jsonify, make_response, url_for from werkzeug.datastructures import WWWAuthenticate, MultiDict from werkzeug.http import http_date from werkzeug.wrappers import BaseResponse @@ -188,14 +188,22 @@ def view_deflate_encoded_content(): @app.route('/redirect/') def redirect_n_times(n): - """301 Redirects n times.""" - + """302 Redirects n times.""" assert n > 0 - if (n == 1): - return redirect('/get') + absolute = request.args.get('absolute', 'false').lower() == 'true' - return redirect('/redirect/{0}'.format(n - 1)) + if n == 1: + return redirect(url_for('view_get', _external=absolute)) + + if absolute: + return _redirect('absolute', n, True) + else: + return _redirect('relative', n, False) + + +def _redirect(kind, n, external): + return redirect(url_for('{0}_redirect_n_times'.format(kind), n=n - 1, _external=external)) @app.route('/redirect-to') @@ -216,14 +224,14 @@ def redirect_to(): @app.route('/relative-redirect/') def relative_redirect_n_times(n): - """301 Redirects n times.""" + """302 Redirects n times.""" assert n > 0 response = app.make_response('') response.status_code = 302 - if (n == 1): + if n == 1: response.headers['Location'] = '/get' return response @@ -231,6 +239,18 @@ def relative_redirect_n_times(n): return response +@app.route('/absolute-redirect/') +def absolute_redirect_n_times(n): + """302 Redirects n times.""" + + assert n > 0 + + if n == 1: + return redirect(url_for('view_get', _external=True)) + + return _redirect('absolute', n, True) + + @app.route('/stream/') def stream_n_messages(n): """Stream n JSON messages""" diff --git a/httpbin/templates/httpbin.1.html b/httpbin/templates/httpbin.1.html index 2119255..70fe7d5 100644 --- a/httpbin/templates/httpbin.1.html +++ b/httpbin/templates/httpbin.1.html @@ -23,6 +23,7 @@
  • /redirect/:n 302 Redirects n times.
  • /redirect-to?url=foo 302 Redirects to the foo URL.
  • /relative-redirect/:n 302 Relative redirects n times.
  • +
  • /absolute-redirect/:n 302 Absolute redirects n times.
  • /cookies Returns cookie data.
  • /cookies/set?name=value Sets one or more simple cookies.
  • /cookies/delete?name Deletes one or more simple cookies.
  • diff --git a/test_httpbin.py b/test_httpbin.py index 6f8b9f2..23e4268 100755 --- a/test_httpbin.py +++ b/test_httpbin.py @@ -290,6 +290,50 @@ class HttpbinTestCase(unittest.TestCase): }) assert json.loads(response.data.decode('utf-8'))['url'].startswith('https://') + def test_redirect_n_higher_than_1(self): + response = self.app.get('/redirect/5') + self.assertEqual( + response.headers.get('Location'), '/relative-redirect/4' + ) + + def test_redirect_absolute_param_n_higher_than_1(self): + response = self.app.get('/redirect/5?absolute=true') + self.assertEqual( + response.headers.get('Location'), 'http://localhost/absolute-redirect/4' + ) + + def test_redirect_n_equals_to_1(self): + response = self.app.get('/redirect/1') + self.assertEqual(response.status_code, 302) + self.assertEqual( + response.headers.get('Location'), '/get' + ) + + def test_relative_redirect_n_equals_to_1(self): + response = self.app.get('/relative-redirect/1') + self.assertEqual( + response.headers.get('Location'), '/get' + ) + + def test_relative_redirect_n_higher_than_1(self): + response = self.app.get('/relative-redirect/7') + self.assertEqual(response.status_code, 302) + self.assertEqual( + response.headers.get('Location'), '/relative-redirect/6' + ) + + def test_absolute_redirect_n_higher_than_1(self): + response = self.app.get('/absolute-redirect/5') + self.assertEqual( + response.headers.get('Location'), 'http://localhost/absolute-redirect/4' + ) + + def test_absolute_redirect_n_equals_to_1(self): + response = self.app.get('/absolute-redirect/1') + self.assertEqual(response.status_code, 302) + self.assertEqual( + response.headers.get('Location'), 'http://localhost/get' + ) if __name__ == '__main__': unittest.main()