package com.philemonworks.critter; import java.io.IOException; import java.net.URI; import javax.inject.Inject; import javax.inject.Named; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import com.philemonworks.critter.proto.Definitions; import com.philemonworks.critter.proto.DefinitionsPerRule; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestBase; import org.rendersnake.HtmlCanvas; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.jamonapi.Monitor; import com.jamonapi.MonitorFactory; import com.philemonworks.critter.action.Forward; import com.philemonworks.critter.action.Respond; import com.philemonworks.critter.action.ResponseBody; import com.philemonworks.critter.action.ResponseHeader; import com.philemonworks.critter.rule.Rule; import com.philemonworks.critter.rule.RuleContext; import com.sun.jersey.api.core.HttpContext; import com.sun.jersey.spi.container.ContainerRequest; @Path("/") @Consumes("*/*") public class ProxyResource { private static final Logger LOG = LoggerFactory.getLogger(ProxyResource.class); @Inject private TrafficManager trafficManager; @Inject private HttpClient httpClient; @Inject private DefinitionsPerRule protoDefinitions; @GET public Response handleGet(@Context HttpContext httpContext) { return this.performActionsFor(httpContext, new HttpGet()); } @POST public Response handlePost(@Context HttpContext httpContext) { return this.performActionsFor(httpContext, new HttpPost()); } @PUT public Response handlePut(@Context HttpContext httpContext) { return this.performActionsFor(httpContext, new HttpPut()); } @DELETE public Response handleDelete(@Context HttpContext httpContext) { return this.performActionsFor(httpContext, new HttpDelete()); } private Response performActionsFor(HttpContext httpContext, HttpRequestBase requestBase) { try { ContainerRequest containerRequest = (ContainerRequest) httpContext.getRequest(); URI forwardUri = (URI) containerRequest.getProperties().get(ProxyFilter.UNPROXIED_URI); if (forwardUri != null) LOG.debug(requestBase.getMethod() + " " + forwardUri); Monitor proxyMon = MonitorFactory.start(forwardUri == null ? "/" : forwardUri.getHost()); try { RuleContext ruleContext = new RuleContext(); ruleContext.recordingDao = trafficManager.recordingDao; ruleContext.httpClient = httpClient; ruleContext.httpContext = httpContext; ruleContext.forwardMethod = requestBase; ruleContext.forwardURI = forwardUri; ruleContext.protoDefinitions = this.protoDefinitions; if (null == forwardUri) { this.handleEmptyDestination(ruleContext); } else { detectAndApplyRule(ruleContext); } return ruleContext.proxyResponse; } finally { proxyMon.stop(); } } catch (Exception ex) { LOG.error("performActionsFor failed", ex); return Response.serverError().entity(ex.toString()).build(); } } private void detectAndApplyRule(RuleContext ruleContext) { Rule rule = null; Monitor mon = MonitorFactory.start("--critter.detect"); try { rule = this.trafficManager.detectRule(ruleContext); } finally { mon.stop(); } if (null == rule) { mon = MonitorFactory.start("--critter.passthrough"); try { new Forward().perform(ruleContext); new Respond().perform(ruleContext); } finally { mon.stop(); } } else { mon = MonitorFactory.start("--critter.perform." + rule.id); try { this.trafficManager.performRule(rule, ruleContext); } finally { mon.stop(); } } } private void handleEmptyDestination(RuleContext ruleContext) { new ResponseHeader() .with("Content-Type", "text/html") .perform(ruleContext); HtmlCanvas canvas = new HtmlCanvas(); try { canvas.html().body() .p().write("You have reached the endpoint of the") .h2().content("Critter Http Proxy Server.") .br() .write("If you are looking for the Admin console then use a different port (probably 8877).") ._p() .p().content("Have a nice day") ._body()._html(); } catch (IOException ex) { } //eat it new ResponseBody() .withBody(canvas.toHtml()) .perform(ruleContext); new Respond() .perform(ruleContext); } }