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") != ""){