Skip to content

Commit

Permalink
Merge pull request postmanlabs#79 from rochacon/cors
Browse files Browse the repository at this point in the history
Adding CORS support for all requests
  • Loading branch information
Kenneth Reitz committed Jul 10, 2013
2 parents 802b1ea + e3cd47d commit 111a933
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 2 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Freely hosted in [HTTP](http://httpbin.org) &
- [`/relative-redirect/:n`](http://httpbin.org/relative-redirect/6) 302 Relative redirects *n* times.
- [`/cookies`](http://httpbin.org/cookies) Returns cookie data.
- [`/cookies/set?name=value`](http://httpbin.org/cookies/set?k1=v1&k2=v2) Sets one or more simple cookies.
- [`/cookies/delete?name`](http://httpbin.org/cookies/delete?k1&k2) Deletes one or more simple cookies.
- [`/basic-auth/:user/:passwd`](http://httpbin.org/basic-auth/user/passwd) Challenges HTTPBasic Auth.
- [`/hidden-basic-auth/:user/:passwd`](http://httpbin.org/hidden-basic-auth/user/passwd) 404'd BasicAuth.
- [`/digest-auth/:qop/:user/:passwd`](http://httpbin.org/digest-auth/auth/user/passwd) Challenges HTTP Digest Auth.
Expand Down Expand Up @@ -82,6 +83,35 @@ All endpoint responses are JSON-encoded.
Content-Length: 135


### $ curl https://httpbin.org/get?show_env=1

{
"headers": {
"Content-Length": "",
"Accept-Language": "en-US,en;q=0.8",
"Accept-Encoding": "gzip,deflate,sdch",
"X-Forwarded-Port": "443",
"X-Forwarded-For": "109.60.101.240",
"X-Heroku-Dynos-In-Use": "1",
"Host": "httpbin.org",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"User-Agent": "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.83 Safari/535.11",
"X-Request-Start": "1350053933441",
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.3",
"Connection": "keep-alive",
"X-Forwarded-Proto": "https",
"Cookie": "_gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1; _gauges_unique_hour=1",
"X-Heroku-Queue-Depth": "0",
"X-Heroku-Queue-Wait-Time": "11",
"Content-Type": ""
},
"args": {
"show_env": "1"
},
"origin": "109.60.101.240",
"url": "http://httpbin.org/get?show_env=1"
}

## AUTHOR

A [Kenneth Reitz](http://kennethreitz.com/pages/open-projects.html)
Expand Down
26 changes: 26 additions & 0 deletions httpbin/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@
sentry = Sentry(app)


# -----------
# Middlewares
# -----------
@app.after_request
def set_cors_headers(response):
response.headers['Access-Control-Allow-Origin'] = request.headers.get('Origin', '*')

if request.method == 'OPTIONS':
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, PATCH, OPTIONS'
response.headers['Access-Control-Max-Age'] = '3600' # 1 hour cache
return response


# ------
# Routes
# ------
Expand Down Expand Up @@ -293,6 +307,18 @@ def set_cookies():
return r


@app.route('/cookies/delete')
def delete_cookies():
"""Deletes cookie(s) as provided by the query string and redirects to cookie list."""

cookies = dict(request.args.items())
r = app.make_response(redirect('/cookies'))
for key, value in cookies.items():
r.delete_cookie(key=key)

return r


@app.route('/basic-auth/<user>/<passwd>')
def basic_auth(user='user', passwd='passwd'):
"""Prompts the user for authorization using HTTP Basic Auth."""
Expand Down
1 change: 1 addition & 0 deletions httpbin/templates/httpbin.1.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ <h2 id="ENDPOINTS">ENDPOINTS</h2>
<li><a href="/relative-redirect/6"><code>/relative-redirect/:n</code></a> 302 Relative redirects <em>n</em> times.</li>
<li><a href="/cookies" data-bare-link="true"><code>/cookies</code></a> Returns cookie data.</li>
<li><a href="/cookies/set?k1=v1&amp;k2=v2"><code>/cookies/set?name=value</code></a> Sets one or more simple cookies.</li>
<li><a href="/cookies/delete?k1&amp;k2"><code>/cookies/delete?name</code></a> Deletes one or more simple cookies.</li>
<li><a href="/basic-auth/user/passwd"><code>/basic-auth/:user/:passwd</code></a> Challenges HTTPBasic Auth.</li>
<li><a href="/hidden-basic-auth/user/passwd"><code>/hidden-basic-auth/:user/:passwd</code></a> 404'd BasicAuth.</li>
<li><a href="/digest-auth/auth/user/passwd"><code>/digest-auth/:qop/:user/:passwd</code></a> Challenges HTTP Digest Auth.</li>
Expand Down
20 changes: 18 additions & 2 deletions test_httpbin.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import base64
import unittest

import httpbin
import unittest
import base64


def _string_to_base64(string):
Expand Down Expand Up @@ -41,6 +41,22 @@ def test_post_file_binary(self):
response = self.app.post('/post', data={"file": f})
self.assertEquals(response.status_code, 200)

def test_set_cors_headers_after_request(self):
response = self.app.get('/get')
self.assertEquals(response.headers.get('Access-Control-Allow-Origin'), '*')

def test_set_cors_headers_after_request_with_request_origin(self):
response = self.app.get('/get', headers={'Origin': 'origin'})
self.assertEquals(response.headers.get('Access-Control-Allow-Origin'), 'origin')

def test_set_cors_headers_with_options_verb(self):
response = self.app.open('/get', method='OPTIONS')
self.assertEquals(response.headers.get('Access-Control-Allow-Origin'), '*')
self.assertEquals(response.headers.get('Access-Control-Allow-Credentials'), 'true')
self.assertEquals(response.headers.get('Access-Control-Allow-Methods'), 'GET, POST, PUT, DELETE, PATCH, OPTIONS')
self.assertEquals(response.headers.get('Access-Control-Max-Age'), '3600')
self.assertNotIn('Access-Control-Allow-Headers', response.headers) # FIXME should we add any extra headers?


if __name__ == '__main__':
unittest.main()

0 comments on commit 111a933

Please sign in to comment.