/** * Sets the <tt>Expect</tt> header if it has not already been set, * in addition to the "standard" set of headers. * * @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 addRequestHeaders(HttpState state, HttpConnection conn) throws IOException, HttpException { LOG.trace("enter ExpectContinueMethod.addRequestHeaders(HttpState, HttpConnection)"); super.addRequestHeaders(state, conn); // If the request is being retried, the header may already be present boolean headerPresent = (getRequestHeader("Expect") != null); // See if the expect header should be sent // = HTTP/1.1 or higher // = request body present if (getParams().isParameterTrue(HttpMethodParams.USE_EXPECT_CONTINUE) && getEffectiveVersion().greaterEquals(HttpVersion.HTTP_1_1) && hasRequestContent()) { if (!headerPresent) { setRequestHeader("Expect", "100-continue"); } } else { if (headerPresent) { removeRequestHeader("Expect"); } } }
@Override protected void writeRequest(HttpState state, HttpConnection conn) throws IOException { try { BufferedChunkedOutputStream bufferedChunkedOutputStream = new BufferedChunkedOutputStream(conn, state, this); this.writer.write(bufferedChunkedOutputStream); bufferedChunkedOutputStream.finish(); conn.flushRequestOutputStream(); } catch (IOException e) { this.cleanupConnection(conn); throw e; } }
@Override protected void writeRequest(HttpState state, HttpConnection conn) throws IOException { try { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(2048); this.writer.write(outputStream); outputStream.close(); this.result = outputStream.toByteArray(); this.setRequestEntity(this); this.writeRequestLine(state, conn); this.writeRequestHeaders(state, conn); conn.writeLine(); // close head // make sure the status line and headers have been sent conn.flushRequestOutputStream(); this.writeRequestBody(state, conn); conn.flushRequestOutputStream(); } catch (IOException e) { this.cleanupConnection(conn); throw e; } }
/** * Adds a <tt>Content-Type</tt> request header. * * @param state current state of http requests * @param conn the connection to use for I/O * * @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. * * @since 3.0 */ protected void addContentTypeRequestHeader(HttpState state, HttpConnection conn) throws IOException, HttpException { LOG.trace("enter EntityEnclosingMethod.addContentTypeRequestHeader(" + "HttpState, HttpConnection)"); if (!parameters.isEmpty()) { StringBuffer buffer = new StringBuffer(MULTIPART_FORM_CONTENT_TYPE); if (Part.getBoundary() != null) { buffer.append("; boundary="); buffer.append(Part.getBoundary()); } setRequestHeader("Content-Type", buffer.toString()); } }
/** * <p> * This implementation will parse the <tt>Allow</tt> header to obtain * the set of methods supported by the resource identified by the Request-URI. * </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 * @since 2.0 */ protected void processResponseHeaders(HttpState state, HttpConnection conn) { LOG.trace("enter OptionsMethod.processResponseHeaders(HttpState, HttpConnection)"); Header allowHeader = getResponseHeader("allow"); if (allowHeader != null) { String allowHeaderValue = allowHeader.getValue(); StringTokenizer tokenizer = new StringTokenizer(allowHeaderValue, ","); while (tokenizer.hasMoreElements()) { String methodAllowed = tokenizer.nextToken().trim().toUpperCase(); methodsAllowed.addElement(methodAllowed); } } }
/** * Generates <tt>Content-Length</tt> or <tt>Transfer-Encoding: Chunked</tt> * request header, as long as no <tt>Content-Length</tt> request header * already exists. * * @param state current state of http requests * @param conn the connection to use for I/O * * @throws IOException when errors occur reading or writing to/from the * connection * @throws HttpException when a recoverable error occurs */ protected void addContentLengthRequestHeader(HttpState state, HttpConnection conn) throws IOException, HttpException { LOG.trace("enter EntityEnclosingMethod.addContentLengthRequestHeader(" + "HttpState, HttpConnection)"); if ((getRequestHeader("content-length") == null) && (getRequestHeader("Transfer-Encoding") == null)) { long len = getRequestContentLength(); if (len < 0) { if (getEffectiveVersion().greaterEquals(HttpVersion.HTTP_1_1)) { addRequestHeader("Transfer-Encoding", "chunked"); } else { throw new ProtocolException(getEffectiveVersion() + " does not support chunk encoding"); } } else { addRequestHeader("Content-Length", String.valueOf(len)); } } }
/** * Closes connections that have been idle for at least the given amount of time. * * @param idleTime the minimum idle time, in milliseconds, for connections to be closed */ public void closeIdleConnections(long idleTime) { // the latest time for which connections will be closed long idleTimeout = System.currentTimeMillis() - idleTime; if (LOG.isDebugEnabled()) { LOG.debug("Checking for connections, idleTimeout: " + idleTimeout); } Iterator connectionIter = connectionToAdded.keySet().iterator(); while (connectionIter.hasNext()) { HttpConnection conn = (HttpConnection) connectionIter.next(); Long connectionTime = (Long) connectionToAdded.get(conn); if (connectionTime.longValue() <= idleTimeout) { if (LOG.isDebugEnabled()) { LOG.debug("Closing connection, connection time: " + connectionTime); } connectionIter.remove(); conn.close(); } } }
/** * Overridden to process the sync-token. Adapted from DavMethodBase. * * @see DavMethodBase#processResponseBody(HttpState, HttpConnection) */ @Override protected void processResponseBody(HttpState httpState, HttpConnection httpConnection) { if (getStatusCode() == DavServletResponse.SC_MULTI_STATUS) { try { Document document = getResponseBodyAsDocument(); if (document != null) { synctoken = DomUtil.getChildText(document.getDocumentElement(), SyncReportInfo.XML_SYNC_TOKEN, DavConstants.NAMESPACE); log.info("Sync-Token for REPORT: " + synctoken); multiStatus = MultiStatus.createFromXml(document.getDocumentElement()); processMultiStatusBody(multiStatus, httpState, httpConnection); } } catch (IOException e) { log.error("Error while parsing sync-token.", e); setSuccess(false); } } }
protected boolean checkMidfetchAbort( CrawlURI curi, HttpRecorderMethod method, HttpConnection conn) { // We'll check for prerequisites here since there is no way to know // if the super method returns false because of a prereq or because // all filters accepeted. if(curi.isPrerequisite()){ return false; } // Run super to allow filters to also abort. Also this method has // been pressed into service as a general 'stuff to do at this point' boolean ret = super.checkMidfetchAbort(curi, method, conn); // Ok, now check for duplicates. if(isDuplicate(curi)){ ret = true; unchangedURLs++; curi.putInt(A_CONTENT_STATE_KEY, CONTENT_UNCHANGED); curi.addAnnotation("header-duplicate"); } return ret; }
private String getHost(HttpMethod httpMethod, Object[] args) { try { final URI url = httpMethod.getURI(); if (url.isAbsoluteURI()) { return getEndpoint(url.getHost(), url.getPort()); } if (isDebug) { logger.debug("URI is not absolute. {}", url.getURI()); } // if not found schema, use httpConnection. final HttpConnection httpConnection = getHttpConnection(args); if (httpConnection != null) { final String host = httpConnection.getHost(); final int port = getPort(httpConnection); return getEndpoint(host, port); } } catch (URIException e) { // unexpected error, perhaps of user fault. logger.error("[HttpClient3] Fail get URI", e); } return null; }
private String getHttpUrl(String host, int port, URI uri, HttpConnection httpConnection) throws URIException { final Protocol protocol = httpConnection.getProtocol(); if (protocol == null) { return uri.getURI(); } final StringBuilder sb = new StringBuilder(); final String scheme = protocol.getScheme(); sb.append(scheme).append("://"); sb.append(host); // if port is default port number. if (port != SKIP_DEFAULT_PORT) { sb.append(':').append(port); } sb.append(uri.getURI()); return sb.toString(); }
/** * Since the same connection is about to be reused, make sure the * previous request was completely processed, and if not * consume it now. * @param conn The connection * @return true, if the connection is reusable */ private static boolean finishLastResponse(final HttpConnection conn) { InputStream lastResponse = conn.getLastResponseInputStream(); if(lastResponse != null) { conn.setLastResponseInputStream(null); try { lastResponse.close(); return true; } catch (IOException ioe) { // force reconnect. return false; } } else { return false; } }
public void run() { try { while (!Thread.interrupted()) { Thread.sleep(SLEEP_INTERVAL); List<HttpConnection> s; synchronized (connections) { s = connections; connections = new ArrayList<HttpConnection>(); } logger.log(Level.INFO, "Closing " + s.size() + " HttpConnections"); for(final Iterator<HttpConnection> it = s.iterator(); it.hasNext();) { HttpConnection conn = it.next(); conn.close(); conn.setHttpConnectionManager(null); it.remove(); } } } catch (InterruptedException e) { return; } }
/** * Since the same connection is about to be reused, make sure the * previous request was completely processed, and if not * consume it now. * * @param conn The connection */ static void finishLastResponse(HttpConnection conn) { InputStream lastResponse = conn.getLastResponseInputStream(); if (lastResponse != null) { conn.setLastResponseInputStream(null); try { lastResponse.close(); } catch (IOException ioe) { //FIXME: badness - close to force reconnect. conn.close(); } } }
/** * Parse response. * * @param input Input stream */ public void parseResponse(InputStream input, HttpState state, HttpConnection conn) throws IOException, HttpException { try { int code = getStatusLine().getStatusCode(); if (code == WebdavStatus.SC_CONFLICT || code == WebdavStatus.SC_MULTI_STATUS || code == WebdavStatus.SC_FORBIDDEN ) { parseXMLResponse(input); } } catch (IOException e) { // FIX ME: provide a way to deliver non xml data } }
/** * Generate additional headers needed by the request. * * @param state State token * @param conn The connection being used to make the request. */ public void addRequestHeaders(HttpState state, HttpConnection conn) throws IOException, HttpException { // set the default utf-8 encoding, if not already present if (getRequestHeader("Content-Type") == null ) super.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); super.addRequestHeaders(state, conn); switch (depth) { case DEPTH_0: super.setRequestHeader("Depth", "0"); break; case DEPTH_1: super.setRequestHeader("Depth", "1"); break; case DEPTH_INFINITY: super.setRequestHeader("Depth", "infinity"); break; } }
protected void processResponseHeaders(HttpState state, HttpConnection conn) { super.processResponseHeaders(state, conn); Header header; header = getResponseHeader(HEADER_SUBSCRIPTION_ID); if (header != null) { this.responsedSubscriptionId = Integer.parseInt(header.getValue()); } header = getResponseHeader(HEADER_SUBSCRIPTION_LIFETIME); if (header != null) { this.responsedSubscriptionLifetime = Long.parseLong(header.getValue()); } header = getResponseHeader(HEADER_CONTENT_LOCATION); if (header != null) { this.responsedContentLocation = header.getValue(); } }
/** * Generate additional headers needed by the request. * * @param state State token * @param conn The connection being used for the request. */ public void addRequestHeaders(HttpState state, HttpConnection conn) throws IOException, HttpException { super.addRequestHeaders(state, conn); // set the default utf-8 encoding, if not already present if (getRequestHeader("Content-Type") == null ) super.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); switch (getDepth()) { case DEPTH_0 : super.setRequestHeader("Depth", "0"); break; case DEPTH_1 : super.setRequestHeader("Depth", "1"); break; case DEPTH_INFINITY : super.setRequestHeader("Depth", "infinity"); break; } }
/** * A client of the {@link MoveMethod} can specify a destination as either an * absolute URL (possibly to a different server), or as a absolute path on * the same server, but this function makes sure that the path sent to the * server is always an absolute URL. * * <p>Note that this function will add server and port to the request - * however, port is not added if it is the default port for the scheme * in question. </p> * * <p>This function is static so that it can be reused by the {@link CopyMethod}. * </p> * * @param conn The connection for the current request, in case the caller * specifies an absolute path. * * @param absolutePathOrURL If an absolute URL, nothing done, but if an absolute * path, it is converted into an absolute URL. * * @return An absolute URL */ static String getAbsoluteDestination(HttpConnection conn, String absolutePathOrURL) { String absoluteDestination = absolutePathOrURL; // is this an absolute path? if (absolutePathOrURL.startsWith("/")) { // yes - get the protocol to start the URL with the appropriate scheme. Protocol protocol = conn.getProtocol(); StringBuffer bufDest = new StringBuffer(protocol.getScheme()); bufDest.append("://").append(conn.getHost()); // only add in the port if it is not the default port. if (conn.getPort() != protocol.getDefaultPort()) { bufDest.append(':').append(conn.getPort()); } // append the path. bufDest.append(absolutePathOrURL); absoluteDestination = bufDest.toString(); } return absoluteDestination; }
/** * Generate additional headers needed by the request. * * @param state HttpState token * @param conn The connection being used for the request. */ public void addRequestHeaders(HttpState state, HttpConnection conn) throws IOException, HttpException { super.addRequestHeaders(state, conn); String absoluteDestination = MoveMethod.getAbsoluteDestination(conn, destination); super.setRequestHeader("Destination", absoluteDestination); if (!isOverwrite()) super.setRequestHeader("Overwrite", "F"); switch (depth) { case DepthSupport.DEPTH_0: super.setRequestHeader("Depth", "0"); break; case DepthSupport.DEPTH_INFINITY: super.setRequestHeader("Depth", "Infinity"); break; } }
/** * Parse response. * * @param input Input stream */ public void parseResponse(InputStream input, HttpState state, HttpConnection conn) throws IOException, HttpException { try { int code = getStatusLine().getStatusCode(); if (code == WebdavStatus.SC_BAD_REQUEST || code == WebdavStatus.SC_MULTI_STATUS || code == WebdavStatus.SC_FORBIDDEN || code == WebdavStatus.SC_CONFLICT ) { parseXMLResponse(input); } } catch (IOException e) { // FIX ME: provide a way to deliver non xml data } }
public void reallyWriteHeaders(HttpState state, HttpConnection conn) throws IOException { this.writeRequestLine(state, conn); this.writeRequestHeaders(state, conn); conn.writeLine(); // close head // make sure the status line and headers have been sent conn.flushRequestOutputStream(); }
public BufferedChunkedOutputStream( HttpConnection conn, HttpState state, StreamedPostMethod streamedPostMethod) throws IOException { this.streamedPostMethod = streamedPostMethod; this.state = state; this.httpConnection = conn; this.cache = new byte[2048]; this.stream = this.httpConnection.getRequestOutputStream(); }
@Override protected boolean writeRequestBody(HttpState httpState, HttpConnection httpConnection) throws IOException { OutputStream outstream = httpConnection.getRequestOutputStream(); outstream.write(StreamBasedInvocator.PING_REQUEST); outstream.flush(); return true; }
@Override protected boolean writeRequestBody(HttpState httpState, HttpConnection httpConnection) throws IOException { OutputStream outstream = httpConnection.getRequestOutputStream(); outstream.write(StreamBasedInvocator.CREATE_SESSION_REQUEST); outstream.flush(); return true; }
/** * Overrides {@link HttpMethodBase} method to <i>not</i> read a response * body, despite the presence of a <tt>Content-Length</tt> or * <tt>Transfer-Encoding</tt> header. * * @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 * * @since 2.0 */ protected void readResponseBody(HttpState state, HttpConnection conn) throws HttpException, IOException { LOG.trace( "enter HeadMethod.readResponseBody(HttpState, HttpConnection)"); int bodyCheckTimeout = getParams().getIntParameter(HttpMethodParams.HEAD_BODY_CHECK_TIMEOUT, -1); if (bodyCheckTimeout < 0) { responseBodyConsumed(); } else { if (LOG.isDebugEnabled()) { LOG.debug("Check for non-compliant response body. Timeout in " + bodyCheckTimeout + " ms"); } boolean responseAvailable = false; try { responseAvailable = conn.isResponseAvailable(bodyCheckTimeout); } catch (IOException e) { LOG.debug("An IOException occurred while testing if a response was available," + " we will assume one is not.", e); responseAvailable = false; } if (responseAvailable) { if (getParams().isParameterTrue(HttpMethodParams.REJECT_HEAD_BODY)) { throw new ProtocolException( "Body content may not be sent in response to HTTP HEAD request"); } else { LOG.warn("Body content returned in response to HTTP HEAD"); } super.readResponseBody(state, conn); } } }
private static boolean doAuthenticateDefault( HttpMethod method, HttpConnection conn, HttpState state, boolean proxy) throws AuthenticationException { if (method == null) { throw new IllegalArgumentException("HTTP method may not be null"); } if (state == null) { throw new IllegalArgumentException("HTTP state may not be null"); } String host = null; if (conn != null) { host = proxy ? conn.getProxyHost() : conn.getHost(); } Credentials credentials = proxy ? state.getProxyCredentials(null, host) : state.getCredentials(null, host); if (credentials == null) { return false; } if (!(credentials instanceof UsernamePasswordCredentials)) { throw new InvalidCredentialsException( "Credentials cannot be used for basic authentication: " + credentials.toString()); } String auth = BasicScheme.authenticate( (UsernamePasswordCredentials) credentials, method.getParams().getCredentialCharset()); if (auth != null) { String s = proxy ? PROXY_AUTH_RESP : WWW_AUTH_RESP; Header header = new Header(s, auth, true); method.addRequestHeader(header); return true; } else { return false; } }
/** * Registers the given connection with this handler. The connection will be held until * {@link #remove(HttpConnection)} or {@link #closeIdleConnections(long)} is called. * * @param connection the connection to add * * @see #remove(HttpConnection) */ public void add(HttpConnection connection) { Long timeAdded = new Long(System.currentTimeMillis()); if (LOG.isDebugEnabled()) { LOG.debug("Adding connection at: " + timeAdded); } connectionToAdded.put(connection, timeAdded); }
private void recordDestination(final Trace trace, final HttpMethod httpMethod, final Object[] args) { final SpanEventRecorder recorder = trace.currentSpanEventRecorder(); try { final URI uri = httpMethod.getURI(); final HttpConnection httpConnection = getHttpConnection(args); // if uri have schema or not found HttpConnection argument. if (uri.isAbsoluteURI() || httpConnection == null) { recorder.recordAttribute(AnnotationKey.HTTP_URL, InterceptorUtils.getHttpUrl(uri.getURI(), param)); recorder.recordDestinationId(getEndpoint(uri.getHost(), uri.getPort())); return; } if (isDebug) { logger.debug("URI is not absolute. {}", uri.getURI()); } // use HttpConnection argument. final String host = httpConnection.getHost(); final int port = getPort(httpConnection); final String httpUrl = getHttpUrl(host, port, uri, httpConnection); recorder.recordAttribute(AnnotationKey.HTTP_URL, InterceptorUtils.getHttpUrl(httpUrl, param)); recorder.recordDestinationId(getEndpoint(host, port)); } catch (URIException e) { logger.error("Fail get URI", e); recorder.recordDestinationId("unknown"); } }
private int getPort(HttpConnection httpConnection) { final int port = httpConnection.getPort(); final Protocol protocol = httpConnection.getProtocol(); // if port is default port number. if (protocol != null && port == protocol.getDefaultPort()) { // skip return SKIP_DEFAULT_PORT; } return port; }
private HttpConnection getHttpConnection(final Object[] args) { if (args != null && args.length > 1 && args[1] instanceof HttpConnection) { return (HttpConnection) args[1]; } return null; }