diff --git a/lib/http_parser.cpp b/lib/http_parser.cpp index 30b58bf6..d9742f7e 100644 --- a/lib/http_parser.cpp +++ b/lib/http_parser.cpp @@ -35,9 +35,13 @@ void HTTP::Parser::CleanPreserveHeaders() { /// Sets the neccesary headers to allow Cross Origin Resource Sharing with all domains. void HTTP::Parser::setCORSHeaders(){ SetHeader("Access-Control-Allow-Origin", "*"); - SetHeader("Access-Control-Allow-Methods", "GET, POST"); - SetHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With"); SetHeader("Access-Control-Allow-Credentials", "true"); + SetHeader("Access-Control-Expose-Headers", "*"); + SetHeader("Access-Control-Max-Age", "600"); + SetHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, HEAD"); + SetHeader("Access-Control-Allow-Headers", "*"); + SetHeader("Access-Control-Request-Method", "GET"); + SetHeader("Access-Control-Request-Headers", "*"); } diff --git a/src/output/output_hds.cpp b/src/output/output_hds.cpp index 1951be74..5eaa6d59 100644 --- a/src/output/output_hds.cpp +++ b/src/output/output_hds.cpp @@ -178,15 +178,22 @@ namespace Mist { } void OutHDS::onHTTP(){ + std::string method = H.method; if (H.url.find(".abst") != std::string::npos){ initialize(); std::string streamID = H.url.substr(streamName.size() + 10); streamID = streamID.substr(0, streamID.find(".abst")); H.Clean(); - H.SetBody(dynamicBootstrap(atoll(streamID.c_str()))); H.SetHeader("Content-Type", "binary/octet"); H.SetHeader("Cache-Control", "no-cache"); + H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } + H.SetBody(dynamicBootstrap(atoll(streamID.c_str()))); H.SendResponse("200", "OK", myConn); H.Clean(); //clean for any possible next requests return; @@ -207,6 +214,7 @@ namespace Mist { unsigned int mslen = 0; if (fragNum < (unsigned int)myMeta.tracks[tid].missedFrags){ H.Clean(); + H.setCORSHeaders(); H.SetBody("The requested fragment is no longer kept in memory on the server and cannot be served.\n"); H.SendResponse("412", "Fragment out of range", myConn); H.Clean(); //clean for any possible next requests @@ -238,6 +246,12 @@ namespace Mist { H.Clean(); H.SetHeader("Content-Type", "video/mp4"); + H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } H.StartResponse(H, myConn); //send the bootstrap std::string bootstrap = dynamicBootstrap(tid); @@ -266,6 +280,12 @@ namespace Mist { H.Clean(); H.SetHeader("Content-Type", "text/xml"); H.SetHeader("Cache-Control", "no-cache"); + H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } H.SetBody(dynamicIndex()); H.SendResponse("200", "OK", myConn); } diff --git a/src/output/output_hls.cpp b/src/output/output_hls.cpp index 055f209f..2bd97072 100644 --- a/src/output/output_hls.cpp +++ b/src/output/output_hls.cpp @@ -134,28 +134,25 @@ namespace Mist { } void OutHLS::onHTTP(){ + std::string method = H.method; + + if (H.url == "/crossdomain.xml"){ H.Clean(); H.SetHeader("Content-Type", "text/xml"); H.SetHeader("Server", "MistServer/" PACKAGE_VERSION); H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } H.SetBody(""); H.SendResponse("200", "OK", myConn); H.Clean(); //clean for any possible next requests return; } //crossdomain.xml - if (H.method == "OPTIONS"){ - H.Clean(); - H.SetHeader("Content-Type", "application/octet-stream"); - H.SetHeader("Cache-Control", "no-cache"); - H.setCORSHeaders(); - H.SetBody(""); - H.SendResponse("200", "OK", myConn); - H.Clean(); - return; - } - if (H.url.find("hls") == std::string::npos){ myConn.close(); return; @@ -178,6 +175,7 @@ namespace Mist { if (sscanf(tmpStr.c_str(), "/%u/%llu_%llu.ts", &vidTrack, &from, &until) != 3){ DEBUG_MSG(DLVL_MEDIUM, "Could not parse URL: %s", H.getUrl().c_str()); H.Clean(); + H.setCORSHeaders(); H.SetBody("The HLS URL wasn't understood - what did you want, exactly?\n"); myConn.SendNow(H.BuildResponse("404", "URL mismatch")); H.Clean(); //clean for any possible next requests @@ -210,6 +208,7 @@ namespace Mist { }while (myConn && seekable > 0); if (seekable < 0){ H.Clean(); + H.setCORSHeaders(); H.SetBody("The requested fragment is no longer kept in memory on the server and cannot be served.\n"); myConn.SendNow(H.BuildResponse("412", "Fragment out of range")); H.Clean(); //clean for any possible next requests @@ -222,8 +221,14 @@ namespace Mist { ts_from = from; lastVid = from * 90; + H.Clean(); H.SetHeader("Content-Type", "video/mp2t"); H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } H.StartResponse(H, myConn, VLCworkaround); unsigned int fragCounter = myMeta.tracks[vidTrack].missedFrags; @@ -251,6 +256,11 @@ namespace Mist { } H.SetHeader("Cache-Control", "no-cache"); H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } std::string manifest; if (request.find("/") == std::string::npos){ manifest = liveIndex(); diff --git a/src/output/output_hss.cpp b/src/output/output_hss.cpp index 3cb91656..de66efa2 100644 --- a/src/output/output_hss.cpp +++ b/src/output/output_hss.cpp @@ -438,12 +438,11 @@ namespace Mist { void OutHSS::onHTTP() { - if (H.method == "OPTIONS"){ + if ((H.method == "OPTIONS" || H.method == "HEAD") && H.url.find("Manifest") == std::string::npos){ H.Clean(); H.SetHeader("Content-Type", "application/octet-stream"); H.SetHeader("Cache-Control", "no-cache"); H.setCORSHeaders(); - H.SetBody(""); H.SendResponse("200", "OK", myConn); H.Clean(); return; @@ -455,6 +454,10 @@ namespace Mist { H.SetHeader("Content-Type", "text/xml"); H.SetHeader("Cache-Control", "no-cache"); H.setCORSHeaders(); + if(H.method == "OPTIONS" || H.method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + return; + } std::string manifest = smoothIndex(); H.SetBody(manifest); H.SendResponse("200", "OK", myConn); diff --git a/src/output/output_http_internal.cpp b/src/output/output_http_internal.cpp index f1720d5b..a19aba18 100644 --- a/src/output/output_http_internal.cpp +++ b/src/output/output_http_internal.cpp @@ -152,13 +152,21 @@ namespace Mist { } void OutHTTP::onHTTP(){ + std::string method = H.method; + if (H.url == "/crossdomain.xml"){ H.Clean(); H.SetHeader("Content-Type", "text/xml"); H.SetHeader("Server", "MistServer/" PACKAGE_VERSION); H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } H.SetBody(""); H.SendResponse("200", "OK", myConn); + H.Clean(); return; } //crossdomain.xml @@ -167,8 +175,14 @@ namespace Mist { H.SetHeader("Content-Type", "text/xml"); H.SetHeader("Server", "MistServer/" PACKAGE_VERSION); H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } H.SetBody(""); H.SendResponse("200", "OK", myConn); + H.Clean(); return; } //clientaccesspolicy.xml @@ -196,8 +210,15 @@ namespace Mist { H.SetHeader("Content-Type", "image/x-icon"); H.SetHeader("Server", "MistServer/" PACKAGE_VERSION); H.SetHeader("Content-Length", icon_len); + H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } H.SendResponse("200", "OK", myConn); myConn.SendNow((const char*)icon_data, icon_len); + H.Clean(); return; } @@ -207,6 +228,11 @@ namespace Mist { H.SetHeader("Content-Type", "text/html"); H.SetHeader("Server", "MistServer/" PACKAGE_VERSION); H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } H.SetBody("Stream "+streamName+""); H.SendResponse("200", "OK", myConn); return; @@ -259,8 +285,14 @@ namespace Mist { H.SetHeader("Content-Type", "application/smil"); H.SetHeader("Server", "MistServer/" PACKAGE_VERSION); H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } H.SetBody("\n \n \n \n \n \n"+trackSources+" \n \n"); H.SendResponse("200", "OK", myConn); + H.Clean(); return; } @@ -280,6 +312,11 @@ namespace Mist { }else{ H.SetHeader("Content-Type", "application/json"); } + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } response = "// Generating info code for stream " + streamName + "\n\nif (!mistvideo){var mistvideo = {};}\n"; JSON::Value json_resp; IPC::semaphore configLock("!mistConfLock", O_CREAT | O_RDWR, ACCESSPERMS, 1); @@ -409,6 +446,7 @@ namespace Mist { } H.SetBody(response); H.SendResponse("200", "OK", myConn); + H.Clean(); return; } //embed code generator } diff --git a/src/output/output_json.cpp b/src/output/output_json.cpp index 1d6928ed..6a430e02 100644 --- a/src/output/output_json.cpp +++ b/src/output/output_json.cpp @@ -30,8 +30,11 @@ namespace Mist { } void OutJSON::sendHeader(){ + std::string method = H.method; + H.Clean(); H.SetHeader("Content-Type", "text/javascript"); H.protocol = "HTTP/1.0"; + H.setCORSHeaders(); H.SendResponse("200", "OK", myConn); sentHeader = true; } @@ -46,6 +49,18 @@ namespace Mist { } void OutJSON::onHTTP(){ + std::string method = H.method; + + H.Clean(); + H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SetHeader("Content-Type", "text/javascript"); + H.protocol = "HTTP/1.0"; + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } + first = true; jsonp = ""; if (H.GetVar("callback") != ""){jsonp = H.GetVar("callback");} diff --git a/src/output/output_progressive_flv.cpp b/src/output/output_progressive_flv.cpp index 7efd9d6d..18ff7e9f 100644 --- a/src/output/output_progressive_flv.cpp +++ b/src/output/output_progressive_flv.cpp @@ -37,9 +37,12 @@ namespace Mist { } void OutProgressiveFLV::sendHeader(){ + + H.Clean(); H.SetHeader("Content-Type", "video/x-flv"); H.protocol = "HTTP/1.0"; + H.setCORSHeaders(); H.SendResponse("200", "OK", myConn); myConn.SendNow(FLV::Header, 13); tag.DTSCMetaInit(myMeta, selectedTracks); @@ -56,6 +59,18 @@ namespace Mist { } void OutProgressiveFLV::onHTTP(){ + std::string method = H.method; + + H.Clean(); + H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SetHeader("Content-Type", "video/x-flv"); + H.protocol = "HTTP/1.0"; + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } + parseData = true; wantRequest = false; } diff --git a/src/output/output_progressive_mp3.cpp b/src/output/output_progressive_mp3.cpp index 10569695..571f16bb 100644 --- a/src/output/output_progressive_mp3.cpp +++ b/src/output/output_progressive_mp3.cpp @@ -24,13 +24,32 @@ namespace Mist { } void OutProgressiveMP3::sendHeader(){ + std::string method = H.method; + H.Clean(); H.SetHeader("Content-Type", "audio/mpeg"); H.protocol = "HTTP/1.0"; + H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SendResponse("200", "OK", myConn); + return; + } H.SendResponse("200", "OK", myConn); sentHeader = true; } void OutProgressiveMP3::onHTTP(){ + std::string method = H.method; + + H.Clean(); + H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SetHeader("Content-Type", "audio/mpeg"); + H.protocol = "HTTP/1.0"; + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } + parseData = true; wantRequest = false; } diff --git a/src/output/output_progressive_mp4.cpp b/src/output/output_progressive_mp4.cpp index cb780d99..b3652cc5 100644 --- a/src/output/output_progressive_mp4.cpp +++ b/src/output/output_progressive_mp4.cpp @@ -439,8 +439,16 @@ namespace Mist { return; } } - void OutProgressiveMP4::onHTTP(){ + if(H.method == "OPTIONS" || H.method == "HEAD"){ + H.Clean(); + H.setCORSHeaders(); + H.SetHeader("Content-Type", "video/MP4"); + H.SetHeader("Accept-Ranges", "bytes, parsec"); + H.SendResponse("200", "OK", myConn); + return; + } + initialize(); parseData = true; wantRequest = false; diff --git a/src/output/output_progressive_ogg.cpp b/src/output/output_progressive_ogg.cpp index 006c5a8a..c081bd36 100644 --- a/src/output/output_progressive_ogg.cpp +++ b/src/output/output_progressive_ogg.cpp @@ -127,6 +127,7 @@ namespace Mist { HTTP_S.SetHeader("Content-Type", "video/ogg"); HTTP_S.protocol = "HTTP/1.0"; myConn.SendNow(HTTP_S.BuildResponse("200", "OK")); //no SetBody = unknown length - this is intentional, we will stream the entire file + std::map > initData; @@ -175,6 +176,16 @@ namespace Mist { void OutProgressiveOGG::onRequest(){ if (HTTP_R.Read(myConn)){ DEBUG_MSG(DLVL_DEVEL, "Received request %s", HTTP_R.getUrl().c_str()); + + if (HTTP_R.method == "OPTIONS" || HTTP_R.method == "HEAD"){ + HTTP_S.Clean(); + HTTP_S.SetHeader("Content-Type", "video/ogg"); + HTTP_S.protocol = "HTTP/1.0"; + HTTP_S.SendResponse("200", "OK", myConn); + HTTP_S.Clean(); + return; + } + if (HTTP_R.GetVar("audio") != ""){ selectedTracks.insert(JSON::Value(HTTP_R.GetVar("audio")).asInt()); } diff --git a/src/output/output_srt.cpp b/src/output/output_srt.cpp index 1f47f77b..ad5d6f3d 100644 --- a/src/output/output_srt.cpp +++ b/src/output/output_srt.cpp @@ -52,6 +52,17 @@ namespace Mist { } void OutProgressiveSRT::onHTTP(){ + std::string method = H.method; + + H.Clean(); + H.setCORSHeaders(); + if(method == "OPTIONS" || method == "HEAD"){ + H.SetHeader("Content-Type", "text/plain"); + H.protocol = "HTTP/1.0"; + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } lastNum = 0; webVTT = (H.url.find(".webvtt") != std::string::npos); if (H.GetVar("track") != ""){