+2005-06-10 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * WebConnection.cs:
+ * HttpWebRequest.cs:
+ * WebConnectionStream.cs: initiate the polling for input data after
+ sending the header so that we detect any response that the server sends
+ back even if we're still trying to write the request for a POST/PUT.
+ If we get the response (or an error) before any one calls GetResponse(),
+ keep it around instead of ignoring it.
+
2005-06-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* HttpWebRequest.cs: send the right header/user/password in
byte[] bodyBuffer;
int bodyBufferLength;
bool getResponseCalled;
+ Exception saved_exc;
#if NET_1_1
int maxResponseHeadersLength;
static int defaultMaxResponseHeadersLength;
initialMethod = method;
if (haveResponse) {
if (webResponse != null) {
+ Exception saved = saved_exc;
Monitor.Exit (this);
- asyncRead.SetCompleted (true, webResponse);
+ if (saved == null) {
+ asyncRead.SetCompleted (true, webResponse);
+ } else {
+ asyncRead.SetCompleted (true, saved);
+ }
asyncRead.DoCallback ();
return asyncRead;
}
public override WebResponse GetResponse()
{
- if (haveResponse && webResponse != null)
- return webResponse;
-
WebAsyncResult result = (WebAsyncResult) BeginGetResponse (null, null);
return EndGetResponse (result);
}
asyncWrite = null;
}
}
-
+
+ void CheckSendError (WebConnectionData data)
+ {
+ // Got here, but no one called GetResponse
+ if (data.StatusCode < 400)
+ return;
+
+ if (writeStream != null && asyncRead == null && !writeStream.CompleteRequestWritten) {
+ // The request has not been completely sent and we got here!
+ // We should probably just close and cause an error in any case,
+ saved_exc = new WebException (data.StatusDescription, null, WebExceptionStatus.ProtocolError, webResponse);
+ webResponse.ReadAll ();
+ }
+ }
+
internal void SetResponseData (WebConnectionData data)
{
if (aborted) {
data.stream.Close ();
}
+ if (wexc == null && (method == "POST" || method == "PUT")) {
+ lock (this) {
+ CheckSendError (data);
+ if (saved_exc != null)
+ wexc = (WebException) saved_exc;
+ }
+ }
+
WebAsyncResult r = asyncRead;
if (r != null) {
if (wexc != null) {
return result;
}
- internal void EndWrite (IAsyncResult result)
+ internal bool EndWrite (IAsyncResult result)
{
- if (nstream != null)
+ if (nstream == null)
+ return false;
+
+ try {
nstream.EndWrite (result);
+ return true;
+ } catch (Exception e) {
+ status = WebExceptionStatus.SendFailure;
+ return false;
+ }
}
internal int Read (byte [] buffer, int offset, int size)
object locker = new object ();
bool initRead;
bool read_eof;
+ bool complete_request_written;
public WebConnectionStream (WebConnection cnc)
{
pending = new ManualResetEvent (true);
}
+ internal bool CompleteRequestWritten {
+ get { return complete_request_written; }
+ }
+
internal bool SendChunked {
set { sendChunked = value; }
}
if (cnc.Data.StatusCode != 0 && cnc.Data.StatusCode != 100)
return;
- cnc.Write (bytes, 0, length);
+ if (!initRead) {
+ initRead = true;
+ WebConnection.InitRead (cnc);
+ }
+
+ IAsyncResult result = cnc.BeginWrite (bytes, 0, length, null, null);
+ complete_request_written = cnc.EndWrite (result);
}
internal void InternalClose ()
{
disposed = true;
}
-
+
+ internal void ForceCloseConnection ()
+ {
+ if (!disposed) {
+ disposed = true;
+ cnc.Close (true);
+ }
+ }
+
public override void Close ()
{
if (sendChunked) {
}
return;
} else if (!allowBuffering) {
+ complete_request_written = true;
if (!initRead) {
initRead = true;
WebConnection.InitRead (cnc);
if (disposed)
return;
- disposed = true;
-
long length = request.ContentLength;
if (length != -1 && length > writeBuffer.Length)
throw new IOException ("Cannot close the stream until all bytes are written");
WriteRequest ();
- if (!initRead) {
- initRead = true;
- WebConnection.InitRead (cnc);
- }
+ disposed = true;
}
public override long Seek (long a, SeekOrigin b)