
org.mockserver.mock.HttpStateHandler Maven / Gradle / Ivy
package org.mockserver.mock;
import com.google.common.base.Function;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.mockserver.callback.WebSocketClientRegistry;
import org.mockserver.client.serialization.*;
import org.mockserver.client.serialization.java.ExpectationToJavaSerializer;
import org.mockserver.client.serialization.java.HttpRequestToJavaSerializer;
import org.mockserver.filters.MockServerEventLog;
import org.mockserver.log.model.LogEntry;
import org.mockserver.log.model.MessageLogEntry;
import org.mockserver.logging.MockServerLogger;
import org.mockserver.model.*;
import org.mockserver.responsewriter.ResponseWriter;
import org.mockserver.scheduler.Scheduler;
import org.mockserver.socket.KeyAndCertificateFactory;
import org.mockserver.verify.Verification;
import org.mockserver.verify.VerificationSequence;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.List;
import static com.google.common.net.MediaType.*;
import static io.netty.handler.codec.http.HttpHeaderNames.HOST;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.mockserver.character.Character.NEW_LINE;
import static org.mockserver.log.model.MessageLogEntry.LogMessageType.*;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;
/**
* @author jamesdbloom
*/
public class HttpStateHandler {
public static final String LOG_SEPARATOR = "\n------------------------------------\n";
public static final String PATH_PREFIX = "/mockserver";
private final MockServerEventLog mockServerLog;
private final Scheduler scheduler;
// mockserver
private MockServerMatcher mockServerMatcher;
private MockServerLogger mockServerLogger = new MockServerLogger(LoggerFactory.getLogger(this.getClass()), this);
private WebSocketClientRegistry webSocketClientRegistry = new WebSocketClientRegistry();
// serializers
private HttpRequestSerializer httpRequestSerializer = new HttpRequestSerializer(mockServerLogger);
private ExpectationSerializer expectationSerializer = new ExpectationSerializer(mockServerLogger);
private HttpRequestToJavaSerializer httpRequestToJavaSerializer = new HttpRequestToJavaSerializer();
private ExpectationToJavaSerializer expectationToJavaSerializer = new ExpectationToJavaSerializer();
private VerificationSerializer verificationSerializer = new VerificationSerializer(mockServerLogger);
private VerificationSequenceSerializer verificationSequenceSerializer = new VerificationSequenceSerializer(mockServerLogger);
public HttpStateHandler(Scheduler scheduler) {
this.scheduler = scheduler;
mockServerLog = new MockServerEventLog(mockServerLogger, scheduler);
mockServerMatcher = new MockServerMatcher(mockServerLogger, scheduler);
}
public MockServerLogger getMockServerLogger() {
return mockServerLogger;
}
public void clear(HttpRequest request) {
HttpRequest requestMatcher = null;
if (!Strings.isNullOrEmpty(request.getBodyAsString())) {
requestMatcher = httpRequestSerializer.deserialize(request.getBodyAsString());
}
try {
ClearType retrieveType = ClearType.valueOf(StringUtils.defaultIfEmpty(request.getFirstQueryStringParameter("type").toUpperCase(), "ALL"));
switch (retrieveType) {
case LOG:
mockServerLog.clear(requestMatcher);
mockServerLogger.info(CLEARED, requestMatcher, "clearing recorded requests and logs that match:{}", (requestMatcher == null ? "{}" : requestMatcher));
break;
case EXPECTATIONS:
mockServerMatcher.clear(requestMatcher);
mockServerLogger.info(CLEARED, requestMatcher, "clearing expectations that match:{}", (requestMatcher == null ? "{}" : requestMatcher));
break;
case ALL:
mockServerLog.clear(requestMatcher);
mockServerMatcher.clear(requestMatcher);
mockServerLogger.info(CLEARED, requestMatcher, "clearing expectations and request logs that match:{}", (requestMatcher == null ? "{}" : requestMatcher));
break;
}
} catch (IllegalArgumentException iae) {
throw new IllegalArgumentException("\"" + request.getFirstQueryStringParameter("type") + "\" is not a valid value for \"type\" parameter, only the following values are supported " + Lists.transform(Arrays.asList(ClearType.values()), new Function() {
public String apply(ClearType input) {
return input.name().toLowerCase();
}
}));
}
}
public void reset() {
mockServerMatcher.reset();
mockServerLog.reset();
mockServerLogger.info(CLEARED, "resetting all expectations and request logs");
}
public void add(Expectation... expectations) {
for (Expectation expectation : expectations) {
final String hostHeader = expectation.getHttpRequest().getFirstHeader(HOST.toString());
scheduler.submit(new Runnable() {
@Override
public void run() {
KeyAndCertificateFactory.addSubjectAlternativeName(hostHeader);
}
});
mockServerMatcher.add(expectation);
mockServerLogger.info(CREATED_EXPECTATION, expectation.getHttpRequest(), "creating expectation:{}", expectation.clone());
}
}
public Expectation firstMatchingExpectation(HttpRequest request) {
if (mockServerMatcher.isEmpty()) {
mockServerLogger.info(EXPECTATION_NOT_MATCHED, request, "no active expectations");
return null;
} else {
return mockServerMatcher.firstMatchingExpectation(request);
}
}
public void log(LogEntry logEntry) {
if (mockServerLog != null) {
mockServerLog.add(logEntry);
}
}
public HttpResponse retrieve(HttpRequest request) {
HttpRequest httpRequest = null;
if (!Strings.isNullOrEmpty(request.getBodyAsString())) {
httpRequest = httpRequestSerializer.deserialize(request.getBodyAsString());
}
HttpResponse response = response();
try {
Format format = Format.valueOf(StringUtils.defaultIfEmpty(request.getFirstQueryStringParameter("format").toUpperCase(), "JSON"));
RetrieveType retrieveType = RetrieveType.valueOf(StringUtils.defaultIfEmpty(request.getFirstQueryStringParameter("type").toUpperCase(), "REQUESTS"));
switch (retrieveType) {
case LOGS: {
mockServerLogger.info(RETRIEVED, httpRequest, "retrieving " + retrieveType.name().toLowerCase() + " that match:{}", (httpRequest == null ? request() : httpRequest));
List retrievedMessages = mockServerLog.retrieveMessages(httpRequest);
StringBuilder stringBuffer = new StringBuilder();
for (int i = 0; i < retrievedMessages.size(); i++) {
MessageLogEntry messageLogEntry = retrievedMessages.get(i);
stringBuffer
.append(messageLogEntry.getTimeStamp())
.append(" - ")
.append(messageLogEntry.getMessage());
if (i < retrievedMessages.size() - 1) {
stringBuffer.append(LOG_SEPARATOR);
}
}
stringBuffer.append("\n");
response.withBody(stringBuffer.toString(), PLAIN_TEXT_UTF_8);
break;
}
case REQUESTS: {
mockServerLogger.info(RETRIEVED, httpRequest, "retrieving " + retrieveType.name().toLowerCase() + " in " + format.name().toLowerCase() + " that match:{}", (httpRequest == null ? request() : httpRequest));
List httpRequests = mockServerLog.retrieveRequests(httpRequest);
switch (format) {
case JAVA:
response.withBody(httpRequestToJavaSerializer.serialize(httpRequests), create("application", "java").withCharset(UTF_8));
break;
case JSON:
response.withBody(httpRequestSerializer.serialize(httpRequests), JSON_UTF_8);
break;
}
break;
}
case RECORDED_EXPECTATIONS: {
mockServerLogger.info(RETRIEVED, httpRequest, "retrieving " + retrieveType.name().toLowerCase() + " in " + format.name().toLowerCase() + " that match:{}", (httpRequest == null ? request() : httpRequest));
List expectations = mockServerLog.retrieveExpectations(httpRequest);
switch (format) {
case JAVA:
response.withBody(expectationToJavaSerializer.serialize(expectations), create("application", "java").withCharset(UTF_8));
break;
case JSON:
response.withBody(expectationSerializer.serialize(expectations), JSON_UTF_8);
break;
}
break;
}
case ACTIVE_EXPECTATIONS: {
mockServerLogger.info(RETRIEVED, httpRequest, "retrieving " + retrieveType.name().toLowerCase() + " in " + format.name().toLowerCase() + " that match:{}", (httpRequest == null ? request() : httpRequest));
List expectations = mockServerMatcher.retrieveExpectations(httpRequest);
switch (format) {
case JAVA:
response.withBody(expectationToJavaSerializer.serialize(expectations), create("application", "java").withCharset(UTF_8));
break;
case JSON:
response.withBody(expectationSerializer.serialize(expectations), JSON_UTF_8);
break;
}
break;
}
}
} catch (IllegalArgumentException iae) {
if (iae.getMessage().contains(RetrieveType.class.getSimpleName())) {
throw new IllegalArgumentException("\"" + request.getFirstQueryStringParameter("type") + "\" is not a valid value for \"type\" parameter, only the following values are supported " + Lists.transform(Arrays.asList(RetrieveType.values()), new Function() {
public String apply(RetrieveType input) {
return input.name().toLowerCase();
}
}));
} else {
throw new IllegalArgumentException("\"" + request.getFirstQueryStringParameter("format") + "\" is not a valid value for \"format\" parameter, only the following values are supported " + Lists.transform(Arrays.asList(Format.values()), new Function() {
public String apply(Format input) {
return input.name().toLowerCase();
}
}));
}
}
return response.withStatusCode(200);
}
public String verify(Verification verification) {
return mockServerLog.verify(verification);
}
public String verify(VerificationSequence verification) {
return mockServerLog.verify(verification);
}
public boolean handle(HttpRequest request, ResponseWriter responseWriter, boolean warDeployment) {
mockServerLogger.trace(request, "received request:{}", request);
if (request.matches("PUT", PATH_PREFIX + "/expectation", "/expectation")) {
for (Expectation expectation : expectationSerializer.deserializeArray(request.getBodyAsString())) {
if (!warDeployment || validateSupportedFeatures(expectation, request, responseWriter)) {
add(expectation);
}
}
responseWriter.writeResponse(request, CREATED);
} else if (request.matches("PUT", PATH_PREFIX + "/clear", "/clear")) {
clear(request);
responseWriter.writeResponse(request, OK);
} else if (request.matches("PUT", PATH_PREFIX + "/reset", "/reset")) {
reset();
responseWriter.writeResponse(request, OK);
} else if (request.matches("PUT", PATH_PREFIX + "/retrieve", "/retrieve")) {
responseWriter.writeResponse(request, retrieve(request), true);
} else if (request.matches("PUT", PATH_PREFIX + "/verify", "/verify")) {
Verification verification = verificationSerializer.deserialize(request.getBodyAsString());
mockServerLogger.info(VERIFICATION, verification.getHttpRequest(), "verifying requests that match:{}", verification);
String result = verify(verification);
if (StringUtils.isEmpty(result)) {
responseWriter.writeResponse(request, ACCEPTED);
} else {
responseWriter.writeResponse(request, NOT_ACCEPTABLE, result, create("text", "plain").toString());
}
} else if (request.matches("PUT", PATH_PREFIX + "/verifySequence", "/verifySequence")) {
VerificationSequence verificationSequence = verificationSequenceSerializer.deserialize(request.getBodyAsString());
mockServerLogger.info(VERIFICATION, verificationSequence.getHttpRequests(), "verifying sequence that match:{}", verificationSequence);
String result = verify(verificationSequence);
if (StringUtils.isEmpty(result)) {
responseWriter.writeResponse(request, ACCEPTED);
} else {
responseWriter.writeResponse(request, NOT_ACCEPTABLE, result, create("text", "plain").toString());
}
} else {
return false;
}
return true;
}
private boolean validateSupportedFeatures(Expectation expectation, HttpRequest request, ResponseWriter responseWriter) {
boolean valid = true;
Action action = expectation.getAction();
String NOT_SUPPORTED_MESSAGE = " is not supported by MockServer deployed as a WAR due to limitations in the JEE specification; use mockserver-netty to enable these features";
if (action instanceof HttpResponse && ((HttpResponse) action).getConnectionOptions() != null) {
responseWriter.writeResponse(request, response("ConnectionOptions" + NOT_SUPPORTED_MESSAGE), true);
valid = false;
} else if (action instanceof HttpObjectCallback) {
responseWriter.writeResponse(request, response("HttpObjectCallback" + NOT_SUPPORTED_MESSAGE), true);
valid = false;
} else if (action instanceof HttpError) {
responseWriter.writeResponse(request, response("HttpError" + NOT_SUPPORTED_MESSAGE), true);
valid = false;
}
return valid;
}
public WebSocketClientRegistry getWebSocketClientRegistry() {
return webSocketClientRegistry;
}
public MockServerMatcher getMockServerMatcher() {
return mockServerMatcher;
}
public MockServerEventLog getMockServerLog() {
return mockServerLog;
}
public Scheduler getScheduler() {
return scheduler;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy