|
using System;
using System.Net.Sockets;
using System.Collections;
using System.Text;
using System.IO;
namespace DistributedCommand.HTTPProvider
{
public class HttpMessageException : Exception
{
public HttpMessageException( String status, String reason )
{
Error = new HttpMessage( );
Error.Status = status;
Error.Reason = reason;
Error.Version = "HTTP/1.1";
}
public HttpMessage Error;
}
public class HttpMessage
{
public HttpMessage( )
{
CorrelationID = String.Empty;
}
public void Send( NetworkStream stream )
{
StringBuilder sb = new StringBuilder( );
// build first line
if ( IsResponse )
{
sb.Append( Version );
sb.Append( ' ' );
sb.Append( Status );
sb.Append( ' ' );
sb.Append( Reason );
}
else
{
sb.Append( Verb );
sb.Append( ' ' );
sb.Append( RequestUri );
sb.Append( ' ' );
sb.Append( Version );
if ( CorrelationID == String.Empty )
CorrelationID = Guid.NewGuid( ).ToString( );
}
sb.Append( "\r\n" );
if ( body.Length > 0 )
ContentLength = body.Length;
// build headers
IDictionaryEnumerator itr = Headers.GetEnumerator( );
while ( itr.MoveNext( ) )
{
sb.Append( itr.Key as String );
sb.Append( ": " );
sb.Append( itr.Value as String );
sb.Append( "\r\n" );
}
sb.Append( "\r\n" );
// convert to bytes
Byte[] bytes = Encoding.UTF8.GetBytes( sb.ToString( ) );
stream.Write( bytes, 0, bytes.Length );
stream.Write( body, 0, body.Length );
stream.Flush( );
}
private void ThrowBadRequest( )
{
throw new HttpMessageException( "400", "Bad request" );
}
public void Receive( NetworkStream stream )
{
// allocate inital buffer
MemoryStream mem = new MemoryStream( );
// read the HTTP headers
bool completed = false;
do
{
int b = 0;
b = stream.ReadByte( );
if ( b == 0x0d )
{
mem.WriteByte( (byte) b ); // add '\r'
b = stream.ReadByte( );
mem.WriteByte( (byte) b ); // add '\n'
completed = true;
break;
}
while ( b != 0x0d )
{
mem.WriteByte( (byte) b );
b = stream.ReadByte( );
}
mem.WriteByte( (byte) b ); // add '\r'
b = stream.ReadByte( );
mem.WriteByte( (byte) b ); // add '\n'
} while ( stream.DataAvailable );
if ( !completed )
ThrowBadRequest( );
mem.Position = 0;
StreamReader reader = new StreamReader( mem, Encoding.UTF8 );
// read and process first line
String line = reader.ReadLine( );
int n = line.IndexOf( ' ' );
if ( n == -1 )
ThrowBadRequest( );
String str = line.Substring( 0, n );
if ( str.ToUpper( ).StartsWith( "HTTP" ) )
{
Version = str;
line = line.Substring( n + 1 );
n = line.IndexOf( ' ' );
if ( n == -1 )
ThrowBadRequest( );
Status = line.Substring( 0, n );
Reason = line.Substring( n + 1 );
}
else
{
Verb = str;
line = line.Substring( n + 1 );
n = line.IndexOf( ' ' );
if ( n == -1 )
ThrowBadRequest( );
RequestUri = line.Substring( 0, n );
Version = line.Substring( n + 1 );
}
// read all the headers
String[] tokens;
line = reader.ReadLine( );
while ( line != null && line != String.Empty )
{
tokens = line.Split( ':' );
String name = tokens[0].Trim( );
Headers[name] = tokens[1].Trim( );
line = reader.ReadLine( );
}
// now go for the message body if there is one
int len = ContentLength;
if ( len == 0 )
return;
int totalBytesRead = 0;
// Read until specified content length is fully read
MemoryStream bodyStream = new MemoryStream(ContentLength);
Byte[] buffer = new Byte[len];
while( totalBytesRead < ContentLength )
{
int bytesRead = stream.Read( buffer, 0, buffer.Length );
bodyStream.Write( buffer, 0, bytesRead );
totalBytesRead += bytesRead;
}
body = bodyStream.GetBuffer();
}
public bool IsResponse
{
get { return Verb == null || Verb == String.Empty; }
}
public Hashtable Headers = new Hashtable( );
public String CorrelationID
{
get { return Headers["Correlation-Id"] as String; }
set { Headers["Correlation-Id"] = value; }
}
public int ContentLength
{
get
{
String tmp = Headers["Content-Length"] as String;
return (tmp != null) ? int.Parse( tmp ) : 0;
}
set { Headers["Content-Length"] = value.ToString( ); }
}
private Byte[] body = new Byte[0];
public Byte[] Body
{
get { return body; }
set
{
body = value;
if ( body.Length > 0 )
ContentLength = body.Length;
}
}
// first line tokens
public String Verb;
public String RequestUri;
public String Version;
public String Status;
public String Reason;
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.