You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@reef.apache.org by se...@apache.org on 2015/03/11 02:15:25 UTC

incubator-reef git commit: [REEF-193] serialize http header info with HttpRequest

Repository: incubator-reef
Updated Branches:
  refs/heads/master 76d101014 -> 64f7e0a03


[REEF-193] serialize http header info with HttpRequest

This PR is to add http header data cross the bridge
* Update http request schema to add header entry
* Update AvroHttpSerializer at java side for the change
* Updated ParsedHttpRequest to return the header info
* Update test java cases
* Updated AvroHttpSerializer as C# side
* Added test  project for Common.Tests
* Added unit tests cases for http serializer in C#

JIRA: Reef-193. (https://issues.apache.org/jira/browse/REEF-193)

Author: Julia Wang  Email: jwang98052@yahoo.com


Project: http://git-wip-us.apache.org/repos/asf/incubator-reef/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-reef/commit/64f7e0a0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-reef/tree/64f7e0a0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-reef/diff/64f7e0a0

Branch: refs/heads/master
Commit: 64f7e0a036e011b240d5e256537fe8eb362c1f0c
Parents: 76d1010
Author: Julia Wang <jw...@yahoo.com>
Authored: Mon Mar 9 12:38:28 2015 -0700
Committer: Julia Wang <jw...@yahoo.com>
Committed: Tue Mar 10 17:51:47 2015 -0700

----------------------------------------------------------------------
 lang/cs/.gitignore                              |   1 +
 .../Org.Apache.REEF.Common.Tests.csproj         |  75 ++++++++++
 .../Properties/AssemblyInfo.cs                  |  55 ++++++++
 .../TestHttpSerialization.cs                    |  96 +++++++++++++
 .../Avro/AvroHttpRequest.cs                     |  43 +++---
 .../Avro/AvroHttpSerializer.cs                  |  77 ++++++++++
 .../Org.Apache.REEF.Common/Avro/HeaderEntry.cs  |  58 ++++++++
 .../Org.Apache.REEF.Common.csproj               |   1 +
 .../Bridge/HttpServerHandler.cs                 |  24 +++-
 .../Bridge/ReefHttpRequest.cs                   |   4 +
 ...bridge-0.11.0-incubating-SNAPSHOT-shaded.jar | Bin 12937817 -> 12748678 bytes
 lang/cs/Org.Apache.REEF.sln                     |   8 ++
 .../reef/javabridge/generic/JobDriver.java      |   5 +-
 .../src/main/avro/webRequest.avsc               |  73 ++++++----
 .../reef/webserver/AvroHttpSerializer.java      |  36 +++++
 .../reef/webserver/ParsedHttpRequest.java       |  20 +++
 .../reef/webserver/TestAvroHttpSerializer.java  | 139 ++++++++++++++++++-
 17 files changed, 659 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/.gitignore
----------------------------------------------------------------------
diff --git a/lang/cs/.gitignore b/lang/cs/.gitignore
index 3da4cf8..cea2523 100644
--- a/lang/cs/.gitignore
+++ b/lang/cs/.gitignore
@@ -8,5 +8,6 @@ TestResults
 **/obj
 **/.nuget/nuspec
 **/.nuget/packages
+*.sln.GhostDoc.xml
 
 

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.Common.Tests/Org.Apache.REEF.Common.Tests.csproj
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common.Tests/Org.Apache.REEF.Common.Tests.csproj b/lang/cs/Org.Apache.REEF.Common.Tests/Org.Apache.REEF.Common.Tests.csproj
new file mode 100644
index 0000000..cfab7bc
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/Org.Apache.REEF.Common.Tests.csproj
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{F1A3495C-2CBD-4F3B-AEDC-9C1A43D9F238}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Org.Apache.REEF.Common.Tests</RootNamespace>
+    <AssemblyName>Org.Apache.REEF.Common.Tests</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..</SolutionDir>
+    <RestorePackages>true</RestorePackages>
+  </PropertyGroup>
+  <Import Project="$(SolutionDir)\build.props" />
+  <PropertyGroup>
+    <BuildPackage>false</BuildPackage>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="TestHttpSerialization.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\Org.Apache.REEF.Common\Org.Apache.REEF.Common.csproj">
+      <Project>{545a0582-4105-44ce-b99c-b1379514a630}</Project>
+      <Name>Org.Apache.REEF.Common</Name>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\Org.Apache.REEF.Utilities\Org.Apache.REEF.Utilities.csproj">
+      <Project>{79e7f89a-1dfb-45e1-8d43-d71a954aeb98}</Project>
+      <Name>Org.Apache.REEF.Utilities</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.Common.Tests/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common.Tests/Properties/AssemblyInfo.cs b/lang/cs/Org.Apache.REEF.Common.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..691b596
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Org.Apache.REEF.Common.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Org.Apache.REEF.Common.Tests")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("56634b2e-ff34-4c06-99f4-3c1388093e59")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.Common.Tests/TestHttpSerialization.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common.Tests/TestHttpSerialization.cs b/lang/cs/Org.Apache.REEF.Common.Tests/TestHttpSerialization.cs
new file mode 100644
index 0000000..de2cffd
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/TestHttpSerialization.cs
@@ -0,0 +1,96 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System.Collections.Generic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Org.Apache.REEF.Common.Avro;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+
+namespace Org.Apache.REEF.Common.Tests
+{
+    /// <summary>
+    /// Class TestHttpSerialization. This class contains unit tests for HttpRequest serailization and deserialization.
+    /// </summary>
+    [TestClass]
+    public class TestHttpSerialization
+    {
+        private static readonly Logger LOGGER = Logger.GetLogger(typeof(TestHttpSerialization));
+
+        /// <summary>
+        /// Tests the HTTP request serialization jason round trip.
+        /// </summary>
+        [TestMethod]
+        public void TestHttpRequestSerializationJasonRoundTrip()
+        {
+            AvroHttpRequest r = CreatAvorHttpRequest();
+
+            string str = AvroHttpSerializer.ToJson(r);
+            byte[] bytes = ByteUtilities.StringToByteArrays(str);
+            var r1 = AvroHttpSerializer.FromBytesWithJoson(bytes);
+
+            var ri = ByteUtilities.ByteArrarysToString(r.InputStream);
+            var ri1 = ByteUtilities.ByteArrarysToString(r1.InputStream);
+            Assert.AreEqual(ri, ri1);
+            Assert.AreEqual(r.QueryString, r1.QueryString);
+        }
+
+        /// <summary>
+        /// Tests the HTTP request serialization round trip.
+        /// </summary>
+        [TestMethod]
+        public void TestHttpRequestSerializationBytesRoundTrip()
+        {
+            AvroHttpRequest r = CreatAvorHttpRequest();
+
+            var b = AvroHttpSerializer.ToBytes(r);
+            var r1 = AvroHttpSerializer.FromBytes(b);
+
+            var ri = ByteUtilities.ByteArrarysToString(r.InputStream);
+            var ri1 = ByteUtilities.ByteArrarysToString(r1.InputStream);
+            Assert.AreEqual(ri, ri1);
+            Assert.AreEqual(r.QueryString, r1.QueryString);
+        }
+
+        /// <summary>
+        /// Creats an Avor HTTP request for unit tests.
+        /// </summary>
+        /// <returns>AvroHttpRequest.</returns>
+        private AvroHttpRequest CreatAvorHttpRequest()
+        {
+            AvroHttpRequest r = new AvroHttpRequest();
+            r.Header = new List<HeaderEntry>();
+            HeaderEntry he1 = new HeaderEntry();
+            he1.key = "a";
+            he1.value = "xxx";
+            HeaderEntry he2 = new HeaderEntry();
+            he2.key = "b";
+            he2.value = "yyy";
+            r.Header.Add(he1);
+            r.Header.Add(he2);
+
+            r.HttpMethod = "POST";
+            r.InputStream = ByteUtilities.StringToByteArrays("test binary stream data");
+            r.PathInfo = "/reef/evaluators";
+            r.QueryString = "id=12&id=34&a=b";
+            r.RequestUrl = "http://localhost:8080/reef/evaluators?id=12&id=34&a=b";
+            return r;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.Common/Avro/AvroHttpRequest.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/Avro/AvroHttpRequest.cs b/lang/cs/Org.Apache.REEF.Common/Avro/AvroHttpRequest.cs
index 29b9ef7..182992e 100644
--- a/lang/cs/Org.Apache.REEF.Common/Avro/AvroHttpRequest.cs
+++ b/lang/cs/Org.Apache.REEF.Common/Avro/AvroHttpRequest.cs
@@ -1,16 +1,19 @@
 //<auto-generated />
-
-using System.Runtime.Serialization;
-
 namespace Org.Apache.REEF.Common.Avro
 {
+    using System;
+    using System.Collections.Generic;
+    using System.Runtime.Serialization;
+    using Microsoft.Hadoop.Avro;
+
     /// <summary>
     /// Used to serialize and deserialize Avro record org.apache.reef.webserver.AvroHttpRequest.
     /// </summary>
     [DataContract(Namespace = "org.apache.reef.webserver")]
+    [KnownType(typeof(List<Org.Apache.REEF.Common.Avro.HeaderEntry>))]
     public partial class AvroHttpRequest
     {
-        private const string JsonSchema = @"{""type"":""record"",""name"":""org.apache.reef.webserver.AvroHttpRequest"",""fields"":[{""name"":""requestUrl"",""type"":""string""},{""name"":""pathInfo"",""type"":""string""},{""name"":""queryString"",""type"":""string""},{""name"":""httpMethod"",""type"":""string""},{""name"":""inputStream"",""type"":""bytes""}]}";
+        private const string JsonSchema = @"{""type"":""record"",""name"":""org.apache.reef.webserver.AvroHttpRequest"",""fields"":[{""name"":""header"",""type"":{""type"":""array"",""items"":{""type"":""record"",""name"":""org.apache.reef.webserver.HeaderEntry"",""fields"":[{""name"":""key"",""type"":""string""},{""name"":""value"",""type"":""string""}]}}},{""name"":""requestUrl"",""type"":""string""},{""name"":""pathInfo"",""type"":""string""},{""name"":""queryString"",""type"":""string""},{""name"":""httpMethod"",""type"":""string""},{""name"":""inputStream"",""type"":""bytes""}]}";
 
         /// <summary>
         /// Gets the schema.
@@ -22,37 +25,43 @@ namespace Org.Apache.REEF.Common.Avro
                 return JsonSchema;
             }
         }
-
+      
+        /// <summary>
+        /// Gets or sets the header field.
+        /// </summary>
+        [DataMember]
+        public List<Org.Apache.REEF.Common.Avro.HeaderEntry> Header { get; set; }
+              
         /// <summary>
         /// Gets or sets the requestUrl field.
         /// </summary>
         [DataMember]
         public string RequestUrl { get; set; }
-
+              
         /// <summary>
         /// Gets or sets the pathInfo field.
         /// </summary>
         [DataMember]
         public string PathInfo { get; set; }
-
+              
         /// <summary>
         /// Gets or sets the queryString field.
         /// </summary>
         [DataMember]
         public string QueryString { get; set; }
-
+              
         /// <summary>
         /// Gets or sets the httpMethod field.
         /// </summary>
         [DataMember]
         public string HttpMethod { get; set; }
-
+              
         /// <summary>
         /// Gets or sets the inputStream field.
         /// </summary>
         [DataMember]
         public byte[] InputStream { get; set; }
-
+                
         /// <summary>
         /// Initializes a new instance of the <see cref="AvroHttpRequest"/> class.
         /// </summary>
@@ -63,18 +72,20 @@ namespace Org.Apache.REEF.Common.Avro
         /// <summary>
         /// Initializes a new instance of the <see cref="AvroHttpRequest"/> class.
         /// </summary>
+        /// <param name="header">The header.</param>
         /// <param name="requestUrl">The requestUrl.</param>
         /// <param name="pathInfo">The pathInfo.</param>
         /// <param name="queryString">The queryString.</param>
         /// <param name="httpMethod">The httpMethod.</param>
         /// <param name="inputStream">The inputStream.</param>
-        public AvroHttpRequest(string requestUrl, string pathInfo, string queryString, string httpMethod, byte[] inputStream)
+        public AvroHttpRequest(List<Org.Apache.REEF.Common.Avro.HeaderEntry> header, string requestUrl, string pathInfo, string queryString, string httpMethod, byte[] inputStream)
         {
-            RequestUrl = requestUrl;
-            PathInfo = pathInfo;
-            QueryString = queryString;
-            HttpMethod = httpMethod;
-            InputStream = inputStream;
+            this.Header = header;
+            this.RequestUrl = requestUrl;
+            this.PathInfo = pathInfo;
+            this.QueryString = queryString;
+            this.HttpMethod = httpMethod;
+            this.InputStream = inputStream;
         }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.Common/Avro/AvroHttpSerializer.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/Avro/AvroHttpSerializer.cs b/lang/cs/Org.Apache.REEF.Common/Avro/AvroHttpSerializer.cs
index 5a57a5b..6b936f7 100644
--- a/lang/cs/Org.Apache.REEF.Common/Avro/AvroHttpSerializer.cs
+++ b/lang/cs/Org.Apache.REEF.Common/Avro/AvroHttpSerializer.cs
@@ -19,9 +19,14 @@
 
 using System.IO;
 using Microsoft.Hadoop.Avro;
+using Newtonsoft.Json;
+using Org.Apache.REEF.Utilities;
 
 namespace Org.Apache.REEF.Common.Avro
 {
+    /// <summary>
+    /// Class AvroHttpSerializer. Provides methods to serialize and deserialize HttpRequest
+    /// </summary>
     public class AvroHttpSerializer
     {
         public static AvroHttpRequest FromBytes(byte[] serializedBytes)
@@ -32,5 +37,77 @@ namespace Org.Apache.REEF.Common.Avro
                 return serializer.Deserialize(stream);
             }
         }
+
+        /// <summary>
+        /// Conver bytes which contains Json string into AvroHttpRequest object
+        /// </summary>
+        /// <param name="serializedBytes">The serialized bytes.</param>
+        /// <returns>AvroHttpRequest.</returns>
+        public static AvroHttpRequest FromBytesWithJoson(byte[] serializedBytes)
+        {
+            string s = ByteUtilities.ByteArrarysToString(serializedBytes);
+            return FromJson(s);
+        }
+
+        /// <summary>
+        /// Convert from Json string into AvroHttpRequest object
+        /// </summary>
+        /// <param name="josonString">The joson string.</param>
+        /// <returns>AvroHttpRequest.</returns>
+        public static AvroHttpRequest FromJson(string josonString)
+        {
+           return JsonConvert.DeserializeObject<AvroHttpRequest>(josonString);
+        }
+
+        /// <summary>
+        /// Convert from AvroHttpRequest to Json string
+        /// </summary>
+        /// <param name="httpRequest">The HTTP request.</param>
+        /// <returns>System.String.</returns>
+        public static string ToJson(AvroHttpRequest httpRequest)
+        {
+            return JsonConvert.SerializeObject(httpRequest);
+        }
+
+        /// <summary>
+        /// Serialize AvroHttpRequest object into bytes
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <returns>System.Byte[].</returns>
+        public static byte[] ToBytes(AvroHttpRequest obj)
+        {
+            var serializer = AvroSerializer.Create<AvroHttpRequest>();
+            using (MemoryStream stream = new MemoryStream())
+            {
+                serializer.Serialize(stream, obj);
+                return stream.GetBuffer();
+            }
+        }
+
+        /// <summary>
+        /// Deserialize from file to AvroHttpRequest object.
+        /// </summary>
+        /// <param name="fileName">Name of the file.</param>
+        /// <returns>AvroHttpRequest.</returns>
+        public static AvroHttpRequest FromFile(string fileName)
+        {
+            var str = File.ReadAllText(fileName);
+            AvroHttpRequest avroHttprequest = JsonConvert.DeserializeObject<AvroHttpRequest>(str);
+            return avroHttprequest;
+        }
+
+        /// <summary>
+        /// Serialize AvroHttpRequest in to file
+        /// </summary>
+        /// <param name="avroHttprequest">The avro httprequest.</param>
+        /// <param name="fileName">Name of the file.</param>
+        public static void ToFile(AvroHttpRequest avroHttprequest, string fileName)
+        {
+            var bytes = ToBytes(avroHttprequest);
+            using (var file = File.OpenWrite(fileName))
+            {
+                file.Write(bytes,0,bytes.Length);
+            }
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.Common/Avro/HeaderEntry.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/Avro/HeaderEntry.cs b/lang/cs/Org.Apache.REEF.Common/Avro/HeaderEntry.cs
new file mode 100644
index 0000000..6645f32
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/Avro/HeaderEntry.cs
@@ -0,0 +1,58 @@
+//<auto-generated />
+namespace Org.Apache.REEF.Common.Avro
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Runtime.Serialization;
+    using Microsoft.Hadoop.Avro;
+
+    /// <summary>
+    /// Used to serialize and deserialize Avro record org.apache.reef.webserver.HeaderEntry.
+    /// </summary>
+    [DataContract(Namespace = "org.apache.reef.webserver")]
+    public partial class HeaderEntry
+    {
+        private const string JsonSchema = @"{""type"":""record"",""name"":""org.apache.reef.webserver.HeaderEntry"",""fields"":[{""name"":""key"",""type"":""string""},{""name"":""value"",""type"":""string""}]}";
+
+        /// <summary>
+        /// Gets the schema.
+        /// </summary>
+        public static string Schema
+        {
+            get
+            {
+                return JsonSchema;
+            }
+        }
+      
+        /// <summary>
+        /// Gets or sets the key field.
+        /// </summary>
+        [DataMember]
+        public string key { get; set; }
+              
+        /// <summary>
+        /// Gets or sets the value field.
+        /// </summary>
+        [DataMember]
+        public string value { get; set; }
+                
+        /// <summary>
+        /// Initializes a new instance of the <see cref="HeaderEntry"/> class.
+        /// </summary>
+        public HeaderEntry()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="HeaderEntry"/> class.
+        /// </summary>
+        /// <param name="key">The key.</param>
+        /// <param name="value">The value.</param>
+        public HeaderEntry(string key, string value)
+        {
+            this.key = key;
+            this.value = value;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj b/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
index b531904..9cb5b72 100644
--- a/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
+++ b/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
@@ -64,6 +64,7 @@ under the License.
     <Compile Include="Avro\AvroHttpSerializer.cs" />
     <Compile Include="Avro\AvroJsonSerializer.cs" />
     <Compile Include="Avro\AvroReefServiceInfo.cs" />
+    <Compile Include="Avro\HeaderEntry.cs" />
     <Compile Include="Catalog\Capabilities\CPU.cs" />
     <Compile Include="Catalog\Capabilities\ICapability.cs" />
     <Compile Include="Catalog\Capabilities\RAM.cs" />

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.Driver/Bridge/HttpServerHandler.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Driver/Bridge/HttpServerHandler.cs b/lang/cs/Org.Apache.REEF.Driver/Bridge/HttpServerHandler.cs
index 7d56f82..c3b6cae 100644
--- a/lang/cs/Org.Apache.REEF.Driver/Bridge/HttpServerHandler.cs
+++ b/lang/cs/Org.Apache.REEF.Driver/Bridge/HttpServerHandler.cs
@@ -66,7 +66,7 @@ namespace Org.Apache.REEF.Driver.Bridge
         }
 
         /// <summary>
-        /// Called when receving an http request from Java side
+        /// Called when receiving an http request from Java side
         /// </summary>
         /// <param name="httpMessage">The HTTP message.</param>
         public void OnNext(IHttpMessage httpMessage)
@@ -84,15 +84,20 @@ namespace Org.Apache.REEF.Driver.Bridge
             else
             {
                 LOGGER.Log(Level.Info, "HttpHandler OnNext, handling http request.");
-                byte[] byteData = httpMessage.GetQueryReuestData();                    
-                AvroHttpRequest avroHttpRequest = AvroHttpSerializer.FromBytes(byteData);
-                LOGGER.Log(Level.Info, "HttpHandler OnNext, requestData:" + avroHttpRequest);
+                byte[] byteData = httpMessage.GetQueryReuestData();
+                AvroHttpRequest avroHttpRequest = AvroHttpSerializer.FromBytesWithJoson(byteData);
+                LOGGER.Log(Level.Info, string.Format(CultureInfo.CurrentCulture, "HttpHandler OnNext, requestData:", avroHttpRequest));
 
                 string spec = GetSpecification(avroHttpRequest.PathInfo);
                 if (spec != null)
                 {
                     LOGGER.Log(Level.Info, "HttpHandler OnNext, target:" + spec);
                     ReefHttpRequest request = ToHttpRequest(avroHttpRequest);
+
+                    foreach (var h in request.Header)
+                    {
+                        LOGGER.Log(Level.Info, string.Format(CultureInfo.CurrentCulture, "HttpRequest Header-key: {0}, value: {1}.", h.Key, h.Value));
+                    }
                     ReefHttpResponse response = new ReefHttpResponse();
 
                     IHttpHandler handler;
@@ -108,9 +113,7 @@ namespace Org.Apache.REEF.Driver.Bridge
                     else
                     {
                         responseData =
-                            ByteUtilities.StringToByteArrays(string.Format(CultureInfo.CurrentCulture,
-                                                                           "No event handler found at CLR side for {0}.",
-                                                                           spec));
+                            ByteUtilities.StringToByteArrays(string.Format(CultureInfo.CurrentCulture, "No event handler found at CLR side for {0}.", spec));
                     }
                     httpMessage.SetQueryResponseData(responseData);
                 }
@@ -154,6 +157,13 @@ namespace Org.Apache.REEF.Driver.Bridge
             httpRequest.Url = avroRequest.RequestUrl;
             httpRequest.Querystring = avroRequest.QueryString;
 
+            IDictionary<string, string> header = new Dictionary<string, string>();
+            foreach (var h in avroRequest.Header)
+            {
+                header.Add(h.key, h.value);
+            }
+            httpRequest.Header = header;
+
             HttpMethod m;
             HttpMethod.TryParse(avroRequest.HttpMethod, true, out m);
             httpRequest.Method = m;

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.Driver/Bridge/ReefHttpRequest.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Driver/Bridge/ReefHttpRequest.cs b/lang/cs/Org.Apache.REEF.Driver/Bridge/ReefHttpRequest.cs
index 97c0465..478e887 100644
--- a/lang/cs/Org.Apache.REEF.Driver/Bridge/ReefHttpRequest.cs
+++ b/lang/cs/Org.Apache.REEF.Driver/Bridge/ReefHttpRequest.cs
@@ -17,6 +17,8 @@
  * under the License.
  */
 
+using System.Collections;
+using System.Collections.Generic;
 using System.Globalization;
 
 namespace Org.Apache.REEF.Driver.Bridge
@@ -41,6 +43,8 @@ namespace Org.Apache.REEF.Driver.Bridge
 
         public string PathInfo { get; set; }
 
+        public IDictionary<string, string> Header { get; set; }
+
         public string Tostring()
         {
             return string.Format(CultureInfo.InvariantCulture, "Url: {0}, query string {1}", Url, Querystring);

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.Tests/bin/reef-bridge-0.11.0-incubating-SNAPSHOT-shaded.jar
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Tests/bin/reef-bridge-0.11.0-incubating-SNAPSHOT-shaded.jar b/lang/cs/Org.Apache.REEF.Tests/bin/reef-bridge-0.11.0-incubating-SNAPSHOT-shaded.jar
index 72fbf13..c4a6fc7 100644
Binary files a/lang/cs/Org.Apache.REEF.Tests/bin/reef-bridge-0.11.0-incubating-SNAPSHOT-shaded.jar and b/lang/cs/Org.Apache.REEF.Tests/bin/reef-bridge-0.11.0-incubating-SNAPSHOT-shaded.jar differ

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/cs/Org.Apache.REEF.sln
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.sln b/lang/cs/Org.Apache.REEF.sln
index cdd8778..d0c3d00 100644
--- a/lang/cs/Org.Apache.REEF.sln
+++ b/lang/cs/Org.Apache.REEF.sln
@@ -40,6 +40,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Org.Apache.REEF.All", "Org.
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Org.Apache.REEF.Examples", "Org.Apache.REEF.Examples\Org.Apache.REEF.Examples.csproj", "{75503F90-7B82-4762-9997-94B5C68F15DB}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Org.Apache.REEF.Common.Tests", "Org.Apache.REEF.Common.Tests\Org.Apache.REEF.Common.Tests.csproj", "{F1A3495C-2CBD-4F3B-AEDC-9C1A43D9F238}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -168,6 +170,12 @@ Global
 		{75503F90-7B82-4762-9997-94B5C68F15DB}.Release|Any CPU.Build.0 = Release|Any CPU
 		{75503F90-7B82-4762-9997-94B5C68F15DB}.Release|x64.ActiveCfg = Release|x64
 		{75503F90-7B82-4762-9997-94B5C68F15DB}.Release|x64.Build.0 = Release|x64
+		{F1A3495C-2CBD-4F3B-AEDC-9C1A43D9F238}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{F1A3495C-2CBD-4F3B-AEDC-9C1A43D9F238}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F1A3495C-2CBD-4F3B-AEDC-9C1A43D9F238}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{F1A3495C-2CBD-4F3B-AEDC-9C1A43D9F238}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{F1A3495C-2CBD-4F3B-AEDC-9C1A43D9F238}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F1A3495C-2CBD-4F3B-AEDC-9C1A43D9F238}.Release|x64.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/java/reef-bridge-java/src/main/java/org/apache/reef/javabridge/generic/JobDriver.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-bridge-java/src/main/java/org/apache/reef/javabridge/generic/JobDriver.java b/lang/java/reef-bridge-java/src/main/java/org/apache/reef/javabridge/generic/JobDriver.java
index b2e0083..228743b 100644
--- a/lang/java/reef-bridge-java/src/main/java/org/apache/reef/javabridge/generic/JobDriver.java
+++ b/lang/java/reef-bridge-java/src/main/java/org/apache/reef/javabridge/generic/JobDriver.java
@@ -406,7 +406,10 @@ public final class JobDriver {
       try (final LoggingScope ls = loggingScopeFactory.httpRequest(parsedHttpRequest.getRequestUri())) {
         final AvroHttpSerializer httpSerializer = new AvroHttpSerializer();
         final AvroHttpRequest avroHttpRequest = httpSerializer.toAvro(parsedHttpRequest);
-        final byte[] requestBytes = httpSerializer.toBytes(avroHttpRequest);
+
+        final String requestString = httpSerializer.toString(avroHttpRequest);
+        final byte[] requestBytes = requestString.getBytes();
+        //final byte[] requestBytes = httpSerializer.toBytes(avroHttpRequest);
 
         try {
           final HttpServerEventBridge httpServerEventBridge = new HttpServerEventBridge(requestBytes);

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/java/reef-webserver/src/main/avro/webRequest.avsc
----------------------------------------------------------------------
diff --git a/lang/java/reef-webserver/src/main/avro/webRequest.avsc b/lang/java/reef-webserver/src/main/avro/webRequest.avsc
index 0cf0abc..ec2520c 100644
--- a/lang/java/reef-webserver/src/main/avro/webRequest.avsc
+++ b/lang/java/reef-webserver/src/main/avro/webRequest.avsc
@@ -1,29 +1,46 @@
 /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- {"namespace": "org.apache.reef.webserver",
- "type": "record",
- "name": "AvroHttpRequest",
- "fields": [
-     {"name": "requestUrl", "type": "string"},
-     {"name": "pathInfo", "type": "string"},
-     {"name": "queryString", "type": "string"},
-     {"name": "httpMethod", "type": "string"},
-     {"name": "inputStream", "type": "bytes"}
- ]
-}
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+[
+  {
+    "namespace": "org.apache.reef.webserver",
+    "type": "record",
+    "name": "HeaderEntry",
+    "fields": [
+       { "name": "key", "type": "string" },
+       { "name": "value", "type": "string" }
+    ]
+  },
+  {
+    "namespace": "org.apache.reef.webserver",
+    "type": "record",
+    "name": "AvroHttpRequest",
+    "fields": [
+      {
+         "name": "header",
+         "type": { "type": "array", "items": "HeaderEntry" }
+       },
+       {"name": "requestUrl", "type": "string"},
+       {"name": "pathInfo", "type": "string"},
+       {"name": "queryString", "type": "string"},
+       {"name": "httpMethod", "type": "string"},
+       {"name": "inputStream", "type": "bytes"}
+    ]
+  }
+]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/AvroHttpSerializer.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/AvroHttpSerializer.java b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/AvroHttpSerializer.java
index 18c64f7..f3fe9d9 100644
--- a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/AvroHttpSerializer.java
+++ b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/AvroHttpSerializer.java
@@ -18,14 +18,18 @@
  */
 package org.apache.reef.webserver;
 
+import org.apache.avro.file.DataFileReader;
+import org.apache.avro.file.DataFileWriter;
 import org.apache.avro.io.*;
 import org.apache.avro.specific.SpecificDatumReader;
 import org.apache.avro.specific.SpecificDatumWriter;
 
 import javax.servlet.ServletException;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.*;
 
 /**
  * Serialize Http Request Response data with Avro.
@@ -41,12 +45,14 @@ public class AvroHttpSerializer {
    * Convert from HttpServletRequest to AvroHttpRequest.
    */
   public AvroHttpRequest toAvro(final ParsedHttpRequest parsedRequest) throws ServletException, IOException {
+
     return AvroHttpRequest.newBuilder()
         .setRequestUrl(parsedRequest.getRequestUrl())
         .setHttpMethod(parsedRequest.getMethod())
         .setQueryString(parsedRequest.getQueryString())
         .setPathInfo(parsedRequest.getPathInfo())
         .setInputStream(ByteBuffer.wrap(parsedRequest.getInputStream()))
+        .setHeader(parsedRequest.getHeaderEntryList())
         .build();
   }
 
@@ -81,6 +87,36 @@ public class AvroHttpSerializer {
   }
 
   /**
+   * Conver AvroHttpRequest to a file
+   * @param avroHttpRequest
+   * @param file
+   * @throws IOException
+   * @throws ServletException
+   */
+  public void toFile(final AvroHttpRequest avroHttpRequest, final File file) throws IOException, ServletException {
+    final DatumWriter<AvroHttpRequest> httpWriter = new SpecificDatumWriter<>(AvroHttpRequest.class);
+    try (final DataFileWriter<AvroHttpRequest> dataFileWriter = new DataFileWriter<>(httpWriter)) {
+      dataFileWriter.create(avroHttpRequest.getSchema(), file);
+      dataFileWriter.append(avroHttpRequest);
+    }
+  }
+
+  /**
+   * Convert a file to AvroHttpRequest
+   * @param file
+   * @return
+   * @throws IOException
+   */
+  public AvroHttpRequest fromFile(final File file) throws IOException {
+    final AvroHttpRequest avrohttpRequest;
+    try (final DataFileReader<AvroHttpRequest> dataFileReader =
+                 new DataFileReader<>(file, new SpecificDatumReader<>(AvroHttpRequest.class))) {
+      avrohttpRequest = dataFileReader.next();
+    }
+    return avrohttpRequest;
+  }
+
+  /**
    * Convert JSON String to AvroHttpRequest.
    */
   public AvroHttpRequest fromString(final String jasonStr) {

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/ParsedHttpRequest.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/ParsedHttpRequest.java b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/ParsedHttpRequest.java
index ccf2a85..55138bf 100644
--- a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/ParsedHttpRequest.java
+++ b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/ParsedHttpRequest.java
@@ -94,6 +94,26 @@ public final class ParsedHttpRequest {
   }
 
   /**
+   * get http header as a list of HeaderEntry
+   * @return
+   */
+  public List<HeaderEntry> getHeaderEntryList() {
+    final List<HeaderEntry> list = new ArrayList<HeaderEntry>();
+    final Iterator it = this.headers.entrySet().iterator();
+    while (it.hasNext()) {
+      final Map.Entry pair = (Map.Entry)it.next();
+      System.out.println(pair.getKey() + " = " + pair.getValue());
+      final HeaderEntry e = HeaderEntry.newBuilder()
+              .setKey((String) pair.getKey())
+              .setValue((String) pair.getValue())
+              .build();
+      list.add(e);
+      it.remove(); // avoids a ConcurrentModificationException
+    }
+    return list;
+  }
+
+  /**
    * get target to match specification like "Reef"
    *
    * @return specification

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/64f7e0a0/lang/java/reef-webserver/src/test/java/org/apache/reef/webserver/TestAvroHttpSerializer.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-webserver/src/test/java/org/apache/reef/webserver/TestAvroHttpSerializer.java b/lang/java/reef-webserver/src/test/java/org/apache/reef/webserver/TestAvroHttpSerializer.java
index 2ca0683..e85f9a7 100644
--- a/lang/java/reef-webserver/src/test/java/org/apache/reef/webserver/TestAvroHttpSerializer.java
+++ b/lang/java/reef-webserver/src/test/java/org/apache/reef/webserver/TestAvroHttpSerializer.java
@@ -25,8 +25,11 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 
+import javax.servlet.ServletException;
+import java.io.*;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
+import java.util.ArrayList;
 
 /**
  * Test Avro Http Serializer
@@ -37,6 +40,20 @@ public final class TestAvroHttpSerializer {
   private AvroHttpRequest avroRequest;
   private AvroHttpSerializer avroHttpSerializer;
 
+  public static String readStream(InputStream is) {
+    final StringBuilder sb = new StringBuilder(512);
+    try {
+      final Reader r = new InputStreamReader(is, "UTF-8");
+      int c = 0;
+      while ((c = r.read()) != -1) {
+        sb.append((char) c);
+      }
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+    return sb.toString();
+  }
+
   @Before
   public void setUp() throws Exception {
     final String s = "test binary stream data";
@@ -47,10 +64,81 @@ public final class TestAvroHttpSerializer {
         .setQueryString("id=12&id=34&a=b")
         .setPathInfo("/reef/evaluators")
         .setInputStream(ByteBuffer.wrap(b))
+        .setHeader(createHeader())
         .build();
     avroHttpSerializer = new AvroHttpSerializer();
   }
 
+  /**
+   * Test serialize to file then deserialize from file
+   * @throws IOException
+   * @throws ServletException
+   */
+  @Test
+  public void testFileRoundTrip() throws IOException, ServletException {
+    final File f = new File("httpRequestData.bin");
+    avroHttpSerializer.toFile(avroRequest, f);
+    final AvroHttpRequest avroRequest2 = avroHttpSerializer.fromFile(f);
+    f.delete();
+    assertEqual(avroRequest, avroRequest2);
+  }
+
+
+  /**
+   * Test serialize to bytes, then write to file, then read from file, finally deserialize
+   * @throws IOException
+   * @throws ServletException
+   */
+  @Test
+  public void testFile1RoundTrip() throws IOException, ServletException {
+    final byte[] bytes = avroHttpSerializer.toBytes(avroRequest);
+    final File f = new File("httpRequestData.bin");
+    final OutputStream os = new FileOutputStream(f);
+    os.write(bytes, 0, bytes.length);
+    os.close();
+
+    //final File f = new File("httpRequestData.bin");
+    final byte[] bytes1 = new byte[(int) f.length()];
+    final InputStream is = new FileInputStream("httpRequestData.bin");
+    is.read(bytes1, 0, bytes1.length);
+
+    is.close();
+    f.delete();
+    final AvroHttpRequest deserializedRequest = avroHttpSerializer.fromBytes(bytes1);
+
+    assertEqual(avroRequest, deserializedRequest);
+  }
+
+  /**
+   * Test serialize to string, then write to file, then read from file, finally deserialize
+   * @throws IOException
+   * @throws ServletException
+   */
+  @Test
+  public void testFile2RoundTrip() throws IOException, ServletException {
+    final String serializedString = avroHttpSerializer.toString(avroRequest);
+
+    final File f = new File("httpRequestData.txt");
+    final OutputStream os = new FileOutputStream(f);//"httpRequestData.txt");
+    final OutputStreamWriter sw = new OutputStreamWriter(os);
+    sw.write(serializedString);
+    sw.flush();
+    sw.close();
+    os.close();
+
+    final InputStream is = new FileInputStream(f);
+    final String all = readStream(is);
+    is.close();
+    f.delete();
+
+    final AvroHttpRequest deserializedRequest = avroHttpSerializer.fromString(all);
+
+    assertEqual(avroRequest, deserializedRequest);
+  }
+
+  /**
+   * Test serialize to JSon string, the deserialize from it
+   */
   @Test
   public void testJSonsStringRoundTrip() {
     final String serializedString = avroHttpSerializer.toString(avroRequest);
@@ -58,6 +146,9 @@ public final class TestAvroHttpSerializer {
     assertEqual(avroRequest, deserializedRequest);
   }
 
+  /**
+   * Test serialize to bytes, the deserialize from it
+   */
   @Test
   public void testBytesRoundTrip() {
     final byte[] serializedBytes = avroHttpSerializer.toBytes(avroRequest);
@@ -73,25 +164,31 @@ public final class TestAvroHttpSerializer {
     Assert.assertEquals(request1.getInputStream(), request2.getInputStream());
   }
 
+  /**
+   * Test null incomplete request
+   */
   @Test
   public void testIncompleteData() {
     thrown.expect(AvroRuntimeException.class);
-    thrown.expectMessage("Field queryString type:STRING pos:2 not set and has no default value");
+    thrown.expectMessage("Field queryString type:STRING pos:3 not set and has no default value");
     final String s = "test binary stream data";
     final byte[] b = s.getBytes(Charset.forName("UTF-8"));
     avroRequest = AvroHttpRequest.newBuilder()
         .setRequestUrl("http://localhost:8080/reef/evaluators?id=12&id=34&a=b")
         .setHttpMethod("POST")
-            //.setQueryString("id=12&id=34&a=b")
         .setPathInfo("/reef/evaluators")
         .setInputStream(ByteBuffer.wrap(b))
+        .setHeader(createHeader())
         .build();
   }
 
+  /**
+   * Test null query string
+   */
   @Test
   public void testNullData() {
     thrown.expect(AvroRuntimeException.class);
-    thrown.expectMessage("Field queryString type:STRING pos:2 does not accept null values");
+    thrown.expectMessage("Field queryString type:STRING pos:3 does not accept null values");
     final String s = "test binary stream data";
     final byte[] b = s.getBytes(Charset.forName("UTF-8"));
     avroRequest = AvroHttpRequest.newBuilder()
@@ -99,55 +196,89 @@ public final class TestAvroHttpSerializer {
         .setHttpMethod("POST")
         .setQueryString(null)
         .setPathInfo("/reef/evaluators")
+        .setHeader(createHeader())
         .setInputStream(ByteBuffer.wrap(b))
         .build();
   }
 
+  /**
+   * Test null bytes
+   */
   @Test
   public void testNullBytes() {
     thrown.expect(AvroRuntimeException.class);
-    thrown.expectMessage("Field inputStream type:BYTES pos:4 does not accept null values");
+    thrown.expectMessage("Field inputStream type:BYTES pos:5 does not accept null values");
     final String s = "test binary stream data";
     final byte[] b = s.getBytes(Charset.forName("UTF-8"));
+
     avroRequest = AvroHttpRequest.newBuilder()
         .setRequestUrl("http://localhost:8080/reef/evaluators?id=12&id=34&a=b")
         .setHttpMethod("POST")
         .setQueryString("id=12&id=34&a=b")
         .setPathInfo("/reef/evaluators")
         .setInputStream(null)
+        .setHeader(createHeader())
         .build();
   }
 
+  /**
+   * Test empty string
+   */
   @Test
   public void testEmptyString() {
     final String s = "test binary stream data";
     final byte[] b = s.getBytes(Charset.forName("UTF-8"));
+
     avroRequest = AvroHttpRequest.newBuilder()
         .setRequestUrl("http://localhost:8080/reef/evaluators?id=12&id=34&a=b")
         .setHttpMethod("POST")
         .setQueryString("")
         .setPathInfo("/reef/evaluators")
         .setInputStream(ByteBuffer.wrap(b))
+        .setHeader(createHeader())
         .build();
+
     avroHttpSerializer = new AvroHttpSerializer();
     final byte[] serializedBytes = avroHttpSerializer.toBytes(avroRequest);
     final AvroHttpRequest deserializedRequest = avroHttpSerializer.fromBytes(serializedBytes);
     assertEqual(avroRequest, deserializedRequest);
   }
 
+  /**
+   * Test empty bytes
+   */
   @Test
   public void testEmptyBytes() {
     final byte[] b = new byte[0];
+
     avroRequest = AvroHttpRequest.newBuilder()
         .setRequestUrl("http://localhost:8080/reef/evaluators?id=12&id=34&a=b")
         .setHttpMethod("POST")
         .setQueryString("")
         .setPathInfo("/reef/evaluators")
         .setInputStream(ByteBuffer.wrap(b))
+        .setHeader(createHeader())
         .build();
     avroHttpSerializer = new AvroHttpSerializer();
     final byte[] serializedBytes = avroHttpSerializer.toBytes(avroRequest);
     final AvroHttpRequest deserializedRequest = avroHttpSerializer.fromBytes(serializedBytes);
     assertEqual(avroRequest, deserializedRequest);
   }
+
+  private ArrayList<HeaderEntry> createHeader() {
+    final ArrayList<HeaderEntry> list = new ArrayList<HeaderEntry>();
+    final HeaderEntry e1 = HeaderEntry.newBuilder()
+        .setKey("a")
+        .setValue("xxx")
+        .build();
+    list.add(e1);
+
+    final HeaderEntry e2 = HeaderEntry.newBuilder()
+        .setKey("b")
+        .setValue("yyy")
+        .build();
+    list.add(e2);
+
+    return list;
+  }
 }