/** * Tests if the {@link HttpMethod method} requires authentication. * * @param method HTTP method * @return boolean <tt>true</tt> if a retry is needed, <tt>false</tt> otherwise. */ private boolean isAuthenticationNeeded(final HttpMethod method) { method .getHostAuthState() .setAuthRequested(method.getStatusCode() == HttpStatus.SC_UNAUTHORIZED); method .getProxyAuthState() .setAuthRequested(method.getStatusCode() == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED); if (method.getHostAuthState().isAuthRequested() || method.getProxyAuthState().isAuthRequested()) { LOG.debug("Authorization required"); if (method.getDoAuthentication()) { // process authentication response return true; } else { // let the client handle the authenticaiton LOG.info("Authentication requested but doAuthentication is " + "disabled"); return false; } } else { return false; } }
private HTTPClientResponseResolver createResponseResolver( final HttpMethod httpMethod, final Status status, final Header[] headers) { try { when(httpMethod.getStatusLine()) .thenReturn( new org.apache.commons.httpclient.StatusLine( String.format("HTTP/1.1 %s %s\r\n", status.getCode(), status.getName()))); } catch (HttpException e) { throw new RuntimeException(e); } when(httpMethod.getStatusCode()).thenReturn(status.getCode()); when(httpMethod.getResponseHeaders()).thenReturn(headers); return new TestableHTTPClientResponseResolver(httpMethod); }
/** * Tests if the {@link HttpMethod method} requires a redirect to another location. * * @param method HTTP method * @return boolean <tt>true</tt> if a retry is needed, <tt>false</tt> otherwise. */ private boolean isRedirectNeeded(final HttpMethod method) { switch (method.getStatusCode()) { case HttpStatus.SC_MOVED_TEMPORARILY: case HttpStatus.SC_MOVED_PERMANENTLY: case HttpStatus.SC_SEE_OTHER: case HttpStatus.SC_TEMPORARY_REDIRECT: LOG.debug("Redirect required"); if (method.getFollowRedirects()) { return true; } else { return false; } default: return false; } // end of switch }
/** * Processes a response that requires authentication * * @param method the current {@link HttpMethod HTTP method} * @return <tt>true</tt> if the authentication challenge can be responsed to, (that is, at least * one of the requested authentication scheme is supported, and matching credentials have been * found), <tt>false</tt> otherwise. */ private boolean processAuthenticationResponse(final HttpMethod method) { LOG.trace("enter HttpMethodBase.processAuthenticationResponse(" + "HttpState, HttpConnection)"); try { switch (method.getStatusCode()) { case HttpStatus.SC_UNAUTHORIZED: return processWWWAuthChallenge(method); case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED: return processProxyAuthChallenge(method); default: return false; } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error(e.getMessage(), e); } return false; } }
/** * Makes a rest request of any type at the specified urlSuffix. The urlSuffix should be of the * form /userService/users. If CS throws an exception it handled and transalated to a Openfire * exception if possible. This is done using the check fault method that tries to throw the best * maching exception. * * @param type Must be GET or DELETE * @param urlSuffix The url suffix of the rest request * @param xmlParams The xml with the request params, must be null if type is GET or DELETE only * @return The response as a xml doc. * @throws ConnectionException Thrown if there are issues perfoming the request. * @throws Exception Thrown if the response from Clearspace contains an exception. */ public Element executeRequest(HttpType type, String urlSuffix, String xmlParams) throws ConnectionException, Exception { if (Log.isDebugEnabled()) { Log.debug("Outgoing REST call [" + type + "] to " + urlSuffix + ": " + xmlParams); } String wsUrl = getConnectionURI() + WEBSERVICES_PATH + urlSuffix; String secret = getSharedSecret(); HttpClient client = new HttpClient(); HttpMethod method; // Configures the authentication client.getParams().setAuthenticationPreemptive(true); Credentials credentials = new UsernamePasswordCredentials(OPENFIRE_USERNAME, secret); AuthScope scope = new AuthScope(host, port, AuthScope.ANY_REALM); client.getState().setCredentials(scope, credentials); // Creates the method switch (type) { case GET: method = new GetMethod(wsUrl); break; case POST: PostMethod pm = new PostMethod(wsUrl); StringRequestEntity requestEntity = new StringRequestEntity(xmlParams); pm.setRequestEntity(requestEntity); method = pm; break; case PUT: PutMethod pm1 = new PutMethod(wsUrl); StringRequestEntity requestEntity1 = new StringRequestEntity(xmlParams); pm1.setRequestEntity(requestEntity1); method = pm1; break; case DELETE: method = new DeleteMethod(wsUrl); break; default: throw new IllegalArgumentException(); } method.setRequestHeader("Accept", "text/xml"); method.setDoAuthentication(true); try { // Executes the request client.executeMethod(method); // Parses the result String body = method.getResponseBodyAsString(); if (Log.isDebugEnabled()) { Log.debug("Outgoing REST call results: " + body); } // Checks the http status if (method.getStatusCode() != 200) { if (method.getStatusCode() == 401) { throw new ConnectionException( "Invalid password to connect to Clearspace.", ConnectionException.ErrorType.AUTHENTICATION); } else if (method.getStatusCode() == 404) { throw new ConnectionException( "Web service not found in Clearspace.", ConnectionException.ErrorType.PAGE_NOT_FOUND); } else if (method.getStatusCode() == 503) { throw new ConnectionException( "Web service not avaible in Clearspace.", ConnectionException.ErrorType.SERVICE_NOT_AVAIBLE); } else { throw new ConnectionException( "Error connecting to Clearspace, http status code: " + method.getStatusCode(), new HTTPConnectionException(method.getStatusCode()), ConnectionException.ErrorType.OTHER); } } else if (body.contains("Clearspace Upgrade Console")) { // TODO Change CS to send a more standard error message throw new ConnectionException( "Clearspace is in an update state.", ConnectionException.ErrorType.UPDATE_STATE); } Element response = localParser.get().parseDocument(body).getRootElement(); // Check for exceptions checkFault(response); // Since there is no exception, returns the response return response; } catch (DocumentException e) { throw new ConnectionException( "Error parsing the response of Clearspace.", e, ConnectionException.ErrorType.OTHER); } catch (HttpException e) { throw new ConnectionException( "Error performing http request to Clearspace", e, ConnectionException.ErrorType.OTHER); } catch (UnknownHostException e) { throw new ConnectionException( "Unknown Host " + getConnectionURI() + " trying to connect to Clearspace", e, ConnectionException.ErrorType.UNKNOWN_HOST); } catch (IOException e) { throw new ConnectionException( "Error peforming http request to Clearspace.", e, ConnectionException.ErrorType.OTHER); } finally { method.releaseConnection(); } }
/** * Process the redirect response. * * @return <code>true</code> if the redirect was successful */ private boolean processRedirectResponse(final HttpMethod method) throws RedirectException { // get the location header to find out where to redirect to Header locationHeader = method.getResponseHeader("location"); if (locationHeader == null) { // got a redirect response, but no location header LOG.error("Received redirect response " + method.getStatusCode() + " but no location header"); return false; } String location = locationHeader.getValue(); if (LOG.isDebugEnabled()) { LOG.debug("Redirect requested to location '" + location + "'"); } // rfc2616 demands the location value be a complete URI // Location = "Location" ":" absoluteURI URI redirectUri = null; URI currentUri = null; try { currentUri = new URI( this.conn.getProtocol().getScheme(), null, this.conn.getHost(), this.conn.getPort(), method.getPath()); String charset = method.getParams().getUriCharset(); redirectUri = new URI(location, true, charset); if (redirectUri.isRelativeURI()) { if (this.params.isParameterTrue(HttpClientParams.REJECT_RELATIVE_REDIRECT)) { LOG.warn("Relative redirect location '" + location + "' not allowed"); return false; } else { // location is incomplete, use current values for defaults LOG.debug("Redirect URI is not absolute - parsing as relative"); redirectUri = new URI(currentUri, redirectUri); } } else { // Reset the default params method.getParams().setDefaults(this.params); } method.setURI(redirectUri); hostConfiguration.setHost(redirectUri); } catch (URIException ex) { throw new InvalidRedirectLocationException( "Invalid redirect location: " + location, location, ex); } if (this.params.isParameterFalse(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS)) { if (this.redirectLocations == null) { this.redirectLocations = new HashSet(); } this.redirectLocations.add(currentUri); try { if (redirectUri.hasQuery()) { redirectUri.setQuery(null); } } catch (URIException e) { // Should never happen return false; } if (this.redirectLocations.contains(redirectUri)) { throw new CircularRedirectException("Circular redirect to '" + redirectUri + "'"); } } if (LOG.isDebugEnabled()) { LOG.debug( "Redirecting from '" + currentUri.getEscapedURI() + "' to '" + redirectUri.getEscapedURI()); } // And finally invalidate the actual authentication scheme method.getHostAuthState().invalidate(); return true; }