diff --git a/lib/http_parser.cpp b/lib/http_parser.cpp index 7408c016..93d3f9e1 100644 --- a/lib/http_parser.cpp +++ b/lib/http_parser.cpp @@ -148,7 +148,7 @@ std::string &HTTP::Parser::BuildRequest(){ /// \todo Include POST variable handling for vars? std::map::iterator it; if (protocol.size() < 5 || protocol[4] != '/'){protocol = "HTTP/1.0";} - if (method == "GET" && vars.size() && url.find('?') == std::string::npos){ + if (method != "POST" && vars.size() && url.find('?') == std::string::npos){ builder = method + " " + Encodings::URL::encode(url, "/:=@[]") + allVars() + " " + protocol + "\r\n"; }else{ builder = method + " " + Encodings::URL::encode(url, "/:=@[]") + " " + protocol + "\r\n"; @@ -277,9 +277,10 @@ void HTTP::Parser::SendResponse(std::string code, std::string message, Socket::C void HTTP::Parser::StartResponse(std::string code, std::string message, const HTTP::Parser &request, Socket::Connection &conn, bool bufferAllChunks){ std::string prot = request.protocol; - sendingChunks = + bool willSendChunks = (!bufferAllChunks && request.protocol == "HTTP/1.1" && request.GetHeader("Connection") != "close"); CleanPreserveHeaders(); + sendingChunks = willSendChunks; protocol = prot; if (sendingChunks){ SetHeader("Transfer-Encoding", "chunked"); diff --git a/lib/urireader.cpp b/lib/urireader.cpp index f65a27e9..b52d496a 100644 --- a/lib/urireader.cpp +++ b/lib/urireader.cpp @@ -45,13 +45,13 @@ namespace HTTP{ void URIReader::dataCallback(const char *ptr, size_t size){allData.append(ptr, size);} bool URIReader::open(const HTTP::URL &uri){ - close(); myURI = uri; curPos = 0; allData.truncate(0); bufPos = 0; if (!myURI.protocol.size() || myURI.protocol == "file"){ + close(); if (!myURI.path.size() || myURI.path == "-"){ downer.getSocket().open(-1, fileno(stdin)); stateType = HTTP::Stream; diff --git a/src/output/output_hls.cpp b/src/output/output_hls.cpp index edf7f29d..44d3ec9c 100644 --- a/src/output/output_hls.cpp +++ b/src/output/output_hls.cpp @@ -230,13 +230,11 @@ namespace Mist{ std::string sessId = H.GetVar("sessId"); if (H.url == "/crossdomain.xml"){ - H.Clean(); H.SetHeader("Content-Type", "text/xml"); H.SetHeader("Server", APPIDENT); 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"){ bool isTS = (HTTP::URL(H.url).getExt().substr(0, 3) != "m3u"); - H.Clean(); H.setCORSHeaders(); if (isTS){ H.SetHeader("Content-Type", "video/mp2t"); @@ -266,7 +262,6 @@ namespace Mist{ } H.SetBody(""); H.SendResponse("200", "OK", myConn); - H.Clean(); return; } @@ -294,11 +289,9 @@ namespace Mist{ if (sscanf(tmpStr.c_str(), "/%zu_%zu/%" PRIu64 "_%" PRIu64 ".ts", &vidTrack, &audTrack, &from, &until) != 4){ if (sscanf(tmpStr.c_str(), "/%zu/%" PRIu64 "_%" PRIu64 ".ts", &vidTrack, &from, &until) != 3){ MEDIUM_MSG("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 return; } userSelect.clear(); @@ -314,12 +307,10 @@ namespace Mist{ } if (M.getLive() && from < M.getFirstms(vidTrack)){ - 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("404", "Fragment out of range")); - H.Clean(); // clean for any possible next requests WARN_MSG("Fragment @ %" PRIu64 " too old", from); return; } @@ -335,7 +326,6 @@ namespace Mist{ } if (method == "OPTIONS" || method == "HEAD"){ H.SendResponse("200", "OK", myConn); - H.Clean(); return; } @@ -353,17 +343,14 @@ namespace Mist{ }else{ initialize(); std::string request = H.url.substr(H.url.find("/", 5) + 1); - H.Clean(); H.setCORSHeaders(); H.SetHeader("Content-Type", "application/vnd.apple.mpegurl"); if (!M.getValidTracks().size()){ H.SendResponse("404", "Not online or found", myConn); - H.Clean(); return; } if (method == "OPTIONS" || method == "HEAD"){ H.SendResponse("200", "OK", myConn); - H.Clean(); return; } std::string manifest; @@ -373,7 +360,6 @@ namespace Mist{ size_t idx = atoi(request.substr(0, request.find("/")).c_str()); if (!M.getValidTracks().count(idx)){ H.SendResponse("404", "No corresponding track found", myConn); - H.Clean(); return; } @@ -389,7 +375,6 @@ namespace Mist{ if (thisPacket.getTime() >= until){ stop(); wantRequest = true; - parseData = false; // Ensure alignment of contCounters, to prevent discontinuities. for (std::map::iterator it = contCounters.begin(); it != contCounters.end(); it++){ @@ -407,6 +392,7 @@ namespace Mist{ // Signal end of data H.Chunkify("", 0, myConn); + H.Clean(); return; } // Invoke the generic TS output sendNext handler diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp index c69c9e32..5abe6cdf 100644 --- a/src/output/output_http.cpp +++ b/src/output/output_http.cpp @@ -14,7 +14,6 @@ namespace Mist{ idleInterval = 0; idleLast = 0; if (config->getString("ip").size()){myConn.setHost(config->getString("ip"));} - firstRun = true; if (config->getString("prequest").size()){ myConn.Received().prepend(config->getString("prequest")); } @@ -197,14 +196,11 @@ namespace Mist{ if (!isBlocking && !parseData){Util::sleep(100);} return; } - // If we can't read anything more and we're non-blocking, sleep some. - if (!firstRun && !myConn.spool()){ - if (!isBlocking && !parseData){Util::sleep(100);} - return; - } - firstRun = false; + //Attempt to read a HTTP request, regardless of data being available + bool sawRequest = false; while (H.Read(myConn)){ + sawRequest = true; std::string handler = getHandler(); if (handler != capa["name"].asStringRef() || H.GetVar("stream") != streamName){ INFO_MSG("Received request: %s => %s (%s)", H.getUrl().c_str(), handler.c_str(), H.GetVar("stream").c_str()); @@ -307,8 +303,12 @@ namespace Mist{ if (!myConn){return;} onHTTP(); idleLast = Util::bootMS(); - if (!H.bufferChunks){H.Clean();} + // Prevent the clean as well as the loop when we're in the middle of handling a request now + if (!wantRequest){return;} + H.Clean(); } + // If we can't read anything more and we're non-blocking, sleep some. + if (!sawRequest && !myConn.spool() && !isBlocking && !parseData){Util::sleep(100);} } /// Default HTTP handler. diff --git a/src/output/output_http.h b/src/output/output_http.h index 402bd742..3acb1b01 100644 --- a/src/output/output_http.h +++ b/src/output/output_http.h @@ -27,7 +27,6 @@ namespace Mist{ bool parseRange(std::string header, uint64_t &byteStart, uint64_t &byteEnd); protected: - bool firstRun; bool responded; HTTP::Parser H; HTTP::Websocket *webSock;