THRIFT-4621 Add THeader for Python

Client: py
diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json
index e523085..9d6d54b 100644
--- a/test/known_failures_Linux.json
+++ b/test/known_failures_Linux.json
@@ -83,6 +83,8 @@
   "cpp-py3_compact-accelc_http-ip-ssl",
   "cpp-py3_compact_http-ip",
   "cpp-py3_compact_http-ip-ssl",
+  "cpp-py3_header_http-ip",
+  "cpp-py3_header_http-ip-ssl",
   "cpp-py3_json_http-ip",
   "cpp-py3_json_http-ip-ssl",
   "cpp-py3_multi-accel_http-ip",
@@ -101,6 +103,8 @@
   "cpp-py3_multic-multiac_http-ip-ssl",
   "cpp-py3_multic_http-ip",
   "cpp-py3_multic_http-ip-ssl",
+  "cpp-py3_multih-header_http-ip",
+  "cpp-py3_multih-header_http-ip-ssl",
   "cpp-py3_multij-json_http-ip",
   "cpp-py3_multij-json_http-ip-ssl",
   "cpp-py3_multij_http-ip",
@@ -113,6 +117,8 @@
   "cpp-py_compact-accelc_http-ip-ssl",
   "cpp-py_compact_http-ip",
   "cpp-py_compact_http-ip-ssl",
+  "cpp-py_header_http-ip",
+  "cpp-py_header_http-ip-ssl",
   "cpp-py_json_http-ip",
   "cpp-py_json_http-ip-ssl",
   "cpp-py_multi-accel_http-ip",
@@ -131,6 +137,8 @@
   "cpp-py_multic-multiac_http-ip-ssl",
   "cpp-py_multic_http-ip",
   "cpp-py_multic_http-ip-ssl",
+  "cpp-py_multih-header_http-ip",
+  "cpp-py_multih-header_http-ip-ssl",
   "cpp-py_multij-json_http-ip",
   "cpp-py_multij-json_http-ip-ssl",
   "cpp-py_multij_http-ip",
@@ -375,6 +383,8 @@
   "py-cpp_binary_http-ip-ssl",
   "py-cpp_compact_http-ip",
   "py-cpp_compact_http-ip-ssl",
+  "py-cpp_header_http-ip",
+  "py-cpp_header_http-ip-ssl",
   "py-cpp_json_http-ip",
   "py-cpp_json_http-ip-ssl",
   "py-d_accel-binary_http-ip",
@@ -396,6 +406,7 @@
   "py-hs_accelc-compact_http-ip",
   "py-hs_binary_http-ip",
   "py-hs_compact_http-ip",
+  "py-hs_header_http-ip",
   "py-hs_json_http-ip",
   "py-java_accel-binary_http-ip",
   "py-java_accel-binary_http-ip-ssl",
@@ -420,6 +431,8 @@
   "py3-cpp_binary_http-ip-ssl",
   "py3-cpp_compact_http-ip",
   "py3-cpp_compact_http-ip-ssl",
+  "py3-cpp_header_http-ip",
+  "py3-cpp_header_http-ip-ssl",
   "py3-cpp_json_http-ip",
   "py3-cpp_json_http-ip-ssl",
   "py3-d_accel-binary_http-ip",
@@ -441,6 +454,7 @@
   "py3-hs_accelc-compact_http-ip",
   "py3-hs_binary_http-ip",
   "py3-hs_compact_http-ip",
+  "py3-hs_header_http-ip",
   "py3-hs_json_http-ip",
   "py3-java_accel-binary_http-ip",
   "py3-java_accel-binary_http-ip-ssl",
diff --git a/test/py/RunClientServer.py b/test/py/RunClientServer.py
index b213d1a..56a408e 100755
--- a/test/py/RunClientServer.py
+++ b/test/py/RunClientServer.py
@@ -56,6 +56,7 @@
     'binary',
     'compact',
     'json',
+    'header',
 ]
 
 
diff --git a/test/py/TestClient.py b/test/py/TestClient.py
index 2164162..ddcce8d 100755
--- a/test/py/TestClient.py
+++ b/test/py/TestClient.py
@@ -348,6 +348,12 @@
         return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService")
 
 
+class HeaderTest(MultiplexedOptionalTest):
+    def get_protocol(self, transport):
+        factory = THeaderProtocol.THeaderProtocolFactory()
+        return factory.getProtocol(transport)
+
+
 def suite():
     suite = unittest.TestSuite()
     loader = unittest.TestLoader()
