package org.mitre.test;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.util.EntityUtils;
import org.mitre.rhex.security.RhexMitreOidcSecurityChecker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URISyntaxException;
/**
* @author Jason Mathews, MITRE Corp.
*
* Date: 2/22/12 4:46 PM
*/
public final class ClientHelper {
private static final Logger log = LoggerFactory.getLogger(ClientHelper.class);
/**
* Dump HTTP Response status code and headers
*
* @param req Optional Http request may be null
* @param response Http Response, never null
*/
public static void dumpResponse(HttpRequestBase req, HttpResponse response) {
dumpResponse(req, response, false);
}
/**
* Dump HTTP Response status code and headers
*
* @param req Optional Http request may be null
* @param response Http Response, never null
* @param dumpEntity True if want to dump the response body otherwise body entity is ignored
*/
public static void dumpResponse(HttpRequestBase req, HttpResponse response, boolean dumpEntity) {
if (req != null)
System.out.printf("%s Response %s%n", req.getMethod(), response.getStatusLine());
else
System.out.println("Response " + response.getStatusLine());
System.out.println("Headers:");
for (Header header : response.getAllHeaders()) {
String name = header.getName();
// suppress set-cookie header in output unless debug enabled
if (log.isDebugEnabled() || !"Set-Cookie".equals(name)) {
System.out.println("\t" + name + ": " + header.getValue());
}
}
if (dumpEntity) {
HttpEntity entity = response.getEntity();
if (entity != null)
try {
String bodyText = EntityUtils.toString(entity);
System.out.println("----------------------------------------");
if (bodyText != null && bodyText.length() > 68)
System.out.println("Response body:");
else
System.out.print("Response body: ");
System.out.println(bodyText);
} catch(Exception e) {
log.debug("Failed to get response body", e);
}
else
System.out.println("XXX: No body");
}
System.out.println("----------------------------------------");
}
/**
* Return content-type value with optional character encoding
* stripped off.
*
* @param entity HttpEntity returned from HttpResponse
* @return content-type from HTTP response header, null if not present
*/
@CheckForNull
public static String getContentType(HttpEntity entity) {
return getContentType(entity, false);
}
/**
* Return content-type value and optionally strip off the character encoding
* following the content MIME type.
*
* @param entity HttpEntity returned from HttpResponse
* @param includeEncoding Flag if true it include character encoding if provided
* otherwise strip encoding from the content type
* @return content-type from HTTP response header, null if not present
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17
*/
@CheckForNull
public static String getContentType(HttpEntity entity, boolean includeEncoding) {
// NOTE: similar to EntityUtils.getContentMimeType(HttpEntity)
if (entity == null) return null;
Header header = entity.getContentType();
if (header == null) return null;
String type = header.getValue();
if (type != null) {
if (!includeEncoding) {
// remove character encoding from mime type
// Content-Type = text/html; charset=ISO-8859-4 => text/html
int ind = type.indexOf(';');
if (ind >= 0) type = type.substring(0, ind);
}
type = StringUtils.trimToNull(type);
}
return type;
}
public static boolean isXmlContentType(String contentType) {
if (contentType == null || contentType.indexOf('/') <= 0) return false;
if (contentType.endsWith("+xml")) return true; // e.g. application/atom+xml, application/rdf+xml, image/svg+xml, etc.
//if (TestUnit.MIME_APPLICATION_ATOM_XML.equals(contentType)) return true;
if (contentType.endsWith("/xml")) return true; // e.g. text/xml, application/xml
// REVIEW: missing any other XML mime types that may appear in section ATOM feeds ?
return false;
}
/**
* Get redirect location from response header and return as URI if available.
*
* @param response the HTTP response, never null
*
* @return URI for redirect location
*
* @throws NullPointerException if response is null
*/
@CheckForNull
public static URI getRedirectURI(HttpResponse response) {
final StatusLine statusLine = response.getStatusLine();
if (statusLine == null || statusLine.getStatusCode() != 302) {
return null;
}
Header location = response.getFirstHeader("Location");
if (location == null) return null;
String locationValue = location.getValue();
if (StringUtils.isBlank(locationValue)) return null;
try {
/*
// debug start
URI uri = new URI(locationValue);
if (log.isDebugEnabled()) {
String query = uri.getQuery();
if (query != null) {
System.out.println("XXX: params");
for(String s : query.split("&")) {
int ind = s.indexOf('=');
if (ind == -1) continue;
String name = s.substring(0,ind);
String value = s.substring(ind+1);
System.out.printf("\t%s=%s%n", name, value);
if ("request".equals(name)) {
// request parameter is base64-encoded JWT + binary token
// e.g. {"typ":"JWT","alg":"HS256"}{"id_token":{"claims"...
byte[] bytes = Base64.decodeBase64(value);
if (bytes != null) {
try {
value = new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
value = new String(bytes); // use default encoding
}
System.out.println("\t\t" + value);
}
}
//if ("nonce".equals(name)) {
//context.setProperty(userEmail.replaceAll("[^a-zA-Z0-9]+","_") + ".nonce", value);
//}
}
// log.debug("XXX: params\n\t" + query.replace("&", "\n\t"));
}
}
return uri;
// debug end
*/
return new URI(locationValue);
} catch (URISyntaxException e) {
log.error("", e);
return null;
}
}
}