Blob Blame History Raw
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