@@ -359,6 +365,8 @@
         suite.addTest(loader.loadTestsFromTestCase(AcceleratedCompactTest))
     elif options.proto == 'compact':
         suite.addTest(loader.loadTestsFromTestCase(CompactTest))
+    elif options.proto == 'header':
+        suite.addTest(loader.loadTestsFromTestCase(HeaderTest))
     elif options.proto == 'json':
         suite.addTest(loader.loadTestsFromTestCase(JSONTest))
     elif options.proto == 'multi':
@@ -408,7 +416,7 @@
                       dest="verbose", const=0,
                       help="minimal output")
     parser.add_option('--protocol', dest="proto", type="string",
-                      help="protocol to use, one of: accel, accelc, binary, compact, json, multi, multia, multiac, multic, multij")
+                      help="protocol to use, one of: accel, accelc, binary, compact, header, json, multi, multia, multiac, multic, multij")
     parser.add_option('--transport', dest="trans", type="string",
                       help="transport to use, one of: buffered, framed, http")
     parser.set_defaults(framed=False, http_path=None, verbose=1, host='localhost', port=9090, proto='binary')
@@ -431,6 +439,7 @@
     from thrift.transport import TZlibTransport
     from thrift.protocol import TBinaryProtocol
     from thrift.protocol import TCompactProtocol
+    from thrift.protocol import THeaderProtocol
     from thrift.protocol import TJSONProtocol
     from thrift.protocol import TMultiplexedProtocol
 
diff --git a/test/py/TestServer.py b/test/py/TestServer.py
index 4dc4c07..aba0d42 100755
--- a/test/py/TestServer.py
+++ b/test/py/TestServer.py
@@ -181,16 +181,22 @@
 def main(options):
     # set up the protocol factory form the --protocol option
     prot_factories = {
-        'accel': TBinaryProtocol.TBinaryProtocolAcceleratedFactory,
-        'accelc': TCompactProtocol.TCompactProtocolAcceleratedFactory,
-        'binary': TBinaryProtocol.TBinaryProtocolFactory,
-        'compact': TCompactProtocol.TCompactProtocolFactory,
-        'json': TJSONProtocol.TJSONProtocolFactory
+        'accel': TBinaryProtocol.TBinaryProtocolAcceleratedFactory(),
+        'accelc': TCompactProtocol.TCompactProtocolAcceleratedFactory(),
+        'binary': TBinaryProtocol.TBinaryProtocolFactory(),
+        'compact': TCompactProtocol.TCompactProtocolFactory(),
+        'header': THeaderProtocol.THeaderProtocolFactory(allowed_client_types=[
+            THeaderTransport.THeaderClientType.HEADERS,
+            THeaderTransport.THeaderClientType.FRAMED_BINARY,
+            THeaderTransport.THeaderClientType.UNFRAMED_BINARY,
+            THeaderTransport.THeaderClientType.FRAMED_COMPACT,
+            THeaderTransport.THeaderClientType.UNFRAMED_COMPACT,
+        ]),
+        'json': TJSONProtocol.TJSONProtocolFactory(),
     }
-    pfactory_cls = prot_factories.get(options.proto, None)
-    if pfactory_cls is None:
+    pfactory = prot_factories.get(options.proto, None)
+    if pfactory is None:
         raise AssertionError('Unknown --protocol option: %s' % options.proto)
-    pfactory = pfactory_cls()
     try:
         pfactory.string_length_limit = options.string_limit
         pfactory.container_length_limit = options.container_limit
@@ -323,11 +329,13 @@
     from ThriftTest import ThriftTest
     from ThriftTest.ttypes import Xtruct, Xception, Xception2, Insanity
     from thrift.Thrift import TException
+    from thrift.transport import THeaderTransport
     from thrift.transport import TTransport
     from thrift.transport import TSocket
     from thrift.transport import TZlibTransport
     from thrift.protocol import TBinaryProtocol
     from thrift.protocol import TCompactProtocol
+    from thrift.protocol import THeaderProtocol
     from thrift.protocol import TJSONProtocol
     from thrift.server import TServer, TNonblockingServer, THttpServer
 
diff --git a/test/tests.json b/test/tests.json
index 72790ac..85a0c07 100644
--- a/test/tests.json
+++ b/test/tests.json
@@ -273,7 +273,8 @@
       "binary",
       "json",
       "binary:accel",
-      "compact:accelc"
+      "compact:accelc",
+      "header"
     ],
     "workdir": "py"
   },
@@ -319,7 +320,8 @@
       "binary",
       "json",
       "binary:accel",
-      "compact:accelc"
+      "compact:accelc",
+      "header"
     ],
     "workdir": "py"
   },