mirror of
https://github.com/kennethreitz/httpbin.git
synced 2026-06-05 06:46:16 +00:00
Merge branch 'master' into setuptools-long-description
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
Dockerfile
|
||||||
@@ -7,3 +7,4 @@ dist/
|
|||||||
.tox
|
.tox
|
||||||
*.egg-info
|
*.egg-info
|
||||||
*.swp
|
*.swp
|
||||||
|
.vscode/
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
FROM ubuntu:18.04
|
FROM ubuntu:18.04
|
||||||
|
|
||||||
|
LABEL name="httpbin"
|
||||||
|
LABEL version="0.9.0"
|
||||||
|
LABEL description="A simple HTTP service."
|
||||||
|
LABEL org.kennethreitz.vendor="Kenneth Reitz"
|
||||||
|
|
||||||
RUN apt update -y && apt install python3-pip -y
|
RUN apt update -y && apt install python3-pip -y
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
include README.rst LICENSE AUTHORS requirements.txt test_httpbin.py
|
include httpbin/VERSION README.md LICENSE AUTHORS test_httpbin.py
|
||||||
recursive-include httpbin/templates *
|
recursive-include httpbin/templates *
|
||||||
recursive-include httpbin/static *
|
recursive-include httpbin/static *
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
0.9.0
|
||||||
+84
-14
@@ -30,6 +30,9 @@ from .helpers import get_headers, status_code, get_dict, get_request_range, chec
|
|||||||
from .utils import weighted_choice
|
from .utils import weighted_choice
|
||||||
from .structures import CaseInsensitiveDict
|
from .structures import CaseInsensitiveDict
|
||||||
|
|
||||||
|
with open(os.path.join(os.path.realpath(os.path.dirname(__file__)), 'VERSION')) as version_file:
|
||||||
|
version = version_file.read().strip()
|
||||||
|
|
||||||
ENV_COOKIES = (
|
ENV_COOKIES = (
|
||||||
'_gauges_unique',
|
'_gauges_unique',
|
||||||
'_gauges_unique_year',
|
'_gauges_unique_year',
|
||||||
@@ -55,6 +58,7 @@ tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
|
|||||||
|
|
||||||
app = Flask(__name__, template_folder=tmpl_dir)
|
app = Flask(__name__, template_folder=tmpl_dir)
|
||||||
app.debug = bool(os.environ.get('DEBUG'))
|
app.debug = bool(os.environ.get('DEBUG'))
|
||||||
|
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
|
||||||
|
|
||||||
app.add_template_global('HTTPBIN_TRACKING' in os.environ, name='tracking_enabled')
|
app.add_template_global('HTTPBIN_TRACKING' in os.environ, name='tracking_enabled')
|
||||||
|
|
||||||
@@ -78,13 +82,12 @@ template = {
|
|||||||
"url": "https://kennethreitz.org",
|
"url": "https://kennethreitz.org",
|
||||||
},
|
},
|
||||||
# "termsOfService": "http://me.com/terms",
|
# "termsOfService": "http://me.com/terms",
|
||||||
"version": "0.9.0"
|
"version": version
|
||||||
},
|
},
|
||||||
"host": "httpbin.org", # overrides localhost:5000
|
"host": "httpbin.org", # overrides localhost:5000
|
||||||
"basePath": "/", # base bash for blueprint registration
|
"basePath": "/", # base bash for blueprint registration
|
||||||
"schemes": [
|
"schemes": [
|
||||||
"https",
|
"https"
|
||||||
"http"
|
|
||||||
],
|
],
|
||||||
'protocol': 'https',
|
'protocol': 'https',
|
||||||
'tags': [
|
'tags': [
|
||||||
@@ -510,17 +513,58 @@ def redirect_to():
|
|||||||
- Redirects
|
- Redirects
|
||||||
produces:
|
produces:
|
||||||
- text/html
|
- text/html
|
||||||
parameters:
|
get:
|
||||||
- name: url
|
parameters:
|
||||||
type: string
|
- in: query
|
||||||
- name: status_code
|
name: url
|
||||||
type: int
|
type: string
|
||||||
|
required: true
|
||||||
|
- in: query
|
||||||
|
name: status_code
|
||||||
|
type: int
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/x-www-form-urlencoded
|
||||||
|
parameters:
|
||||||
|
- in: formData
|
||||||
|
name: url
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
- in: formData
|
||||||
|
name: status_code
|
||||||
|
type: int
|
||||||
|
required: false
|
||||||
|
patch:
|
||||||
|
consumes:
|
||||||
|
- application/x-www-form-urlencoded
|
||||||
|
parameters:
|
||||||
|
- in: formData
|
||||||
|
name: url
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
- in: formData
|
||||||
|
name: status_code
|
||||||
|
type: int
|
||||||
|
required: false
|
||||||
|
put:
|
||||||
|
consumes:
|
||||||
|
- application/x-www-form-urlencoded
|
||||||
|
parameters:
|
||||||
|
- in: formData
|
||||||
|
name: url
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
- in: formData
|
||||||
|
name: status_code
|
||||||
|
type: int
|
||||||
|
required: false
|
||||||
responses:
|
responses:
|
||||||
302:
|
302:
|
||||||
description: A redirection.
|
description: A redirection.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
args = CaseInsensitiveDict(request.args.items())
|
argsDict = request.form.to_dict(flat=True) if request.method in ('POST', 'PATCH', 'PUT') else request.args.items()
|
||||||
|
args = CaseInsensitiveDict(argsDict)
|
||||||
|
|
||||||
# We need to build the response manually and convert to UTF-8 to prevent
|
# We need to build the response manually and convert to UTF-8 to prevent
|
||||||
# werkzeug from "fixing" the URL. This endpoint should set the Location
|
# werkzeug from "fixing" the URL. This endpoint should set the Location
|
||||||
@@ -907,13 +951,14 @@ def bearer_auth():
|
|||||||
401:
|
401:
|
||||||
description: Unsuccessful authentication.
|
description: Unsuccessful authentication.
|
||||||
"""
|
"""
|
||||||
if 'Authorization' not in request.headers:
|
authorization = request.headers.get('Authorization')
|
||||||
|
if not (authorization and authorization.startswith('Bearer ')):
|
||||||
response = app.make_response('')
|
response = app.make_response('')
|
||||||
response.headers['WWW-Authenticate'] = 'Bearer'
|
response.headers['WWW-Authenticate'] = 'Bearer'
|
||||||
response.status_code = 401
|
response.status_code = 401
|
||||||
return response
|
return response
|
||||||
authorization = request.headers.get('Authorization')
|
slice_start = len('Bearer ')
|
||||||
token = authorization.lstrip('Bearer ')
|
token = authorization[slice_start:]
|
||||||
|
|
||||||
return jsonify(authenticated=True, token=token)
|
return jsonify(authenticated=True, token=token)
|
||||||
|
|
||||||
@@ -1072,7 +1117,7 @@ def digest_auth(qop=None, user='user', passwd='passwd', algorithm='MD5', stale_a
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@app.route('/delay/<delay>')
|
@app.route('/delay/<delay>', methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'TRACE'])
|
||||||
def delay_response(delay):
|
def delay_response(delay):
|
||||||
""""Returns a delayed response (max of 10 seconds).
|
""""Returns a delayed response (max of 10 seconds).
|
||||||
---
|
---
|
||||||
@@ -1102,6 +1147,31 @@ def drip():
|
|||||||
---
|
---
|
||||||
tags:
|
tags:
|
||||||
- Dynamic data
|
- Dynamic data
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: duration
|
||||||
|
type: number
|
||||||
|
description: The amount of time (in seconds) over which to drip each byte
|
||||||
|
default: 2
|
||||||
|
required: false
|
||||||
|
- in: query
|
||||||
|
name: numbytes
|
||||||
|
type: integer
|
||||||
|
description: The number of bytes to respond with
|
||||||
|
default: 10
|
||||||
|
required: false
|
||||||
|
- in: query
|
||||||
|
name: code
|
||||||
|
type: integer
|
||||||
|
description: The response code that will be returned
|
||||||
|
default: 200
|
||||||
|
required: false
|
||||||
|
- in: query
|
||||||
|
name: delay
|
||||||
|
type: number
|
||||||
|
description: The amount of time (in seconds) to delay before responding
|
||||||
|
default: 2
|
||||||
|
required: false
|
||||||
produces:
|
produces:
|
||||||
- application/octet-stream
|
- application/octet-stream
|
||||||
responses:
|
responses:
|
||||||
@@ -1124,7 +1194,7 @@ def drip():
|
|||||||
pause = duration / numbytes
|
pause = duration / numbytes
|
||||||
def generate_bytes():
|
def generate_bytes():
|
||||||
for i in xrange(numbytes):
|
for i in xrange(numbytes):
|
||||||
yield u"*".encode('utf-8')
|
yield b"*"
|
||||||
time.sleep(pause)
|
time.sleep(pause)
|
||||||
|
|
||||||
response = Response(generate_bytes(), headers={
|
response = Response(generate_bytes(), headers={
|
||||||
|
|||||||
+232
-51
@@ -1,70 +1,251 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv='content-type' value='text/html;charset=utf8'>
|
<meta http-equiv='content-type' value='text/html;charset=utf8'>
|
||||||
<meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>
|
<meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>
|
||||||
<title>httpbin(1): HTTP Client Testing Service</title>
|
<title>httpbin(1): HTTP Client Testing Service</title>
|
||||||
<style type='text/css' media='all'>
|
<style type='text/css' media='all'>
|
||||||
/* style: man */
|
/* style: man */
|
||||||
body#manpage {margin:0}
|
|
||||||
.mp {max-width:100ex;padding:0 9ex 1ex 4ex}
|
body#manpage {
|
||||||
.mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
|
margin: 0;
|
||||||
.mp h2 {margin:10px 0 0 0}
|
}
|
||||||
.mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
|
|
||||||
.mp h3 {margin:0 0 0 4ex}
|
.mp {
|
||||||
.mp dt {margin:0;clear:left}
|
max-width: 100ex;
|
||||||
.mp dt.flush {float:left;width:8ex}
|
padding: 0 9ex 1ex 4ex;
|
||||||
.mp dd {margin:0 0 0 9ex}
|
}
|
||||||
.mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
|
|
||||||
.mp pre {margin-bottom:20px}
|
.mp p,
|
||||||
.mp pre+h2,.mp pre+h3 {margin-top:22px}
|
.mp pre,
|
||||||
.mp h2+pre,.mp h3+pre {margin-top:5px}
|
.mp ul,
|
||||||
.mp img {display:block;margin:auto}
|
.mp ol,
|
||||||
.mp h1.man-title {display:none}
|
.mp dl {
|
||||||
.mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
|
margin: 0 0 20px 0;
|
||||||
.mp h2 {font-size:16px;line-height:1.25}
|
}
|
||||||
.mp h1 {font-size:20px;line-height:2}
|
|
||||||
.mp {text-align:justify;background:#fff}
|
.mp h2 {
|
||||||
.mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
|
margin: 10px 0 0 0;
|
||||||
.mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
|
}
|
||||||
.mp u {text-decoration:underline}
|
|
||||||
.mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
|
.mp>p,
|
||||||
.mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
|
.mp>pre,
|
||||||
.mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
|
.mp>ul,
|
||||||
.mp b.man-ref {font-weight:normal;color:#434241}
|
.mp>ol,
|
||||||
.mp pre {padding:0 4ex}
|
.mp>dl {
|
||||||
.mp pre code {font-weight:normal;color:#434241}
|
margin-left: 8ex;
|
||||||
.mp h2+pre,h3+pre {padding-left:0}
|
}
|
||||||
ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
|
|
||||||
ol.man-decor {width:100%}
|
.mp h3 {
|
||||||
ol.man-decor li.tl {text-align:left}
|
margin: 0 0 0 4ex;
|
||||||
ol.man-decor li.tc {text-align:center;letter-spacing:4px}
|
}
|
||||||
ol.man-decor li.tr {text-align:right;float:right}
|
|
||||||
|
.mp dt {
|
||||||
|
margin: 0;
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp dt.flush {
|
||||||
|
float: left;
|
||||||
|
width: 8ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp dd {
|
||||||
|
margin: 0 0 0 9ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp h1,
|
||||||
|
.mp h2,
|
||||||
|
.mp h3,
|
||||||
|
.mp h4 {
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp pre {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp pre+h2,
|
||||||
|
.mp pre+h3 {
|
||||||
|
margin-top: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp h2+pre,
|
||||||
|
.mp h3+pre {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp img {
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp h1.man-title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp,
|
||||||
|
.mp code,
|
||||||
|
.mp pre,
|
||||||
|
.mp tt,
|
||||||
|
.mp kbd,
|
||||||
|
.mp samp,
|
||||||
|
.mp h3,
|
||||||
|
.mp h4 {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.42857142857143;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp h2 {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp h1 {
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp {
|
||||||
|
text-align: justify;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp,
|
||||||
|
.mp code,
|
||||||
|
.mp pre,
|
||||||
|
.mp pre code,
|
||||||
|
.mp tt,
|
||||||
|
.mp kbd,
|
||||||
|
.mp samp {
|
||||||
|
color: #131211;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp h1,
|
||||||
|
.mp h2,
|
||||||
|
.mp h3,
|
||||||
|
.mp h4 {
|
||||||
|
color: #030201;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp u {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp code,
|
||||||
|
.mp strong,
|
||||||
|
.mp b {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #131211;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp em,
|
||||||
|
.mp var {
|
||||||
|
font-style: italic;
|
||||||
|
color: #232221;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp a,
|
||||||
|
.mp a:link,
|
||||||
|
.mp a:hover,
|
||||||
|
.mp a code,
|
||||||
|
.mp a pre,
|
||||||
|
.mp a tt,
|
||||||
|
.mp a kbd,
|
||||||
|
.mp a samp {
|
||||||
|
color: #0000ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp b.man-ref {
|
||||||
|
font-weight: normal;
|
||||||
|
color: #434241;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp pre {
|
||||||
|
padding: 0 4ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp pre code {
|
||||||
|
font-weight: normal;
|
||||||
|
color: #434241;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mp h2+pre,
|
||||||
|
h3+pre {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.man-decor,
|
||||||
|
ol.man-decor li {
|
||||||
|
margin: 3px 0 10px 0;
|
||||||
|
padding: 0;
|
||||||
|
float: left;
|
||||||
|
width: 33%;
|
||||||
|
list-style-type: none;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #999;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.man-decor {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.man-decor li.tl {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.man-decor li.tc {
|
||||||
|
text-align: center;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.man-decor li.tr {
|
||||||
|
text-align: right;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<style type='text/css' media='all'>
|
<style type='text/css' media='all'>
|
||||||
/* style: 80c */
|
/* style: 80c */
|
||||||
.mp {max-width:86ex}
|
|
||||||
ul {list-style: None; margin-left: 1em!important}
|
.mp {
|
||||||
.man-navigation {left:101ex}
|
max-width: 86ex
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: None;
|
||||||
|
margin-left: 1em !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.man-navigation {
|
||||||
|
left: 101ex
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheme-container {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body id='manpage'>
|
<body id='manpage'>
|
||||||
<a href="https://github.com/requests/httpbin" class="github-corner" aria-label="View source on Github">
|
<a href="https://github.com/requests/httpbin" class="github-corner" aria-label="View source on Github">
|
||||||
<svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true">
|
<svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;"
|
||||||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
|
aria-hidden="true">
|
||||||
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
|
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
|
||||||
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>
|
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
|
||||||
</svg>
|
fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
|
||||||
</a>
|
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
|
||||||
|
fill="currentColor" class="octo-body"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% include 'httpbin.1.html' %}
|
{% include 'httpbin.1.html' %} {% if tracking_enabled %} {% include 'trackingscripts.html' %} {% endif %}
|
||||||
|
|
||||||
{% if tracking_enabled %}
|
|
||||||
{% include 'trackingscripts.html' %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "httpbin",
|
||||||
|
"regions": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"alias": [
|
||||||
|
"httpbin.org"
|
||||||
|
],
|
||||||
|
"type": "docker"
|
||||||
|
}
|
||||||
@@ -2,9 +2,13 @@ from setuptools import setup, find_packages
|
|||||||
import os
|
import os
|
||||||
import io
|
import io
|
||||||
|
|
||||||
|
|
||||||
|
with open(os.path.join(os.path.realpath(os.path.dirname(__file__)), 'httpbin', 'VERSION')) as version_file:
|
||||||
|
version = version_file.read().strip()
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="httpbin",
|
name="httpbin",
|
||||||
version="0.9.0",
|
version=version,
|
||||||
description="HTTP Request and Response Service",
|
description="HTTP Request and Response Service",
|
||||||
long_description="A simple HTTP Request & Response Service, written in Python + Flask.",
|
long_description="A simple HTTP Request & Response Service, written in Python + Flask.",
|
||||||
|
|
||||||
|
|||||||
@@ -280,6 +280,37 @@ class HttpbinTestCase(unittest.TestCase):
|
|||||||
response = self.app.get('/brotli')
|
response = self.app.get('/brotli')
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
def test_bearer_auth(self):
|
||||||
|
token = 'abcd1234'
|
||||||
|
response = self.app.get(
|
||||||
|
'/bearer',
|
||||||
|
headers={'Authorization': 'Bearer ' + token}
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
assert json.loads(response.data.decode('utf-8'))['token'] == token
|
||||||
|
|
||||||
|
def test_bearer_auth_with_wrong_authorization_type(self):
|
||||||
|
"""Sending an non-Bearer Authorization header to /bearer should return a 401"""
|
||||||
|
auth_headers = (
|
||||||
|
('Authorization', 'Basic 1234abcd'),
|
||||||
|
('Authorization', ''),
|
||||||
|
('', '')
|
||||||
|
)
|
||||||
|
for header in auth_headers:
|
||||||
|
response = self.app.get(
|
||||||
|
'/bearer',
|
||||||
|
headers={header[0]: header[1]}
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
||||||
|
def test_bearer_auth_with_missing_token(self):
|
||||||
|
"""Sending an 'Authorization: Bearer' header with no token to /bearer should return a 401"""
|
||||||
|
response = self.app.get(
|
||||||
|
'/bearer',
|
||||||
|
headers={'Authorization': 'Bearer'}
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
||||||
def test_digest_auth_with_wrong_password(self):
|
def test_digest_auth_with_wrong_password(self):
|
||||||
auth_header = 'Digest username="user",realm="wrong",nonce="wrong",uri="/digest-auth/user/passwd/MD5",response="wrong",opaque="wrong"'
|
auth_header = 'Digest username="user",realm="wrong",nonce="wrong",uri="/digest-auth/user/passwd/MD5",response="wrong",opaque="wrong"'
|
||||||
response = self.app.get(
|
response = self.app.get(
|
||||||
|
|||||||
Reference in New Issue
Block a user