]> 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>
Sun, 1 Feb 2015 13:55:31 +0000 (15:55 +0200)
pdns/webserver.cc
regression-tests.api/test_Basics.py
regression-tests.api/test_helper.py

index 4c012cf013037ffd4bbf378584cd063285a42175..d4bfdedb3d5dbe151affb819fb639f8f3a55b00b 100644 (file)
@@ -96,8 +96,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();
@@ -109,7 +128,6 @@ static void apiWrapper(WebServer::HandlerFunction handler, HttpRequest* req, Htt
     throw HttpBadRequestException();
   }
 
-  resp->headers["Access-Control-Allow-Origin"] = "*";
   resp->headers["Content-Type"] = "application/json";
 
   string callback;
@@ -151,6 +169,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 1856e41e564b9dc98f33eb085ce8132a5a7916a1..c275018e5efe4a1dfce63378972e199bfd6e23ed 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 448b2b61cd29093f9af0a03e2fad0fc7af52961d..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)