예제 #1
0
        /// <summary>Processes the response (possibly updating or inserting) Content-Length and Transfer-Encoding headers.
        ///     </summary>
        /// <remarks>Processes the response (possibly updating or inserting) Content-Length and Transfer-Encoding headers.
        ///     </remarks>
        /// <param name="response">The HttpResponse to modify.</param>
        /// <param name="context">Unused.</param>
        /// <exception cref="Org.Apache.Http.ProtocolException">If either the Content-Length or Transfer-Encoding headers are found.
        ///     </exception>
        /// <exception cref="System.ArgumentException">If the response is null.</exception>
        /// <exception cref="Org.Apache.Http.HttpException"></exception>
        /// <exception cref="System.IO.IOException"></exception>
        public virtual void Process(HttpResponse response, HttpContext context)
        {
            Args.NotNull(response, "HTTP response");
            if (this.overwrite)
            {
                response.RemoveHeaders(HTTP.TransferEncoding);
                response.RemoveHeaders(HTTP.ContentLen);
            }
            else
            {
                if (response.ContainsHeader(HTTP.TransferEncoding))
                {
                    throw new ProtocolException("Transfer-encoding header already present");
                }
                if (response.ContainsHeader(HTTP.ContentLen))
                {
                    throw new ProtocolException("Content-Length header already present");
                }
            }
            ProtocolVersion ver    = response.GetStatusLine().GetProtocolVersion();
            HttpEntity      entity = response.GetEntity();

            if (entity != null)
            {
                long len = entity.GetContentLength();
                if (entity.IsChunked() && !ver.LessEquals(HttpVersion.Http10))
                {
                    response.AddHeader(HTTP.TransferEncoding, HTTP.ChunkCoding);
                }
                else
                {
                    if (len >= 0)
                    {
                        response.AddHeader(HTTP.ContentLen, System.Convert.ToString(entity.GetContentLength
                                                                                        ()));
                    }
                }
                // Specify a content type if known
                if (entity.GetContentType() != null && !response.ContainsHeader(HTTP.ContentType))
                {
                    response.AddHeader(entity.GetContentType());
                }
                // Specify a content encoding if known
                if (entity.GetContentEncoding() != null && !response.ContainsHeader(HTTP.ContentEncoding
                                                                                    ))
                {
                    response.AddHeader(entity.GetContentEncoding());
                }
            }
            else
            {
                int status = response.GetStatusLine().GetStatusCode();
                if (status != HttpStatus.ScNoContent && status != HttpStatus.ScNotModified && status
                    != HttpStatus.ScResetContent)
                {
                    response.AddHeader(HTTP.ContentLen, "0");
                }
            }
        }
        /// <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);
        }
예제 #3
0
        /// <exception cref="Org.Apache.Http.HttpException"></exception>
        /// <exception cref="System.IO.IOException"></exception>
        public virtual void Process(HttpResponse response, HttpContext context)
        {
            Args.NotNull(response, "HTTP response");
            HttpCoreContext corecontext = HttpCoreContext.Adapt(context);
            // Always drop connection after certain type of responses
            int status = response.GetStatusLine().GetStatusCode();

            if (status == HttpStatus.ScBadRequest || status == HttpStatus.ScRequestTimeout ||
                status == HttpStatus.ScLengthRequired || status == HttpStatus.ScRequestTooLong ||
                status == HttpStatus.ScRequestUriTooLong || status == HttpStatus.ScServiceUnavailable ||
                status == HttpStatus.ScNotImplemented)
            {
                response.SetHeader(HTTP.ConnDirective, HTTP.ConnClose);
                return;
            }
            Header _explicit = response.GetFirstHeader(HTTP.ConnDirective);

            if (_explicit != null && Sharpen.Runtime.EqualsIgnoreCase(HTTP.ConnClose, _explicit
                                                                      .GetValue()))
            {
                // Connection persistence _explicitly disabled
                return;
            }
            // Always drop connection for HTTP/1.0 responses and below
            // if the content body cannot be correctly delimited
            HttpEntity entity = response.GetEntity();

            if (entity != null)
            {
                ProtocolVersion ver = response.GetStatusLine().GetProtocolVersion();
                if (entity.GetContentLength() < 0 && (!entity.IsChunked() || ver.LessEquals(HttpVersion
                                                                                            .Http10)))
                {
                    response.SetHeader(HTTP.ConnDirective, HTTP.ConnClose);
                    return;
                }
            }
            // Drop connection if requested by the client or request was <= 1.0
            IHttpRequest request = corecontext.GetRequest();

            if (request != null)
            {
                Header header = request.GetFirstHeader(HTTP.ConnDirective);
                if (header != null)
                {
                    response.SetHeader(HTTP.ConnDirective, header.GetValue());
                }
                else
                {
                    if (request.GetProtocolVersion().LessEquals(HttpVersion.Http10))
                    {
                        response.SetHeader(HTTP.ConnDirective, HTTP.ConnClose);
                    }
                }
            }
        }
		/// <exception cref="Org.Apache.Http.HttpException"></exception>
		/// <exception cref="System.IO.IOException"></exception>
		public virtual void Process(IHttpRequest request, HttpContext context)
		{
			Args.NotNull(request, "HTTP request");
			HttpCoreContext corecontext = HttpCoreContext.Adapt(context);
			ProtocolVersion ver = request.GetRequestLine().GetProtocolVersion();
			string method = request.GetRequestLine().GetMethod();
			if (Sharpen.Runtime.EqualsIgnoreCase(method, "CONNECT") && ver.LessEquals(HttpVersion
				.Http10))
			{
				return;
			}
			if (!request.ContainsHeader(HTTP.TargetHost))
			{
				HttpHost targethost = corecontext.GetTargetHost();
				if (targethost == null)
				{
					HttpConnection conn = corecontext.GetConnection();
					if (conn is HttpInetConnection)
					{
						// Populate the context with a default HTTP host based on the
						// inet address of the target host
						IPAddress address = ((HttpInetConnection)conn).GetRemoteAddress();
						int port = ((HttpInetConnection)conn).GetRemotePort();
						if (address != null)
						{
							targethost = new HttpHost(address.GetHostName(), port);
						}
					}
					if (targethost == null)
					{
						if (ver.LessEquals(HttpVersion.Http10))
						{
							return;
						}
						else
						{
							throw new ProtocolException("Target host missing");
						}
					}
				}
				request.AddHeader(HTTP.TargetHost, targethost.ToHostString());
			}
		}
