Skip to content

Commit

Permalink
Added JsonErrorHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
azagniotov committed Oct 23, 2016
1 parent 01bb8a9 commit 42299f9
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 64 deletions.
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -1066,11 +1066,12 @@ You can start-up and manage stubby4j with the help of [StubbyClient](main/java/i
### Change log

##### 4.0.3-SNAPSHOT
* Suppressed Jetty's default [ErrorHandler](http://download.eclipse.org/jetty/9.3.12.v20160915/apidocs/org/eclipse/jetty/server/handler/ErrorHandler.html) with a custom [JsonErrorHandler](main/java/io/github/azagniotov/stubby4j/handlers/JsonErrorHandler.java) to send errors in JSON format

##### 4.0.2
* Log to terminal why a request fails to match https://github.com/soundcloud/stubby4j/commit/5901710efd31653a05804ebec62f67184c212832
* Square brackets were not escaped as literals for regular expression in Json POST [BUG]
* Precompiling & caching stubbed regex patterns upon parsing YAML stub configuration
* Pre-compiling & caching stubbed regex patterns upon parsing YAML stub configuration

##### 4.0.1
* Issue #54 - Support for regular expression in Json POST
Expand Down
52 changes: 0 additions & 52 deletions functional/java/io/github/azagniotov/stubby4j/StubsPortalTest.java
Expand Up @@ -973,56 +973,4 @@ public void should_ReturnExpectedRecordedResponse_OnSubsequentCallToValidUrl() t
}
}
}

/**
* This test really has value when there is an active connection to the Internet
*/
@Test
@Ignore
@CoberturaIgnore
public void should_ReturnExpectedRecordedResponse_FromGoogle() throws Exception {

ANSITerminal.muteConsole(false);

final ByteArrayOutputStream consoleCaptor = new ByteArrayOutputStream();
final boolean NO_AUTO_FLUSH = false;
final PrintStream oldPrintStream = System.out;
System.setOut(new PrintStream(consoleCaptor, NO_AUTO_FLUSH, StringUtils.UTF_8));

final String requestUrl = String.format("%s%s", STUBS_URL, "/maps/api/geocode/json?sensor=false&address=1600+Amphitheatre+Parkway,+Mountain+View,+CA");
final HttpRequest request = HttpUtils.constructHttpRequest(HttpMethods.GET, requestUrl);

final int LIMIT = 1;
for (int idx = 1; idx <= LIMIT; idx++) {
final HttpResponse response = request.execute();
final String actualConsoleOutput = consoleCaptor.toString(StringUtils.UTF_8).trim();
if (idx == 1) {
if (actualConsoleOutput.contains("Exception")) {
System.setOut(oldPrintStream);
System.out.println(actualConsoleOutput);
// If we are here, it means we do not have active Internet connection (or something else has happened)
// and we could not hit Google in that case, there is no point to causing this test to fail if the user
// running this test without having the ability to access the Internet.
break;
}
}

final HttpHeaders headers = response.getHeaders();
assertThat(headers.getContentType().contains(Common.HEADER_APPLICATION_JSON)).isTrue();

String responseContent = response.parseAsString().trim();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK_200);
assertThat(responseContent).contains("results");
assertThat(responseContent).contains("address_components");
assertThat(responseContent).contains("formatted_address");

// Make sure we only hitting recordabe source once
assertThat(actualConsoleOutput).containsOnlyOnce("Recording HTTP response using");

if (idx == LIMIT) {
System.setOut(oldPrintStream);
System.out.println(actualConsoleOutput);
}
}
}
}
Expand Up @@ -343,7 +343,7 @@ public void doPost_ShouldMakeSuccessfulPost_WhenGivenEmptyUri() throws Exception

assertThat(stubbyResponse.getResponseCode()).isEqualTo(HttpStatus.NOT_FOUND_404);
assertThat(stubbyResponse.getContent()).contains("(404) Nothing found for POST request at URI /");
assertThat(stubbyResponse.getContent()).contains("With post data: post body");
assertThat(stubbyResponse.getContent()).contains("post body");
}


Expand All @@ -357,7 +357,7 @@ public void doPost_ShouldMakeSuccessfulPost_WhenGivenNullUri() throws Exception

assertThat(stubbyResponse.getResponseCode()).isEqualTo(HttpStatus.NOT_FOUND_404);
assertThat(stubbyResponse.getContent()).contains("(404) Nothing found for POST request at URI /");
assertThat(stubbyResponse.getContent()).contains("With post data: post body");
assertThat(stubbyResponse.getContent()).contains("post body");
}

@Test
Expand All @@ -370,7 +370,7 @@ public void doPost_ShouldMakeSuccessfulPost_WhenGivenWrongPostData() throws Exce

assertThat(stubbyResponse.getResponseCode()).isEqualTo(HttpStatus.NOT_FOUND_404);
assertThat(stubbyResponse.getContent()).contains("(404) Nothing found for POST request at URI /item/1");
assertThat(stubbyResponse.getContent()).contains("With post data: unexpected or wrong post body");
assertThat(stubbyResponse.getContent()).contains("unexpected or wrong post body");
}

@Test
Expand Down
@@ -0,0 +1,66 @@
package io.github.azagniotov.stubby4j.handlers;

import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.util.ByteArrayISO8859Writer;
import org.json.JSONException;
import org.json.JSONObject;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Writer;

