/// <summary>Send the given request over the given connection.</summary> /// <remarks> /// Send the given request over the given connection. /// <p> /// This method also handles the expect-continue handshake if necessary. /// If it does not have to handle an expect-continue handshake, it will /// not use the connection for reading or anything else that depends on /// data coming in over the connection. /// </remarks> /// <param name="request"> /// the request to send, already /// <see cref="PreProcess(Org.Apache.Http.IHttpRequest, HttpProcessor, HttpContext)">preprocessed /// </see> /// </param> /// <param name="conn"> /// the connection over which to send the request, /// already established /// </param> /// <param name="context">the context for sending the request</param> /// <returns> /// a terminal response received as part of an expect-continue /// handshake, or /// <code>null</code> if the expect-continue handshake is not used /// </returns> /// <exception cref="System.IO.IOException">in case of an I/O error.</exception> /// <exception cref="Org.Apache.Http.HttpException"> /// in case of HTTP protocol violation or a processing /// problem. /// </exception> protected internal virtual HttpResponse DoSendRequest(IHttpRequest request, HttpClientConnection conn, HttpContext context) { Args.NotNull(request, "HTTP request"); Args.NotNull(conn, "Client connection"); Args.NotNull(context, "HTTP context"); HttpResponse response = null; context.SetAttribute(HttpCoreContext.HttpConnection, conn); context.SetAttribute(HttpCoreContext.HttpReqSent, false); conn.SendRequestHeader(request); if (request is HttpEntityEnclosingRequest) { // Check for expect-continue handshake. We have to flush the // headers and wait for an 100-continue response to handle it. // If we get a different response, we must not send the entity. bool sendentity = true; ProtocolVersion ver = request.GetRequestLine().GetProtocolVersion(); if (((HttpEntityEnclosingRequest)request).ExpectContinue() && !ver.LessEquals(HttpVersion .Http10)) { conn.Flush(); // As suggested by RFC 2616 section 8.2.3, we don't wait for a // 100-continue response forever. On timeout, send the entity. if (conn.IsResponseAvailable(this.waitForContinue)) { response = conn.ReceiveResponseHeader(); if (CanResponseHaveBody(request, response)) { conn.ReceiveResponseEntity(response); } int status = response.GetStatusLine().GetStatusCode(); if (status < 200) { if (status != HttpStatus.ScContinue) { throw new ProtocolException("Unexpected response: " + response.GetStatusLine()); } // discard 100-continue response = null; } else { sendentity = false; } } } if (sendentity) { conn.SendRequestEntity((HttpEntityEnclosingRequest)request); } } conn.Flush(); context.SetAttribute(HttpCoreContext.HttpReqSent, true); return(response); }
/// <summary>Waits for and receives a response.</summary> /// <remarks> /// Waits for and receives a response. /// This method will automatically ignore intermediate responses /// with status code 1xx. /// </remarks> /// <param name="request">the request for which to obtain the response</param> /// <param name="conn">the connection over which the request was sent</param> /// <param name="context">the context for receiving the response</param> /// <returns>the terminal response, not yet post-processed</returns> /// <exception cref="System.IO.IOException">in case of an I/O error.</exception> /// <exception cref="Org.Apache.Http.HttpException"> /// in case of HTTP protocol violation or a processing /// problem. /// </exception> protected internal virtual HttpResponse DoReceiveResponse(IHttpRequest request, HttpClientConnection conn, HttpContext context) { Args.NotNull(request, "HTTP request"); Args.NotNull(conn, "Client connection"); Args.NotNull(context, "HTTP context"); HttpResponse response = null; int statusCode = 0; while (response == null || statusCode < HttpStatus.ScOk) { response = conn.ReceiveResponseHeader(); if (CanResponseHaveBody(request, response)) { conn.ReceiveResponseEntity(response); } statusCode = response.GetStatusLine().GetStatusCode(); } // while intermediate response return(response); }