예제 #5
0
 /// <exception cref="Org.Apache.Http.HttpException"></exception>
 /// <exception cref="System.IO.IOException"></exception>
 public virtual void Process(IHttpRequest request, HttpContext context)
 {
     Args.NotNull(request, "HTTP request");
     if (request is HttpEntityEnclosingRequest)
     {
         if (this.overwrite)
         {
             request.RemoveHeaders(HTTP.TransferEncoding);
             request.RemoveHeaders(HTTP.ContentLen);
         }
         else
         {
             if (request.ContainsHeader(HTTP.TransferEncoding))
             {
                 throw new ProtocolException("Transfer-encoding header already present");
             }
             if (request.ContainsHeader(HTTP.ContentLen))
             {
                 throw new ProtocolException("Content-Length header already present");
             }
         }
         ProtocolVersion ver    = request.GetRequestLine().GetProtocolVersion();
         HttpEntity      entity = ((HttpEntityEnclosingRequest)request).GetEntity();
         if (entity == null)
         {
             request.AddHeader(HTTP.ContentLen, "0");
             return;
         }
         // Must specify a transfer encoding or a content length
         if (entity.IsChunked() || entity.GetContentLength() < 0)
         {
             if (ver.LessEquals(HttpVersion.Http10))
             {
                 throw new ProtocolException("Chunked transfer encoding not allowed for " + ver);
             }
             request.AddHeader(HTTP.TransferEncoding, HTTP.ChunkCoding);
         }
         else
         {
             request.AddHeader(HTTP.ContentLen, System.Convert.ToString(entity.GetContentLength
                                                                            ()));
         }
         // Specify a content type if known
         if (entity.GetContentType() != null && !request.ContainsHeader(HTTP.ContentType))
         {
             request.AddHeader(entity.GetContentType());
         }
         // Specify a content encoding if known
         if (entity.GetContentEncoding() != null && !request.ContainsHeader(HTTP.ContentEncoding
                                                                            ))
         {
             request.AddHeader(entity.GetContentEncoding());
         }
     }
 }
