diff --git a/gcovr.cfg b/gcovr.cfg
new file mode 100644
index 00000000..385b37bd
--- /dev/null
+++ b/gcovr.cfg
@@ -0,0 +1,3 @@
+filter = src/
+filter = lib/
+
diff --git a/lib/http_parser.cpp b/lib/http_parser.cpp
index 913a8e22..98d591f7 100644
--- a/lib/http_parser.cpp
+++ b/lib/http_parser.cpp
@@ -45,6 +45,7 @@ void HTTP::Parser::CleanPreserveHeaders(){
   protocol = "HTTP/1.1";
   body.clear();
   length = 0;
+  knownLength = false;
   vars.clear();
 }
 
@@ -619,11 +620,13 @@ bool HTTP::Parser::parse(std::string &HTTPbuffer, Util::DataCallback &cb){
         if (tmpA.size() == 0){
           seenHeaders = true;
           body.clear();
+          knownLength = false;
           if (GetHeader("Content-Length") != ""){
             length = atoi(GetHeader("Content-Length").c_str());
             if (!bodyCallback && (&cb == &Util::defaultDataCallback) && body.capacity() < length){
               body.reserve(length);
             }
+            knownLength = true;
           }
           if (GetHeader("Transfer-Encoding") == "chunked"){
             getChunks = true;
@@ -645,7 +648,7 @@ bool HTTP::Parser::parse(std::string &HTTPbuffer, Util::DataCallback &cb){
         unsigned int code = atoi(url.data());
         if ((code >= 100 && code < 200) || code == 204 || code == 304){return true;}
       }
-      if (length > 0 && !getChunks){
+      if (knownLength && !getChunks){
         unsigned int toappend = length - body.length();
 
         // limit the amount of bytes that will be appended to the amount there
@@ -673,8 +676,8 @@ bool HTTP::Parser::parse(std::string &HTTPbuffer, Util::DataCallback &cb){
           currentLength += toappend;
         }
         if (length == body.length()){
-          // parse POST variables
-          if (method == "POST"){parseVars(body, vars);}
+          // parse POST body if the content type is URLEncoded
+          if (method == "POST" && GetHeader("Content-Type") == "application/x-www-form-urlencoded"){parseVars(body, vars);}
           return true;
         }else{
           return false;
diff --git a/lib/http_parser.h b/lib/http_parser.h
index 35845aac..b45aedb9 100644
--- a/lib/http_parser.h
+++ b/lib/http_parser.h
@@ -57,6 +57,7 @@ namespace HTTP{
     std::string url;
     std::string protocol;
     unsigned int length;
+    bool knownLength;
     unsigned int currentLength;
     bool headerOnly; ///< If true, do not parse body if the length is a known size.
     bool bufferChunks;
diff --git a/test/http_parser.cpp b/test/http_parser.cpp
new file mode 100644
index 00000000..26e9783f
--- /dev/null
+++ b/test/http_parser.cpp
@@ -0,0 +1,64 @@
+#include <iostream>
+#include <mist/http_parser.h>
+#include <mist/timing.h>
+
+int main(int argc, char ** argv){
+  bool preMade = false;
+  Socket::Connection C(1, 0); // Open stdio by default
+  // If there is a T_HTTP environment variable, use that as input instead
+  if (getenv("T_HTTP")){
+    preMade = true;
+    // Keep stdio open, only drop the reference to it
+    C.drop();
+    // Create a pipe and reconnect the socket to it
+    int p[2];
+    if (pipe(p)){
+      FAIL_MSG("Could not open pipe!");
+      return 1;
+    }
+    C.open(p[1], p[0]);
+    // Write the T_HTTP env contents into the pipe
+    C.SendNow(getenv("T_HTTP"));
+    // Close the write end if we're not lingering
+    if (!getenv("T_LINGER")){close(p[1]);}
+  }
+
+  HTTP::Parser p;
+  int counter = 0;
+  C.setBlocking(false);
+  uint64_t lastData = Util::bootMS();
+  do {
+    if (C.spool()){
+      lastData = Util::bootMS();
+      while (p.Read(C)){
+        INFO_MSG("Read a HTTP message: %s %s %s (%zu bytes)", p.method.c_str(), p.url.c_str(), p.protocol.c_str(), p.body.size());
+        ++counter;
+        p.Clean();
+      }
+    }else{
+      // premade requests will instantly time out, others after 10 seconds
+      if (preMade){break;}
+      if (Util::bootMS() > lastData + 10000){
+        WARN_MSG("Read timeout, aborting");
+        break;
+      }
+      Util::sleep(5);
+    }
+  }while(C);
+  while (p.Read(C)){
+    INFO_MSG("Read a HTTP message: %s %s %s (%zu bytes)", p.method.c_str(), p.url.c_str(), p.protocol.c_str(), p.body.size());
+    ++counter;
+    p.Clean();
+  }
+
+  INFO_MSG("Total messages: %d", counter);
+
+  if (getenv("T_COUNT")){
+    if (counter != atoi(getenv("T_COUNT"))){
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
diff --git a/test/meson.build b/test/meson.build
index d127db1d..adc96929 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -148,6 +148,21 @@ test('DTSC Sizing Test', dtsc_sizing_test)
 bitwritertest = executable('bitwritertest', 'bitwriter.cpp', dependencies: libmist_dep)
 test('bitWriter Test', bitwritertest)
 
+httpparsertest = executable('httpparsertest', 'http_parser.cpp', dependencies: libmist_dep)
+test('GET request for /', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'GET / HTTP/1.1\n\n', 'T_COUNT':'1'})
+test('GET request for / with carriage returns', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'GET / HTTP/1.1\r\n\r\n', 'T_COUNT':'1'})
+test('POST request to /, raw body', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'POST / HTTP/1.1\nContent-Length: 4\nContent-Type: text/plain\n\ntest', 'T_COUNT':'1'})
+test('POST request to /, urlencoded body', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'POST / HTTP/1.1\nContent-Length: 28\nContent-Type: application/x-www-form-urlencoded\n\nfoo=bar&banana=sauce&cookies', 'T_COUNT':'1'})
+test('Blank HTTP response, closed connection', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'HTTP/1.1 200 OK\nDate: Thu, 15 Jun 2023 21:34:06 GMT\nContent-Length: 0\n\n', 'T_COUNT':'1'})
+test('Blank HTTP response, lingering connection', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'HTTP/1.1 200 OK\nDate: Thu, 15 Jun 2023 21:34:06 GMT\nContent-Length: 0\n\n', 'T_LINGER':'1', 'T_COUNT':'1'})
+test('Simple HTTP response, closed connection', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'HTTP/1.1 200 OK\nDate: Thu, 15 Jun 2023 21:34:06 GMT\nContent-Length: 4\n\ntest', 'T_COUNT':'1'})
+test('Simple HTTP response, lingering connection', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'HTTP/1.1 200 OK\nDate: Thu, 15 Jun 2023 21:34:06 GMT\nContent-Length: 4\n\ntest', 'T_LINGER':'1', 'T_COUNT':'1'})
+test('Simple HTTP response, no length, closed connection', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'HTTP/1.1 200 OK\nDate: Thu, 15 Jun 2023 21:34:06 GMT\n\ntest', 'T_COUNT':'1'})
+test('Simple HTTP response, no length, lingering connection', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'HTTP/1.1 200 OK\nDate: Thu, 15 Jun 2023 21:34:06 GMT\n\ntest', 'T_LINGER':'1', 'T_COUNT':'0'})
+test('Chunked HTTP response, closed connection', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'HTTP/1.1 200 OK\nTransfer-Encoding: chunked\n\n1\nt\n3\nest\n0\n\n', 'T_COUNT':'1'})
+test('Chunked HTTP response, lingering connection', httpparsertest, suite: 'HTTP parser', env: {'T_HTTP':'HTTP/1.1 200 OK\nTransfer-Encoding: chunked\n\n1\nt\n3\nest\n0\n\n', 'T_LINGER':'1', 'T_COUNT':'1'})
+
+
 #abst_test = executable('abst_test', 'abst_test.cpp', dependencies: libmist_dep)
 #test('MP4::ABST Test', abst_test)