To separate your HTTP request header and data:
- Read NetworkStream And copy the data to MemoryStream
- Call
byte[] mem = MemoryStream.ToArry()
Method
- Search for these bytes
{ 13, 10, 13, 10 }
and find first index within mem
- And substring
mem
like byte[] heaader = mem[..endpoint]
- If you want to Consume Http request body you may want to install nuget package
Install-Package HttpMultipartParser
you can find it's repo at https://github.com/Http-Multipart-Data-Parser/Http-Multipart-Data-Parser
Here's the code you need:
// This method will read HTTP Request
public async void ReadRequestHeader(NetworkStream stream)
{
MemoryStream memory = new MemoryStream();
while (stream.DataAvailable && stream.CanRead)
{
byte[] b = new byte[256];
int read = await stream.ReadAsync(b, 0, b.Length);
await memory.WriteAsync(b, 0, read);
}
memory.Seek(0, SeekOrigin.Begin);
byte[] mem = memory.ToArray();
byte[] emptyline = new byte[] { 13, 10, 13, 10 };
byte[] data;
byte[] header;
bool test = mem.Contains(emptyline, out int endpoint);
if (test)
{
endpoint+= emptyline.Length;
header = mem[..endpoint]; // your Header bytes
data = mem[endpoint..]; // your Body bytes
// if you want to consume http request body. just follow
MultipartFormDataParser parser = await MultipartFormDataParser.ParseAsync(new MemoryStream(data)).ConfigureAwait(false);
Console.WriteLine("MyName : {0}", parser.GetParameterValue("username"));
foreach (FilePart file in parser.Files)
{
File.WriteAllBytes(
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), file.FileName), ((MemoryStream)file.Data).ToArray()
);
}
}
}
Now, Let's Implement Contains(this byte[] self, byte[] candidate, out int ep)
// Note: I've copied this class from
// https://stackoverflow.com/a/5062250/10903225
static class ByteArrayRocks
{
public static bool Contains(this byte[] self, byte[] candidate, out int ep)
{
ep = 0;
if (IsEmptyLocate(self, candidate))
return false;
for (int i = 0; i < self.Length; i++)
{
if (IsMatch(self, i, candidate))
{
ep = i;
return true;
}
}
return false;
}
static bool IsMatch(byte[] array, int position, byte[] candidate)
{
if (candidate.Length > (array.Length - position))
return false;
for (int i = 0; i < candidate.Length; i++)
if (array[position + i] != candidate[i])
return false;
return true;
}
static bool IsEmptyLocate(byte[] array, byte[] candidate)
{
return array == null
|| candidate == null
|| array.Length == 0
|| candidate.Length == 0
|| candidate.Length > array.Length;
}
}
Note:
I know it's not the best solution especially if Http request body is too big (Which'll eat up all your memory). but, you can specify fixed number of bytes to be read by MemoryStream
I hope this long solution hepls you.