to MS.NET).
Removed try/catch from AsyncProcessRequest. If there is an exception it must
flow to the caller.
in AsyncRequestHandler, improved management of exceptions. HttpWebRequest
throws an exception if the result code is 400, 500. Is is not a communication
error, but an application or server error. The content of the body must be
deserialized like in normal responses.
In CreateWebRequest, if the stream being sent is a MemoryStream, use a more
efficient way of writing the content.
In SendAndRecieve, same as in AsyncRequestHandler. Also moved some code to a
new method named ReceiveResponse, so it can be reused from AsyncRequestHandler.
* HttpHelper.cs: Removed some debugging code that is not needed.
* HttpServer.cs: Improved formatting of some code.
In CheckRequest method, send a 100-continue response if the request has
the header: expect:100-continue.
Method SendResponse: the remoting formatter may include the result code and
reason phrase to use in the transport headers. Used them if provided.
* HttpServerChannel.cs: Use ThreadPool to create the thread that will answer
a request.
svn path=/trunk/mcs/; revision=17515
--- /dev/null
+2003-08-22 Lluis Sanchez Gual <lluis@ximian.com>
+
+ * HttpClientChannel.cs: Changed text for user-agent header (removed references
+ to MS.NET).
+ Removed try/catch from AsyncProcessRequest. If there is an exception it must
+ flow to the caller.
+ in AsyncRequestHandler, improved management of exceptions. HttpWebRequest
+ throws an exception if the result code is 400, 500. Is is not a communication
+ error, but an application or server error. The content of the body must be
+ deserialized like in normal responses.
+ In CreateWebRequest, if the stream being sent is a MemoryStream, use a more
+ efficient way of writing the content.
+ In SendAndRecieve, same as in AsyncRequestHandler. Also moved some code to a
+ new method named ReceiveResponse, so it can be reused from AsyncRequestHandler.
+ * HttpHelper.cs: Removed some debugging code that is not needed.
+ * HttpServer.cs: Improved formatting of some code.
+ In CheckRequest method, send a 100-continue response if the request has
+ the header: expect:100-continue.
+ Method SendResponse: the remoting formatter may include the result code and
+ reason phrase to use in the transport headers. Used them if provided.
+ * HttpServerChannel.cs: Use ThreadPool to create the thread that will answer
+ a request.
+
+2003-08-18 Lluis Sanchez Gual <lluis@ximian.com>
+
+ * HttpClientChannel.cs, HttpServerChannel.cs: Fixed bug #47703
+
+2003-06-21 Lluis Sanchez Gual <lluis@ximian.com>
+
+ * HttpChannel.cs, HttpClientChannel.cs, HttpHelper.cs, HttpServer.cs,
+ HttpServerChannel.cs, HttpThread.cs: added new implementation of the HttpChannel
+ by Ahmad Tantawy, Ahmad Kadry and Hussein Mehanna.
+ * unix.args: added HttpHelper.cs,HttpServer.cs,HttpThread.cs.
+
namespace System.Runtime.Remoting.Channels.Http
{
-
-
-
-
-
public class HttpClientChannel : IChannelSender,IChannel
{
// Property Keys (purposely all lower-case)
private const String s_defaultVerb = "POST";
private static String s_userAgent =
- "Mozilla/4.0+(compatible; MSIE 6.0; Windows " +
- "; MS .NET Remoting; MS .NET CLR " + System.Environment.Version.ToString() + " )";
+ "Mono Remoting Client (Mono CLR " + System.Environment.Version.ToString() + ")";
// Property keys (purposely all lower-case)
private const String UserNameKey = "username";
ITransportHeaders requestHeaders, Stream requestStream,
out ITransportHeaders responseHeaders, out Stream responseStream)
{
-
-
string url = null;
string uri = (string)requestHeaders[CommonTransportKeys.RequestUri];
CreateUrl(uri,out url);
public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg,
ITransportHeaders headers, Stream stream)
{
- try
- {
- string url = null;
- string uri = (string)headers[CommonTransportKeys.RequestUri];
- CreateUrl(uri,out url);
-
- HttpWebRequest httpWebRequest = CreateWebRequest(url,headers,stream);
- RequestState reqState = new RequestState(httpWebRequest,sinkStack);
+ string url = null;
+ string uri = (string)headers[CommonTransportKeys.RequestUri];
+ CreateUrl(uri,out url);
- httpWebRequest.BeginGetResponse(new AsyncCallback(AsyncRequestHandler),reqState);
+ HttpWebRequest httpWebRequest = CreateWebRequest(url,headers,stream);
+ RequestState reqState = new RequestState(httpWebRequest,sinkStack);
- }
- catch
- {
- Console.WriteLine("Error Sending Async Request");
- }
+ httpWebRequest.BeginGetResponse(new AsyncCallback(AsyncRequestHandler),reqState);
}
private void AsyncRequestHandler(IAsyncResult ar)
RequestState reqState = (RequestState) ar.AsyncState;
HttpWebRequest httpWebRequest = reqState.webRquest;
+ IClientChannelSinkStack sinkStack = reqState.sinkStack;
try
{
httpWebResponse = (HttpWebResponse) httpWebRequest.EndGetResponse(ar);
-
- Stream responseStream ;
- ITransportHeaders responseHeaders;
-
- IClientChannelSinkStack sinkStack = reqState.sinkStack;
+ }
+ catch (WebException ex)
+ {
+ httpWebResponse = ex.Response as HttpWebResponse;
+ if (httpWebResponse == null) sinkStack.DispatchException (ex);
+ }
- responseStream = new MemoryStream();
- HttpHelper.CopyStream(httpWebResponse.GetResponseStream(),ref responseStream);
-
-
- responseHeaders = new TransportHeaders();
-
- for(int i=0; i < httpWebResponse.Headers.Count; ++i)
- responseHeaders[httpWebResponse.Headers.Keys[i].ToString()] = httpWebResponse.Headers[i].ToString();
+ Stream responseStream;
+ ITransportHeaders responseHeaders;
- sinkStack.AsyncProcessResponse(responseHeaders,responseStream);
-
- }
- catch
+ try
{
- Console.WriteLine("Error Recieving Async Response");
+ ReceiveResponse (httpWebResponse, out responseHeaders, out responseStream);
+ sinkStack.AsyncProcessResponse(responseHeaders,responseStream);
}
- finally
+ catch (Exception ex)
{
- if(httpWebResponse!=null)
- httpWebResponse.Close();
+ sinkStack.DispatchException (ex);
}
}
private HttpWebRequest CreateWebRequest(string url, ITransportHeaders requestHeaders, Stream requestStream)
{
-
-
-
-
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);;
request.AllowAutoRedirect = _bAllowAutoRedirect;
request.ContentLength = requestStream.Length;
}
Stream reqStream = request.GetRequestStream();
- HttpHelper.CopyStream(requestStream,ref reqStream);
-
+ if (requestStream is MemoryStream)
+ {
+ MemoryStream memStream = (MemoryStream)requestStream;
+ reqStream.Write (memStream.GetBuffer(), 0, (int)memStream.Length);
+ }
+ else
+ HttpHelper.CopyStream(requestStream, reqStream);
+
reqStream.Close();
return request;
}
- private bool SendAndRecieve(HttpWebRequest httpRequest,out ITransportHeaders responseHeaders,out Stream responseStream)
+ private void SendAndRecieve(HttpWebRequest httpRequest,out ITransportHeaders responseHeaders,out Stream responseStream)
{
responseStream = null;
responseHeaders = null;
HttpWebResponse httpWebResponse = null;
- bool returnValue = false;
-
-
try
{
httpWebResponse = (HttpWebResponse)httpRequest.GetResponse();
+ }
+ catch (WebException ex)
+ {
+ httpWebResponse = ex.Response as HttpWebResponse;
+ if (httpWebResponse == null) throw ex;
+ }
- responseStream = new MemoryStream();
- HttpHelper.CopyStream(httpWebResponse.GetResponseStream(),ref responseStream);
+ ReceiveResponse (httpWebResponse, out responseHeaders, out responseStream);
+ }
+ private void ReceiveResponse (HttpWebResponse httpWebResponse, out ITransportHeaders responseHeaders, out Stream responseStream)
+ {
+ responseHeaders = new TransportHeaders();
+
+ try
+ {
+ Stream webStream = httpWebResponse.GetResponseStream();
+
+ if (httpWebResponse.ContentLength != -1)
+ {
+ byte[] buffer = new byte [httpWebResponse.ContentLength];
+ int nr = 0;
+ while (nr < buffer.Length)
+ nr += webStream.Read (buffer, nr, buffer.Length - nr);
+ responseStream = new MemoryStream (buffer);
+ }
+ else
+ {
+ responseStream = new MemoryStream();
+ HttpHelper.CopyStream(webStream, responseStream);
+ }
- responseHeaders = new TransportHeaders();
-
-
//Use the two commented lines below instead of the 3 below lines when HttpWebResponse
//class is fully implemented in order to support custom headers
//for(int i=0; i < httpWebResponse.Headers.Count; ++i)
// responseHeaders[httpWebResponse.Headers.Keys[i].ToString()] = httpWebResponse.Headers[i].ToString();
-
+
responseHeaders["Content-Type"] = httpWebResponse.ContentType;
responseHeaders["Server"] = httpWebResponse.Server;
responseHeaders["Content-Length"] = httpWebResponse.ContentLength;
-
- returnValue =true;
}
- catch(Exception e)
- {
-
- Console.WriteLine(e);
- returnValue = false;
- }
-
finally
{
if(httpWebResponse!=null)
- httpWebResponse.Close();
+ httpWebResponse.Close();
}
- return returnValue;
}
private void ProcessErrorCode()
{
internal class HttpHelper
{
- public static int d;
public static string Parse(string URL , out string ObjectURI)
{
Pos = URL.IndexOf("/",0);
}
- if(Pos>0 || Pos == 0)
+ if(Pos >= 0)
{
- ObjectURI = URL.Substring(Pos);
+ ObjectURI = URL.Substring(Pos + 1);
return URL.Substring(0,Pos);
}
return URL;
return outStream;
}
- public static bool CopyStream(Stream inStream,ref Stream outStream)
+ public static bool CopyStream(Stream inStream, Stream outStream)
{
int temp;
- d++;
+
try
{
- FileStream f=null;
- if(d==2)
- f = new FileStream("f.txt",System.IO.FileMode.Create);
-
while(true)
{
temp = inStream.ReadByte();
-
-
- if(d==2)
- f.WriteByte((byte)temp);
-
-
+
if(temp==-1)
break;
outStream.WriteByte((byte)temp);
}
- if(d==2)
- f.Close();
outStream.Flush();
if(outStream.CanSeek)
public static void ProcessRequest(object Object)
{
-
if(Object as RequestArguments == null)
return;
-
Socket socket;
HttpServerTransportSink snk;
socket = reqArg.socket;
snk = reqArg.snk;
- if(!socket.Connected)
- return;
-
- //Step (1) Start Reciceve the header
- ArrayList Headers = RecieveHeader(socket);
-
-
- //Step (2) Start Parse the header
- IDictionary HeaderFields = new Hashtable();
- IDictionary CustomHeaders = new Hashtable();
- if(!ParseHeader(socket,Headers,HeaderFields,CustomHeaders))
- return;
-
-
-
-
- //Step (3)
- if(!CheckRequest(socket,HeaderFields,CustomHeaders))
- return;
-
+ if(!socket.Connected)
+ return;
- //Step (4) Recieve the entity body
- byte [] buffer =new byte[(int)HeaderFields["content-length"]];
- if(!RecieveEntityBody(socket,buffer))
- return ;
-
+ //Step (1) Start Reciceve the header
+ ArrayList Headers = RecieveHeader(socket);
+ //Step (2) Start Parse the header
+ IDictionary HeaderFields = new Hashtable();
+ IDictionary CustomHeaders = new Hashtable();
+ if(!ParseHeader(socket,Headers,HeaderFields,CustomHeaders))
+ return;
- //Step (5)
+ //Step (3)
+ if(!CheckRequest(socket,HeaderFields,CustomHeaders))
+ return;
- if(! SendRequestForChannel(socket,snk,HeaderFields,CustomHeaders,buffer))
- return ;
+ //Step (4) Recieve the entity body
+ byte [] buffer =new byte[(int)HeaderFields["content-length"]];
+ if(!RecieveEntityBody(socket,buffer))
+ return ;
-
+ //Step (5)
+ if(! SendRequestForChannel(socket,snk,HeaderFields,CustomHeaders,buffer))
+ return ;
}
private static ArrayList RecieveHeader(Socket socket)
byte[] buffer = new byte[1024];
ArrayList Headers = new ArrayList();
-
-
int index =0;
while(!bLastLine)
{
continue;
Headers.Add( Encoding.ASCII.GetString(buffer,0,index));
-
-
}//end while loop
return Headers;
return false;
}
+ if (HeaderFields["expect"].ToString() == "100-continue")
+ SendResponse(socket,100,null,null);
+
//Check for the content-length field
if(HeaderFields["content-length"]==null)
{
private static bool RecieveEntityBody(Socket socket, byte[] buffer)
{
-
-
try
{
- //Recieved = socket.Receive(buffer,0,buffer.Length,SocketFlags.None);
int nr = 0;
while (nr < buffer.Length)
nr += socket.Receive (buffer, nr, buffer.Length - nr,SocketFlags.None);
private static bool SendRequestForChannel(Socket socket ,HttpServerTransportSink snk ,IDictionary HeaderFields , IDictionary CustomHeaders, byte[]buffer)
{
-
-
TransportHeaders THeaders = new TransportHeaders();
-
Stream stream = new MemoryStream(buffer);
-
if(stream.Position !=0)
stream.Seek(0,SeekOrigin.Begin);
byte [] headersBuffer = null;
byte [] entityBuffer = null;
- StringBuilder ResponseStr ;
+ StringBuilder ResponseStr;
String Reason = GetReasonPhrase(HttpStatusCode);
+ if (headers != null && headers["__HttpStatusCode"] != null) {
+ // The formatter can override the result code
+ HttpStatusCode = int.Parse ((string)headers["__HttpStatusCode"]);
+ Reason = (string)headers["__HttpReasonPhrase"];
+ }
//Response Line
- ResponseStr = new StringBuilder( "HTTP/1.1 " + HttpStatusCode.ToString() + " " + Reason + "\r\n" );
+ ResponseStr = new StringBuilder( "HTTP/1.0 " + HttpStatusCode + " " + Reason + "\r\n" );
if(headers!=null)
foreach(DictionaryEntry entry in headers)
{
- ResponseStr.Append(entry.Key.ToString()+": "+entry.Value.ToString()+"\r\n");
+ string key = entry.Key.ToString();
+ if (key != "__HttpStatusCode" && key != "__HttpReasonPhrase")
+ ResponseStr.Append(key + ": " + entry.Value.ToString() + "\r\n");
}
- ResponseStr.Append("Server: MS .NET Remoting, MS .NET CLR 1.0.3705.0\r\n");
+ ResponseStr.Append("Server: Mono Remoting, Mono CLR " + System.Environment.Version.ToString() + "\r\n");
if(responseStream != null)
if(responseStream.Length!=0)
{
switch (HttpStatusCode)
{
- case 100 : return " Continue" ;
+ case 100 : return "Continue" ;
case 101 :return "Switching Protocols";
case 200 :return "OK";
case 201 :return "Created";
if(_sinkProvider == null)
_sinkProvider = new SoapServerFormatterSinkProvider();
-
-
// collect channel data from all providers
IServerChannelSinkProvider provider = _sinkProvider;
while (provider != null)
// create the sink chain
IServerChannelSink snk =
ChannelServices.CreateServerChannelSinkChain(_sinkProvider,this);
-
_transportSink = new HttpServerTransportSink(snk);
{
Socket socket = _tcpListener.AcceptSocket();
RequestArguments reqArg = new RequestArguments(socket,_transportSink);
- HttpThread httpThread = new HttpThread(reqArg);
-
+ ThreadPool.QueueUserWorkItem (new WaitCallback (HttpServer.ProcessRequest), reqArg);
}
}
ThreadStart t = new ThreadStart(this.Listen);
_listenerThread = new Thread(t);
_listenerThread.IsBackground = true;
-
}
if(!_listenerThread.IsAlive)
_listenerThread.Start();
-
-
_bListening = true;
}
{
if( _bListening)
{
+ _listenerThread.Abort ();
_tcpListener.Stop();
}
ITransportHeaders responseHeaders;
Stream responseStream;
- ServerProcessing processing= ServerProcessing.Complete;
+ ServerProcessing processing = ServerProcessing.Complete;
try
{
processing =
out responseMessage,
out responseHeaders, out responseStream);
-
-
switch (processing)
{
case ServerProcessing.Complete:
catch(Exception )
{
}
-
-}
-
-
+ }
//