예제 #6
0
 /// <exception cref="Org.Apache.Http.HttpException"></exception>
 /// <exception cref="System.IO.IOException"></exception>
 public virtual void Process(IHttpRequest request, HttpContext context)
 {
     Args.NotNull(request, "HTTP request");
     if (!request.ContainsHeader(HTTP.ExpectDirective))
     {
         if (request is HttpEntityEnclosingRequest)
         {
             ProtocolVersion ver    = request.GetRequestLine().GetProtocolVersion();
             HttpEntity      entity = ((HttpEntityEnclosingRequest)request).GetEntity();
             // Do not send the expect header if request body is known to be empty
             if (entity != null && entity.GetContentLength() != 0 && !ver.LessEquals(HttpVersion
                                                                                     .Http10))
             {
                 bool active = request.GetParams().GetBooleanParameter(CoreProtocolPNames.UseExpectContinue
                                                                       , this.activeByDefault);
                 if (active)
                 {
                     request.AddHeader(HTTP.ExpectDirective, HTTP.ExpectContinue);
                 }
             }
         }
     }
 }
 /// <exception cref="Apache.Http.HttpException"></exception>
 /// <exception cref="System.IO.IOException"></exception>
 public virtual void Process(IHttpRequest request, HttpContext context)
 {
     Args.NotNull(request, "HTTP request");
     if (!request.ContainsHeader(HTTP.ExpectDirective))
     {
         if (request is HttpEntityEnclosingRequest)
         {
             ProtocolVersion ver    = request.GetRequestLine().GetProtocolVersion();
             HttpEntity      entity = ((HttpEntityEnclosingRequest)request).GetEntity();
             // Do not send the expect header if request body is known to be empty
             if (entity != null && entity.GetContentLength() != 0 && !ver.LessEquals(HttpVersion
                                                                                     .Http10))
             {
                 HttpClientContext clientContext = ((HttpClientContext)HttpClientContext.Adapt(context
                                                                                               ));
                 RequestConfig config = clientContext.GetRequestConfig();
                 if (config.IsExpectContinueEnabled())
                 {
                     request.AddHeader(HTTP.ExpectDirective, HTTP.ExpectContinue);
                 }
             }
         }
     }
 }
        // see interface ConnectionReuseStrategy
        public virtual bool KeepAlive(HttpResponse response, HttpContext context)
        {
            Args.NotNull(response, "HTTP response");
            Args.NotNull(context, "HTTP context");
            // Check for a self-terminating entity. If the end of the entity will
            // be indicated by closing the connection, there is no keep-alive.
            ProtocolVersion ver = response.GetStatusLine().GetProtocolVersion();
            Header          teh = response.GetFirstHeader(HTTP.TransferEncoding);

            if (teh != null)
            {
                if (!Sharpen.Runtime.EqualsIgnoreCase(HTTP.ChunkCoding, teh.GetValue()))
                {
                    return(false);
                }
            }
            else
            {
                if (CanResponseHaveBody(response))
                {
                    Header[] clhs = response.GetHeaders(HTTP.ContentLen);
                    // Do not reuse if not properly content-length delimited
                    if (clhs.Length == 1)
                    {
                        Header clh = clhs[0];
                        try
                        {
                            int contentLen = System.Convert.ToInt32(clh.GetValue());
                            if (contentLen < 0)
                            {
                                return(false);
                            }
                        }
                        catch (FormatException)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            // Check for the "Connection" header. If that is absent, check for
            // the "Proxy-Connection" header. The latter is an unspecified and
            // broken but unfortunately common extension of HTTP.
            HeaderIterator hit = response.HeaderIterator(HTTP.ConnDirective);

            if (!hit.HasNext())
            {
                hit = response.HeaderIterator("Proxy-Connection");
            }
            // Experimental usage of the "Connection" header in HTTP/1.0 is
            // documented in RFC 2068, section 19.7.1. A token "keep-alive" is
            // used to indicate that the connection should be persistent.
            // Note that the final specification of HTTP/1.1 in RFC 2616 does not
            // include this information. Neither is the "Connection" header
            // mentioned in RFC 1945, which informally describes HTTP/1.0.
            //
            // RFC 2616 specifies "close" as the only connection token with a
            // specific meaning: it disables persistent connections.
            //
            // The "Proxy-Connection" header is not formally specified anywhere,
            // but is commonly used to carry one token, "close" or "keep-alive".
            // The "Connection" header, on the other hand, is defined as a
            // sequence of tokens, where each token is a header name, and the
            // token "close" has the above-mentioned additional meaning.
            //
            // To get through this mess, we treat the "Proxy-Connection" header
            // in exactly the same way as the "Connection" header, but only if
            // the latter is missing. We scan the sequence of tokens for both
            // "close" and "keep-alive". As "close" is specified by RFC 2068,
            // it takes precedence and indicates a non-persistent connection.
            // If there is no "close" but a "keep-alive", we take the hint.
            if (hit.HasNext())
            {
                try
                {
                    TokenIterator ti        = CreateTokenIterator(hit);
                    bool          keepalive = false;
                    while (ti.HasNext())
                    {
                        string token = ti.NextToken();
                        if (Sharpen.Runtime.EqualsIgnoreCase(HTTP.ConnClose, token))
                        {
                            return(false);
                        }
                        else
                        {
                            if (Sharpen.Runtime.EqualsIgnoreCase(HTTP.ConnKeepAlive, token))
                            {
                                // continue the loop, there may be a "close" afterwards
                                keepalive = true;
                            }
                        }
                    }
                    if (keepalive)
                    {
                        return(true);
                    }
                }
                catch (ParseException)
                {
                    // neither "close" nor "keep-alive", use default policy
                    // invalid connection header means no persistent connection
                    // we don't have logging in HttpCore, so the exception is lost
                    return(false);
                }
            }
            // default since HTTP/1.1 is persistent, before it was non-persistent
            return(!ver.LessEquals(HttpVersion.Http10));
        }