diff -ur ipython-2.4.1/IPython/html/base/handlers.py ipython/IPython/html/base/handlers.py
--- ipython-2.4.1/IPython/html/base/handlers.py 2015-02-09 15:59:57.000000000 -0700
+++ ipython/IPython/html/base/handlers.py 2015-07-16 09:08:21.874322394 -0600
@@ -29,6 +29,10 @@
from http.client import responses
except ImportError:
from httplib import responses
+try:
+ from urllib.parse import urlparse # Py 3
+except ImportError:
+ from urlparse import urlparse # Py 2
from jinja2 import TemplateNotFound
from tornado import web
@@ -208,6 +212,50 @@
origin = self.request.headers.get("Sec-Websocket-Origin", None)
return origin
+ def check_origin_api(self):
+ """Check Origin for cross-site API requests.
+
+ Copied from WebSocket with changes:
+
+ - allow unspecified host/origin (e.g. scripts)
+ """
+ if self.allow_origin == '*':
+ return True
+
+ host = self.request.headers.get("Host")
+ origin = self.request.headers.get("Origin")
+
+ # If no header is provided, assume it comes from a script/curl.
+ # We are only concerned with cross-site browser stuff here.
+ if origin is None or host is None:
+ return True
+
+ origin = origin.lower()
+ origin_host = urlparse(origin).netloc
+
+ # OK if origin matches host
+ if origin_host == host:
+ return True
+
+ # Check CORS headers
+ if self.allow_origin:
+ allow = self.allow_origin == origin
+ elif self.allow_origin_pat:
+ allow = bool(self.allow_origin_pat.match(origin))
+ else:
+ # No CORS headers deny the request
+ allow = False
+ if not allow:
+ self.log.warn("Blocking Cross Origin API request. Origin: %s, Host: %s",
+ origin, host,
+ )
+ return allow
+
+ def prepare(self):
+ if not self.check_origin_api():
+ raise web.HTTPError(404)
+ return super(IPythonHandler, self).prepare()
+
#---------------------------------------------------------------
# template rendering
#---------------------------------------------------------------
@@ -339,6 +387,7 @@
message = e.log_message
self.log.warn(message)
self.set_status(e.status_code)
+ self.set_header('Content-Type', 'application/json')
self.finish(json.dumps(dict(message=message)))
except Exception:
self.log.error("Unhandled error in API request", exc_info=True)
@@ -348,6 +397,7 @@
self.set_status(status)
tb_text = ''.join(traceback.format_exception(t, value, tb))
reply = dict(message=message, traceback=tb_text)
+ self.set_header('Content-Type', 'application/json')
self.finish(json.dumps(reply))
else:
return result