?? httpmethodbase.java
字號:
buf.append(version); buf.append("\r\n"); return buf.toString(); } /** * This method is invoked immediately after * {@link #readResponseBody(HttpState,HttpConnection)} and can be overridden by * sub-classes in order to provide custom body processing. * * <p> * This implementation does nothing. * </p> * * @param state the {@link HttpState state} information associated with this method * @param conn the {@link HttpConnection connection} used to execute * this HTTP method * * @see #readResponse * @see #readResponseBody */ protected void processResponseBody(HttpState state, HttpConnection conn) { } /** * This method is invoked immediately after * {@link #readResponseHeaders(HttpState,HttpConnection)} and can be overridden by * sub-classes in order to provide custom response headers processing. * <p> * This implementation will handle the <tt>Set-Cookie</tt> and * <tt>Set-Cookie2</tt> headers, if any, adding the relevant cookies to * the given {@link HttpState}. * </p> * * @param state the {@link HttpState state} information associated with this method * @param conn the {@link HttpConnection connection} used to execute * this HTTP method * * @see #readResponse * @see #readResponseHeaders */ protected void processResponseHeaders(HttpState state, HttpConnection conn) { LOG.trace("enter HttpMethodBase.processResponseHeaders(HttpState, " + "HttpConnection)"); Header[] headers = getResponseHeaderGroup().getHeaders("set-cookie2"); //Only process old style set-cookie headers if new style headres //are not present if (headers.length == 0) { headers = getResponseHeaderGroup().getHeaders("set-cookie"); } CookieSpec parser = getCookieSpec(state); String host = this.params.getVirtualHost(); if (host == null) { host = conn.getHost(); } for (int i = 0; i < headers.length; i++) { Header header = headers[i]; Cookie[] cookies = null; try { cookies = parser.parse( host, conn.getPort(), getPath(), conn.isSecure(), header); } catch (MalformedCookieException e) { if (LOG.isWarnEnabled()) { LOG.warn("Invalid cookie header: \"" + header.getValue() + "\". " + e.getMessage()); } } if (cookies != null) { for (int j = 0; j < cookies.length; j++) { Cookie cookie = cookies[j]; try { parser.validate( host, conn.getPort(), getPath(), conn.isSecure(), cookie); state.addCookie(cookie); if (LOG.isDebugEnabled()) { LOG.debug("Cookie accepted: \"" + parser.formatCookie(cookie) + "\""); } } catch (MalformedCookieException e) { if (LOG.isWarnEnabled()) { LOG.warn("Cookie rejected: \"" + parser.formatCookie(cookie) + "\". " + e.getMessage()); } } } } } } /** * This method is invoked immediately after * {@link #readStatusLine(HttpState,HttpConnection)} and can be overridden by * sub-classes in order to provide custom response status line processing. * * @param state the {@link HttpState state} information associated with this method * @param conn the {@link HttpConnection connection} used to execute * this HTTP method * * @see #readResponse * @see #readStatusLine */ protected void processStatusLine(HttpState state, HttpConnection conn) { } /** * Reads the response from the given {@link HttpConnection connection}. * * <p> * The response is processed as the following sequence of actions: * * <ol> * <li> * {@link #readStatusLine(HttpState,HttpConnection)} is * invoked to read the request line. * </li> * <li> * {@link #processStatusLine(HttpState,HttpConnection)} * is invoked, allowing the method to process the status line if * desired. * </li> * <li> * {@link #readResponseHeaders(HttpState,HttpConnection)} is invoked to read * the associated headers. * </li> * <li> * {@link #processResponseHeaders(HttpState,HttpConnection)} is invoked, allowing * the method to process the headers if desired. * </li> * <li> * {@link #readResponseBody(HttpState,HttpConnection)} is * invoked to read the associated body (if any). * </li> * <li> * {@link #processResponseBody(HttpState,HttpConnection)} is invoked, allowing the * method to process the response body if desired. * </li> * </ol> * * Subclasses may want to override one or more of the above methods to to * customize the processing. (Or they may choose to override this method * if dramatically different processing is required.) * </p> * * @param state the {@link HttpState state} information associated with this method * @param conn the {@link HttpConnection connection} used to execute * this HTTP method * * @throws IOException if an I/O (transport) error occurs. Some transport exceptions * can be recovered from. * @throws HttpException if a protocol exception occurs. Usually protocol exceptions * cannot be recovered from. */ protected void readResponse(HttpState state, HttpConnection conn) throws IOException, HttpException { LOG.trace( "enter HttpMethodBase.readResponse(HttpState, HttpConnection)"); // Status line & line may have already been received // if 'expect - continue' handshake has been used while (this.statusLine == null) { readStatusLine(state, conn); processStatusLine(state, conn); readResponseHeaders(state, conn); processResponseHeaders(state, conn); int status = this.statusLine.getStatusCode(); if ((status >= 100) && (status < 200)) { if (LOG.isInfoEnabled()) { LOG.info("Discarding unexpected response: " + this.statusLine.toString()); } this.statusLine = null; } } readResponseBody(state, conn); processResponseBody(state, conn); } /** * Read the response body from the given {@link HttpConnection}. * * <p> * The current implementation wraps the socket level stream with * an appropriate stream for the type of response (chunked, content-length, * or auto-close). If there is no response body, the connection associated * with the request will be returned to the connection manager. * </p> * * <p> * Subclasses may want to override this method to to customize the * processing. * </p> * * @param state the {@link HttpState state} information associated with this method * @param conn the {@link HttpConnection connection} used to execute * this HTTP method * * @throws IOException if an I/O (transport) error occurs. Some transport exceptions * can be recovered from. * @throws HttpException if a protocol exception occurs. Usually protocol exceptions * cannot be recovered from. * * @see #readResponse * @see #processResponseBody */ protected void readResponseBody(HttpState state, HttpConnection conn) throws IOException, HttpException { LOG.trace( "enter HttpMethodBase.readResponseBody(HttpState, HttpConnection)"); // assume we are not done with the connection if we get a stream InputStream stream = readResponseBody(conn); if (stream == null) { // done using the connection! responseBodyConsumed(); } else { conn.setLastResponseInputStream(stream); setResponseStream(stream); } } /** * Returns the response body as an {@link InputStream input stream} * corresponding to the values of the <tt>Content-Length</tt> and * <tt>Transfer-Encoding</tt> headers. If no response body is available * returns <tt>null</tt>. * <p> * * @see #readResponse * @see #processResponseBody * * @param conn the {@link HttpConnection connection} used to execute * this HTTP method * * @throws IOException if an I/O (transport) error occurs. Some transport exceptions * can be recovered from. * @throws HttpException if a protocol exception occurs. Usually protocol exceptions * cannot be recovered from. */ private InputStream readResponseBody(HttpConnection conn) throws HttpException, IOException { LOG.trace("enter HttpMethodBase.readResponseBody(HttpConnection)"); responseBody = null; InputStream is = conn.getResponseInputStream(); if (Wire.CONTENT_WIRE.enabled()) { is = new WireLogInputStream(is, Wire.CONTENT_WIRE); } InputStream result = null; Header transferEncodingHeader = responseHeaders.getFirstHeader("Transfer-Encoding"); // We use Transfer-Encoding if present and ignore Content-Length. // RFC2616, 4.4 item number 3 if (transferEncodingHeader != null) { String transferEncoding = transferEncodingHeader.getValue(); if (!"chunked".equalsIgnoreCase(transferEncoding) && !"identity".equalsIgnoreCase(transferEncoding)) { if (LOG.isWarnEnabled()) { LOG.warn("Unsupported transfer encoding: " + transferEncoding); } } HeaderElement[] encodings = transferEncodingHeader.getElements(); // The chunked encoding must be the last one applied // RFC2616, 14.41 int len = encodings.length; if ((len > 0) && ("chunked".equalsIgnoreCase(encodings[len - 1].getName()))) { // if response body is empty if (conn.isResponseAvailable(conn.getParams().getSoTimeout())) { result = new ChunkedInputStream(is, this); } else { if (getParams().isParameterTrue(HttpMethodParams.STRICT_TRANSFER_ENCODING)) { throw new ProtocolException("Chunk-encoded body declared but not sent"); } else { LOG.warn("Chunk-encoded body missing"); } } } else { LOG.info("Response content is not chunk-encoded"); // The connection must be terminated by closing // the socket as per RFC 2616, 3.6 setConnectionCloseForced(true); result = is; } } else { long expectedLength = getResponseContentLength(); if (expectedLength == -1) { Header connectionHeader = responseHeaders.getFirstHeader("Connection"); String connectionDirective = null; if (connectionHeader != null) { connectionDirective = connectionHeader.getValue(); } if (this.effectiveVersion.greaterEquals(HttpVersion.HTTP_1_1) && !"close".equalsIgnoreCase(connectionDirective)) { LOG.info("Response content length is not known"); setConnectionCloseForced(true); } result = is; } else { result = new ContentLengthInputStream(is, expectedLength); } } // See if the response is supposed to have a response body if (!canResponseHaveBody(statusLine.getStatusCode())) { result = null; } // if there is a result - ALWAYS wrap it in an observer which will // close the underlying stream as soon as it is consumed, and notify // the watcher that the stream has been consumed. if (result != null) { result = new AutoCloseInputStream( result, new ResponseConsumedWatcher() { public void responseConsumed() { responseBodyConsumed(); } } ); } return result; } /** * Reads the response headers from the given {@link HttpConnection connection}. * * <p> * Subclasses may want to override this method to to customize the * processing. * </p> * * <p> * "It must be possible to combine the multiple header fields into one * "field-name: field-value" pair, without changing the semantics of the * message, by appending each subsequent field-value to the first, each * separated by a comma." - HTTP/1.0 (4.3) * </p> * * @param state the {@link HttpState state} information associated with this method * @param conn the {@link HttpConnection connection} used to execute * this HTTP method * * @throws IOException if an I/O (transport) error occurs. Some transport exceptions * can be recovered
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -