package com.goebl.david; import java.net.HttpURLConnection; /** * Holds data about the response message returning from HTTP request. * * @author hgoebl */ public class Response<T> { final Request request; int statusCode; String responseMessage; T body; Object errorBody; HttpURLConnection connection; Response(Request request) { this.request = request; } void setBody(Object body) { this.body = (T) body; } /** * Access to the <code>Request</code> object (which will not be very useful in most cases). * @return the request object which was responsible for creating this response. */ public Request getRequest() { return request; } /** * Returns the payload of the response converted to the given type. * @return the converted payload (can be null). */ public T getBody() { return body; } /** * Get the body which was returned in case of error (HTTP-Code >= 400). * <br> * The type of the error body depends on following factors: * <ul> * <li> * <code>Content-Type</code> header (overrules the expected return type of the response) * </li> * <li> * The expected type (see <code>asXyz()</code>). We try to coerce the error body to this type. * In case of REST services, where often a JSONObject is the normal response body, the error body * will be converted to JSONObject if possible. <code>JSONArray</code> is not expected to be the * error body. * </li> * </ul> * If converting the error body is not successful, <code>String</code> and <code>byte[]</code> is used as * a fallback. You have to check the type with <code>instanceof</code> or try/catch the cast. * @return the error body converted to an object (see above) or <code>null</code> if there is no body or * no error. */ public Object getErrorBody() { return errorBody; } /** * See <a href="http://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html#responseCode"> * HttpURLConnection.responseCode</a> * @return An int representing the three digit HTTP Status-Code. */ public int getStatusCode() { return statusCode; } /** * The first line returned by the web-server, like "HTTP/1.1 200 OK". * @return first header */ public String getStatusLine() { return connection.getHeaderField(null); } /** * Was the request successful (returning a 2xx status code)? * @return <code>true</code> when status code is between 200 and 299, else <code>false</code> */ public boolean isSuccess() { return (statusCode / 100) == 2; // 200, 201, 204, ... } /** * Returns the text explaining the status code. * @return e.g. "Moved Permanently", "Created", ... */ public String getResponseMessage() { return responseMessage; } /** * Returns the MIME-type of the response body. * <br> * See <a href="http://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#getContentType()"> * URLConnection.getContentType()</a> * * @return e.g. "application/json", "text/plain", ... */ public String getContentType() { return connection.getContentType(); } /** * Returns the date when the request was created (server-time). * <br> * See <a href="http://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#getDate()"> * URLConnection.getDate()</a> * * @return the parsed "Date" header as millis or <code>0</code> if this header was not set. */ public long getDate() { return connection.getDate(); } /** * Returns the value of the expires header field. * <br> * See <a href="http://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#getExpiration()"> * URLConnection.getExpiration()</a> * * @return the expiration date of the resource, or 0 if not known. */ public long getExpiration() { return connection.getExpiration(); } /** * Returns the value of the last-modified header field. * <br> * See <a href="http://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#getLastModified()"> * URLConnection.getLastModified()</a> * * @return the date the resource was last modified, or 0 if not known. */ public long getLastModified() { return connection.getLastModified(); } /** * Returns the value of the named header field. * <br> * See <a href="http://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#getHeaderField(java.lang.String)"> * URLConnection.getHeaderField()</a> * * @param name name of the header field * @return the value of the named header field, or null */ public String getHeaderField (String name) { return connection.getHeaderField(name); } /** * Returns the value of the named field parsed as date (Millis since 1970). * <br> * See <a href="http://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#getHeaderFieldDate(java.lang.String,+long)"> * URLConnection.getHeaderFieldDate()</a> * * @param field name of the header field * @param defaultValue the default value if the field is not present or malformed * @return the value of the named header field, or the given default value */ public long getHeaderFieldDate (String field, long defaultValue) { return connection.getHeaderFieldDate(field, defaultValue); } /** * Returns the value of the named field parsed as a number. * <br> * See <a href="http://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#getHeaderFieldInt(java.lang.String,+int)"> * URLConnection.getHeaderFieldInt()</a> * * @param field name of the header field * @param defaultValue the default value if the field is not present or malformed * @return the value of the named header field, or the given default value */ public int getHeaderFieldInt(String field, int defaultValue) { return connection.getHeaderFieldInt(field, defaultValue); } /** * Get the "real" connection, typically to call some getters which are not provided by this Response object. * @return the connection object (many methods throw IllegalStateException depending on the internal state). */ public HttpURLConnection getConnection() { return connection; } /** * A shortcut to check for successful status codes and throw exception in case of non-2xx status codes. * <br> * In many cases you will call {@link com.goebl.david.Request#ensureSuccess()} instead of this method. * But there might be cases where you want to inspect the response-object first (check header values) and * then have a short exit where the response-code is not suitable for further normal processing. */ public void ensureSuccess() { if (!isSuccess()) { throw new WebbException("Request failed: " + statusCode + " " + responseMessage, (Response) this); } } }