package org.couchbase.mock.httpio; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import org.apache.http.*; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpCoreContext; import org.couchbase.mock.http.AuthContext; import java.io.*; import java.net.*; import java.util.HashMap; import java.util.Map; /** * Various utilities for use by handlers and {@link org.couchbase.mock.httpio.HttpServer} */ public class HandlerUtil { private HandlerUtil() {} /** * Get the raw httpcomponents ServerConnection object * @param cx The context * @return The connection for this request */ public static HttpServerConnection getConnection(HttpContext cx) { return (HttpServerConnection) cx.getAttribute(HttpCoreContext.HTTP_CONNECTION); } /** * Get the underlying raw Socket for this request * @param cx The context * @return The raw socket */ public static Socket getSocket(HttpContext cx) { return (Socket) cx.getAttribute(HttpServer.CX_SOCKET); } /** * @param request The request * @return a URL object for the request * @throws MalformedURLException */ public static URL getUrl(HttpRequest request) throws MalformedURLException{ String uriStr = request.getRequestLine().getUri(); try { return URI.create(uriStr).toURL(); } catch (IllegalArgumentException ex) { return URI.create("http://dummy/" + uriStr).toURL(); } } /** * Parses a url-encoded query string and * @param url The URL to decode * @return a map of keys and JSON Values * @throws MalformedURLException If one of the values is not JSON */ public static JsonObject getJsonQuery(URL url) throws MalformedURLException { String query = url.getQuery(); JsonObject payload = new JsonObject(); JsonParser parser = new JsonParser(); if (query == null) { return null; } for (String kv : query.split("&")) { String[] parts = kv.split("="); if (parts.length != 2) { throw new MalformedURLException(); } String optName = parts[0]; JsonElement optVal; try { optVal = parser.parse(URLDecoder.decode(parts[1], "UTF-8")); } catch (UnsupportedEncodingException e) { throw new MalformedURLException(); } payload.add(optName, optVal); } return payload; } /** * Get traditional query parameters as a Java map * @param s The query string * @return A Java map with key-value pairs derived from the query string * @throws MalformedURLException If the query string is malformed. */ public static Map<String,String> getQueryParams(String s) throws MalformedURLException { Map<String,String> params = new HashMap<String, String>(); for (String kv : s.split("&")) { String[] parts = kv.split("="); if (parts.length != 2) { throw new MalformedURLException(); } try { String k = URLDecoder.decode(parts[0], "UTF-8"); String v = URLDecoder.decode(parts[1], "UTF-8"); params.put(k, v); } catch (UnsupportedEncodingException ex) { throw new MalformedURLException(ex.getMessage()); } } return params; } /** * Sets a string as the response * @param response The response object * @param s The response body */ public static void makeStringResponse(HttpResponse response, String s) { StringEntity entity = new StringEntity(s, ContentType.TEXT_PLAIN); entity.setContentEncoding("utf-8"); response.setEntity(entity); } /** * Sets the response body and status * @param response The response object * @param msg The response body * @param status The response status */ public static void makeResponse(HttpResponse response, String msg, int status) { response.setStatusCode(status); makeStringResponse(response, msg); } /** * Sets a 404 not found response with a message * @param response The response object * @param msg The message */ public static void make400Response(HttpResponse response, String msg) { makeResponse(response, msg, HttpStatus.SC_BAD_REQUEST); } /** * Sets a JSON encoded response. The response's {@code Content-Type} header will be set to {@code application/json} * @param response The response object * @param encoded The JSON-encoded string */ public static void makeJsonResponse(HttpResponse response, String encoded) { StringEntity ent = new StringEntity(encoded, ContentType.APPLICATION_JSON); response.setEntity(ent); } /** * Send and flush the response object over the current connection and close the connection * @param cx The context * @param response The response object * @throws IOException * @throws HttpException */ public static void bailResponse(HttpContext cx, HttpResponse response) throws IOException, HttpException { HttpServerConnection conn = getConnection(cx); conn.sendResponseHeader(response); conn.sendResponseEntity(response); conn.flush(); } /** * Get any authorization credentials supplied over the connection. If no credentials were provided in the request, * an empty AuthContex is returned * @param cx The HTTP Context (from httpcomonents) * @param req The request * @return The authentication info * @throws IOException */ public static AuthContext getAuth(HttpContext cx, HttpRequest req) throws IOException { AuthContext auth = (AuthContext) cx.getAttribute(HttpServer.CX_AUTH); if (auth == null) { Header authHdr = req.getLastHeader(HttpHeaders.AUTHORIZATION); if (authHdr == null) { auth = new AuthContext(); } else { auth = new AuthContext(authHdr.getValue()); } } return auth; } }