Просмотр исходного кода

Merge pull request #9110 from afishbeck/corsAllow

HPCC-14493 Cross domaing scripting of ESP API

Reviewed-By: Gordon Smith <gordon.smith@lexisnexis.com>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 8 лет назад
Родитель
Сommit
065ef80919

+ 44 - 1
esp/bindings/http/platform/httpservice.cpp

@@ -215,6 +215,18 @@ EspHttpBinding* CEspHttpServer::getBinding()
     return thebinding;
 }
 
+//CORS allow headers for interoperability, we do not rely on this for security since
+//that only means treating the browser as a trusted entity.  We need to be diligent and secure
+//for every request whether it comes from a cross domain browser or any other source
+
+void checkSetCORSAllowOrigin(CHttpRequest *req, CHttpResponse *resp)
+{
+    StringBuffer origin;
+    req->getHeader("Origin", origin);
+    if (origin.length())
+        resp->setHeader("Access-Control-Allow-Origin", "*");
+}
+
 int CEspHttpServer::processRequest()
 {
     try
@@ -312,6 +324,8 @@ int CEspHttpServer::processRequest()
 #endif
                 if (!rootAuth(ctx) )
                     return 0;
+
+                checkSetCORSAllowOrigin(m_request, m_response);
                 if (methodName.charAt(methodName.length()-1)=='_')
                     methodName.setCharAt(methodName.length()-1, 0);
                 if (!stricmp(methodName.str(), "files"))
@@ -405,7 +419,7 @@ int CEspHttpServer::processRequest()
                         authState = authSucceeded;
                 }
             }
-                    
+
             if (authState==authRequired)
             {
                 ISecUser *user = ctx->queryUser();
@@ -433,6 +447,12 @@ int CEspHttpServer::processRequest()
             if (authenticateOptionalFailed(*ctx,thebinding))
                 throw createEspHttpException(401,"Unauthorized Access","Unauthorized Access");
 
+
+            if(strieq(method.str(), OPTIONS_METHOD))
+                return onOptions();
+
+            checkSetCORSAllowOrigin(m_request, m_response);
+
             if (thebinding!=NULL)
             {
                 if(stricmp(method.str(), POST_METHOD)==0)
@@ -854,6 +874,29 @@ int CEspHttpServer::unsupported()
     return 0;
 }
 
+int CEspHttpServer::onOptions()
+{
+    m_response->setVersion(HTTP_VERSION);
+    m_response->setStatus(HTTP_STATUS_OK);
+
+    //CORS allow headers for interoperability, we do not rely on this for security since
+    //that only means treating the browser as a trusted entity.  We need to be diligent and secure
+    //for every request whether it comes from a cross domain browser or any other source
+    StringBuffer allowHeaders;
+    m_request->getHeader("Access-Control-Request-Headers", allowHeaders);
+    if (allowHeaders.length())
+        m_response->setHeader("Access-Control-Allow-Headers", allowHeaders);
+    m_response->setHeader("Access-Control-Allow-Origin", "*");
+    m_response->setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
+    m_response->setHeader("Access-Control-Max-Age", "86400"); //arbitrary 24 hours
+    m_response->setContentType("text/plain");
+    m_response->setContent("");
+
+    m_response->send();
+
+    return 0;
+}
+
 int CEspHttpServer::onPost()
 {
     HtmlPage page("Enterprise Services Platform");

+ 1 - 0
esp/bindings/http/platform/httpservice.hpp

@@ -67,6 +67,7 @@ public:
 
     virtual int onPost();
     virtual int onGet();
+    virtual int onOptions();
 
     virtual int onGetFile(CHttpRequest* request, CHttpResponse* response, const char *path);
     virtual int onGetXslt(CHttpRequest* request, CHttpResponse* response, const char *path);

+ 4 - 0
esp/bindings/http/platform/httptransport.cpp

@@ -1235,6 +1235,10 @@ int CHttpRequest::parseFirstLine(char* oneline)
     {
         setMethod(HEAD_METHOD);
     }
+    else if(!stricmp(method.str(), OPTIONS_METHOD))
+    {
+        setMethod(OPTIONS_METHOD);
+    }
 
     StringBuffer pathbuf;
     curptr = Utils::getWord(curptr, pathbuf);

+ 1 - 0
esp/bindings/http/platform/httptransport.ipp

@@ -35,6 +35,7 @@
 #define POST_METHOD "POST"
 #define GET_METHOD "GET"
 #define HEAD_METHOD "HEAD"
+#define OPTIONS_METHOD "OPTIONS"
 
 #define UNKNOWN_METHOD_ERROR -1;