/* * Copyright 2013 Couchbase, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.couchbase.mock.http; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import java.io.*; import java.net.URL; import java.net.URLDecoder; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import org.apache.http.*; import org.apache.http.entity.ContentType; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpRequestHandler; import org.apache.http.util.EntityUtils; import org.couchbase.mock.control.CommandNotFoundException; import org.couchbase.mock.control.MockCommandDispatcher; import org.couchbase.mock.control.handlers.MockHelpCommandHandler; import org.couchbase.mock.httpio.HandlerUtil; /** * * @author Mark Nunberg <mnunberg@haskalah.org> */ public class ControlHandler implements HttpRequestHandler { private final MockCommandDispatcher dispatcher; private class WantHelpException extends Exception { } public ControlHandler(MockCommandDispatcher dispatcher) { this.dispatcher = dispatcher; } /** * Sends a help text with the provided code * @param response The response * @param code The HTTP status code to be used in the response */ private static void sendHelpText(HttpResponse response, int code) throws IOException { HandlerUtil.makeStringResponse(response, MockHelpCommandHandler.getIndentedHelp()); response.setStatusCode(code); } private JsonObject getQueryPayload(URL url, HttpRequest request) throws HttpException, IOException { // First check the URL itself to see if there's a payload JsonObject payload; payload = HandlerUtil.getJsonQuery(url); if (payload != null) { return payload; } // Next, check the actual request body.. if (!(request instanceof HttpEntityEnclosingRequest)) { return null; } String encoded = EntityUtils.toString(((HttpEntityEnclosingRequest)request).getEntity()); // Determine how to parse this.. Header header = request.getLastHeader(HttpHeaders.CONTENT_TYPE); if (header == null || header.getValue().equals(ContentType.APPLICATION_FORM_URLENCODED.getMimeType())) { // Parse as URL: url = new URL("http://foo.com?" + encoded); return HandlerUtil.getJsonQuery(url); } else if (header.getValue().equals(ContentType.APPLICATION_JSON.getMimeType())) { JsonParser parser = new JsonParser(); JsonElement elem = parser.parse(encoded); if (elem != null) { return elem.getAsJsonObject(); } else { return null; } } else { return null; } } @Override public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { URL url = HandlerUtil.getUrl(request); String path = url.getPath(); path = path.replaceFirst("^/+", ""); String[] components = path.split("/"); try { if (components.length != 2) { throw new CommandNotFoundException("/mock/<COMMAND>", null); } if (components[1].equals("help")) { throw new WantHelpException(); } JsonObject payload = getQueryPayload(url, request); String cmdStr = URLDecoder.decode(components[1], "UTF-8"); String rStr = dispatcher.dispatch(cmdStr, payload).toString(); HandlerUtil.makeJsonResponse(response, rStr); } catch (WantHelpException e) { sendHelpText(response, 200); } catch (CommandNotFoundException e) { sendHelpText(response, 404); } catch (RuntimeException e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(new PrintWriter(pw)); HandlerUtil.makeStringResponse(response, sw.toString()); HandlerUtil.bailResponse(context, response); throw e; } } }