Bladeren bron

Added CORS preflight request support.

This change is based on the patch from binux.
Tatsuhiro Tsujikawa 13 jaren geleden
bovenliggende
commit
5a0a62c5f4
3 gewijzigde bestanden met toevoegingen van 42 en 1 verwijderingen
  1. 11 0
      src/HttpServer.h
  2. 27 0
      src/HttpServerBodyCommand.cc
  3. 4 1
      src/HttpServerCommand.cc

+ 11 - 0
src/HttpServer.h

@@ -84,6 +84,7 @@ public:
 
   const std::string& getRequestPath() const;
 
+
   void feedResponse(std::string& text, const std::string& contentType);
 
   // Feeds HTTP response with the status code |status| (e.g.,
@@ -135,6 +136,11 @@ public:
     return socketRecvBuffer_;
   }
 
+  const std::string& getAllowOrigin() const
+  {
+    return allowOrigin_;
+  }
+
   void setAllowOrigin(const std::string& allowOrigin)
   {
     allowOrigin_ = allowOrigin;
@@ -144,6 +150,11 @@ public:
   {
     return socket_;
   }
+
+  const SharedHandle<HttpHeader>& getRequestHeader() const
+  {
+    return lastRequestHeader_;
+  }
 };
 
 } // namespace aria2

+ 27 - 0
src/HttpServerBodyCommand.cc

@@ -159,6 +159,33 @@ bool HttpServerBodyCommand::execute()
         std::string query(std::find(reqPath.begin(), reqPath.end(), '?'),
                           reqPath.end());
         reqPath.erase(reqPath.size()-query.size(), query.size());
+
+        if(httpServer_->getMethod() == "OPTIONS") {
+          // Response to Preflight Request.
+          // See http://www.w3.org/TR/cors/
+          const SharedHandle<HttpHeader>& header =
+            httpServer_->getRequestHeader();
+          std::string accessControlHeaders;
+          if(!header->find("origin").empty() &&
+             !header->find("access-control-request-method").empty() &&
+             !httpServer_->getAllowOrigin().empty()) {
+            accessControlHeaders +=
+              "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n"
+              "Access-Control-Max-Age: 1728000\r\n";
+            const std::string& accReqHeaders =
+              header->find("access-control-request-headers");
+            if(!accReqHeaders.empty()) {
+              // We allow all headers requested.
+              accessControlHeaders += "Access-Control-Allow-Headers: ";
+              accessControlHeaders += accReqHeaders;
+              accessControlHeaders += "\r\n";
+            }
+          }
+          httpServer_->feedResponse(200, accessControlHeaders);
+          addHttpServerResponseCommand();
+          return true;
+        }
+
         // Do something for requestpath and body
         if(reqPath == "/rpc") {
 #ifdef ENABLE_XML_RPC

+ 4 - 1
src/HttpServerCommand.cc

@@ -164,7 +164,10 @@ bool HttpServerCommand::execute()
         e_->addCommand(this);
         return false;
       }
-      if(!httpServer_->authenticate()) {
+      // CORS preflight request uses OPTIONS method. It is not
+      // restricted by authentication.
+      if(!httpServer_->authenticate() &&
+         httpServer_->getMethod() != "OPTIONS") {
         httpServer_->disableKeepAlive();
         httpServer_->feedResponse
           (401, "WWW-Authenticate: Basic realm=\"aria2\"\r\n");