]> granicus.if.org Git - pdns/commitdiff
Implement CORS in WebServer, fixes #1984
authorAki Tuomi <cmouse@desteem.org>
Fri, 30 Jan 2015 08:41:41 +0000 (10:41 +0200)
committerAki Tuomi <cmouse@desteem.org>
Mon, 2 Feb 2015 07:44:59 +0000 (09:44 +0200)
pdns/webserver.cc
regression-tests.api/test_Basics.py
regression-tests.api/test_helper.py

index 22eba06cf5d76888673fb04f451bc53e82466ac4..9c1be2f03bc871c1224f5098ef2f086294a4f63b 100644 (file)
@@ -101,8 +101,27 @@ void WebServer::registerBareHandler(const string& url, HandlerFunction handler)
   YaHTTP::Router::Any(url, f);
 }
 
+static bool optionsHandler(HttpRequest* req, HttpResponse* resp) {
+  if (req->method == "OPTIONS") {
+    resp->headers["access-control-allow-origin"] = "*";
+    resp->headers["access-control-allow-headers"] = "Content-Type, X-API-Key";
+    resp->headers["access-control-allow-methods"] = "GET, POST, PUT, PATCH, DELETE, OPTIONS";
+    resp->headers["access-control-max-age"] = "3600";
+    resp->status = 200;
+    resp->headers["content-type"]= "text/plain";
+    resp->body = "";
+    return true;
+  }
+  return false;
+}
+
 static void apiWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp) {
   const string& api_key = arg()["experimental-api-key"];
+
+  if (optionsHandler(req, resp)) return;
+
+  resp->headers["access-control-allow-origin"] = "*";
+
   if (api_key.empty()) {
     L<<Logger::Debug<<"HTTP API Request \"" << req->url.path << "\": Authentication failed, API Key missing in config" << endl;
     throw HttpUnauthorizedException();
@@ -113,7 +132,6 @@ static void apiWrapper(WebServer::HandlerFunction handler, HttpRequest* req, Htt
     throw HttpUnauthorizedException();
   }
 
-  resp->headers["Access-Control-Allow-Origin"] = "*";
   resp->headers["Content-Type"] = "application/json";
 
   string callback;
@@ -155,6 +173,11 @@ void WebServer::registerApiHandler(const string& url, HandlerFunction handler) {
 
 static void webWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp) {
   const string& web_password = arg()["webserver-password"];
+
+  if (optionsHandler(req, resp)) return;
+
+  resp->headers["access-control-allow-origin"] = "*";
+
   if (!web_password.empty()) {
     bool auth_ok = req->compareAuthorization(web_password);
     if (!auth_ok) {
index 56f5db591ae7833420859fb15a755cd96353a7c2..79c3d9ecfdd975d998ec22f464c13c0436846121 100644 (file)
@@ -31,3 +31,14 @@ class TestBasics(ApiTestCase):
         status = resp.splitlines(0)[0]
         if '400' in status:
             raise Exception('Got unwanted response: %s' % status)
+
+    def test_cors(self):
+        r = self.session.options(self.url("/servers/localhost"))
+        # look for CORS headers
+
+        self.assertEquals(r.status_code, requests.codes.ok)
+        self.assertEquals(r.headers['access-control-allow-origin'], "*")
+        self.assertEquals(r.headers['access-control-allow-headers'], 'Content-Type, X-API-Key')
+        self.assertEquals(r.headers['access-control-allow-methods'], 'GET, POST, PUT, PATCH, DELETE, OPTIONS')
+
+        print "response", repr(r.headers)
index 287cccf136a02c64120edc1e64c8a23c35476d11..494b3be0e725e5e0a11df757e8c3b577c031a80c 100644 (file)
@@ -15,7 +15,7 @@ class ApiTestCase(unittest.TestCase):
         self.server_port = int(os.environ.get('WEBPORT', '5580'))
         self.server_url = 'http://%s:%s/' % (self.server_address, self.server_port)
         self.session = requests.Session()
-        self.session.headers = {'x-api-key': os.environ.get('APIKEY', 'changeme-key')}
+        self.session.headers = {'X-API-Key': os.environ.get('APIKEY', 'changeme-key'), 'Origin': 'http://%s:%s' % (self.server_address, self.server_port)}
 
     def url(self, relative_url):
         return urlparse.urljoin(self.server_url, relative_url)