public class JsonErrorHandler extends ErrorHandler {

@Override
public void handle(final String target,
final Request baseRequest,
final HttpServletRequest request,
final HttpServletResponse response) throws IOException {

final String method = request.getMethod();
if (!HttpMethod.GET.is(method) && !HttpMethod.POST.is(method) && !HttpMethod.PUT.is(method) && !HttpMethod.HEAD.is(method)) {
baseRequest.setHandled(true);
return;
}

baseRequest.setHandled(true);
response.setContentType(MimeTypes.Type.APPLICATION_JSON.asString());

final ByteArrayISO8859Writer byteArrayWriter = new ByteArrayISO8859Writer(4096);
final String reason = (response instanceof Response) ? ((Response) response).getReason() : null;

handleErrorPage(request, byteArrayWriter, response.getStatus(), reason);

byteArrayWriter.flush();
response.setContentLength(byteArrayWriter.size());
byteArrayWriter.writeTo(response.getOutputStream());
byteArrayWriter.destroy();
}

@Override
protected void writeErrorPage(final HttpServletRequest request,
final Writer writer,
final int code,
final String message,
final boolean showStacks) throws IOException {

final String error = message == null ? HttpStatus.getMessage(code) : message;
if (code == 404) {
try {
final JSONObject jsonObject = new JSONObject(error);
jsonObject.putOpt("code", code);
writer.write(jsonObject.toString());
} catch (final JSONException e) {
writer.write("{\"code\":\"" + code + "\",\"message\"=\"" + error + "\"}");
}
} else {
writer.write("{\"code\":\"" + code + "\",\"message\"=\"" + error + "\"}");
}
}
}
Expand Up @@ -22,11 +22,10 @@
import io.github.azagniotov.stubby4j.utils.HandlerUtils;
import io.github.azagniotov.stubby4j.yaml.stubs.StubRequest;
import org.eclipse.jetty.http.HttpStatus;
import org.json.JSONObject;

import javax.servlet.http.HttpServletResponse;

import static io.github.azagniotov.stubby4j.utils.FileUtils.BR;

public final class NotFoundResponseHandlingStrategy implements StubResponseHandlingStrategy {

public NotFoundResponseHandlingStrategy() {
Expand All @@ -38,12 +37,24 @@ public void handle(final HttpServletResponse response, final StubRequest asserti

HandlerUtils.setResponseMainHeaders(response);

final String postMessage = assertionStubRequest.hasPostBody() ? String.format(BR + "\t%s%s", "With post data: ", assertionStubRequest.getPostBody()) : "";
final String headersMessage = assertionStubRequest.hasHeaders() ? String.format(BR + "\t%s%s", "With headers: ", assertionStubRequest.getHeaders()) : "";
final String queryMessage = (assertionStubRequest.hasQuery() ? String.format(BR + "\t%s%s", "With query params: ", assertionStubRequest.getQuery()) : "");
final String reason = String.format("(404) Nothing found for %s request at URI %s", assertionStubRequest.getMethod().get(0), assertionStubRequest.getUrl());

final JSONObject json404Response = new JSONObject();
json404Response.put("reason", reason);
json404Response.put("method", assertionStubRequest.getMethod().get(0));
json404Response.put("url", assertionStubRequest.getUrl());

if (assertionStubRequest.hasQuery()) {
json404Response.put("query", new JSONObject(assertionStubRequest.getQuery()));
}

final String error = String.format("(404) Nothing found for %s request at URI %s%s%s%s", assertionStubRequest.getMethod().get(0), assertionStubRequest.getUrl(), postMessage, headersMessage, queryMessage);
if (assertionStubRequest.hasHeaders()) {
json404Response.put("headers", new JSONObject(assertionStubRequest.getHeaders()));
}

HandlerUtils.configureErrorResponse(response, HttpStatus.NOT_FOUND_404, error);
if (assertionStubRequest.hasPostBody()) {
json404Response.put("post", assertionStubRequest.getPostBody());
}
HandlerUtils.configureErrorResponse(response, HttpStatus.NOT_FOUND_404, json404Response.toString());
}
}
Expand Up @@ -27,6 +27,7 @@
import io.github.azagniotov.stubby4j.handlers.AjaxEndpointStatsHandler;
import io.github.azagniotov.stubby4j.handlers.AjaxResourceContentHandler;
import io.github.azagniotov.stubby4j.handlers.FaviconHandler;
import io.github.azagniotov.stubby4j.handlers.JsonErrorHandler;
import io.github.azagniotov.stubby4j.handlers.StatusPageHandler;
import io.github.azagniotov.stubby4j.handlers.StubDataRefreshActionHandler;
import io.github.azagniotov.stubby4j.handlers.StubsPortalHandler;
Expand Down Expand Up @@ -175,8 +176,10 @@ private ContextHandler constructHandler(final String connectorName, final String
contextHandler.addLocaleEncoding(Locale.US.getDisplayName(), StringUtils.UTF_8);
contextHandler.setHandler(handler);

contextHandler.setErrorHandler(new JsonErrorHandler());

final MimeTypes mimeTypes = new MimeTypes();
mimeTypes.setMimeMap(new HashMap<String, String>());
mimeTypes.setMimeMap(new HashMap<>());
contextHandler.setMimeTypes(mimeTypes);

return contextHandler;
Expand Down

0 comments on commit 42299f9

Please sign in to comment.