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 3f08acb4..c17ca117 100644
--- a/src/output/output_hds.cpp
+++ b/src/output/output_hds.cpp
@@ -192,15 +192,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;
@@ -221,6 +228,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
@@ -252,6 +260,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);
@@ -280,6 +294,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 d9a2adbe..4a945088 100644
--- a/src/output/output_hls.cpp
+++ b/src/output/output_hls.cpp
@@ -158,28 +158,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;
@@ -202,6 +199,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
@@ -234,6 +232,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
@@ -246,8 +245,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;
@@ -275,6 +280,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 1ce17bd4..4b5dc62d 100644
--- a/src/output/output_hss.cpp
+++ b/src/output/output_hss.cpp
@@ -528,12 +528,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;
@@ -546,6 +545,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 e66539f7..521140bf 100644
--- a/src/output/output_http_internal.cpp
+++ b/src/output/output_http_internal.cpp
@@ -160,13 +160,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
@@ -175,8 +183,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
@@ -213,8 +227,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;
}
@@ -224,6 +245,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;
@@ -276,8 +302,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;
}
@@ -297,6 +329,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;
if (config->getString("nostreamtext") != ""){
@@ -430,6 +467,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 da1ea1e4..f3aff008 100644
--- a/src/output/output_progressive_mp4.cpp
+++ b/src/output/output_progressive_mp4.cpp
@@ -604,6 +604,15 @@ namespace Mist {
}
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;
+ }
+
/*LTS-START*/
//allow setting of max lead time through buffer variable.
//max lead time is set in MS, but the variable is in integer seconds for simplicity.
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") != ""){