package org.mockserver.client.proxy;
import org.mockserver.client.AbstractClient;
import org.mockserver.client.netty.SocketConnectionException;
import org.mockserver.mock.Expectation;
import org.mockserver.model.HttpRequest;
import org.mockserver.model.HttpResponse;
import org.mockserver.model.HttpStatusCode;
import org.mockserver.verify.Verification;
import org.mockserver.verify.VerificationSequence;
import org.mockserver.verify.VerificationTimes;
import java.util.concurrent.TimeUnit;
import static org.mockserver.model.HttpRequest.request;
/**
* @author jamesdbloom
*/
public class ProxyClient extends AbstractClient {
/**
* Start the client communicating to a the proxy at the specified host and port
* for example:
*
* ProxyClient mockServerClient = new ProxyClient("localhost", 1080);
*
* @param host the host for the MockServer to communicate with
* @param port the port for the MockServer to communicate with
*/
public ProxyClient(String host, int port) {
this(host, port, "");
}
/**
* Start the client communicating to the proxy at the specified host and port
* and contextPath for example:
*
* ProxyClient mockServerClient = new ProxyClient("localhost", 1080, "/proxy");
*
* @param host the host for the proxy to communicate with
* @param port the port for the proxy to communicate with
* @param contextPath the context path that the proxy war is deployed to
*/
public ProxyClient(String host, int port, String contextPath) {
super(host, port, contextPath);
}
/**
* Pretty-print the json for all requests / responses as Expectations to the log.
* They are printed into a dedicated log called mockserver_request.log
*/
public ProxyClient dumpToLogAsJSON() {
return dumpToLogAsJSON(null);
}
/**
* Pretty-print the json for matching requests and their responses as Expectations to the log.
* They are printed into a dedicated log called mockserver_request.log
*
* @param httpRequest the http request that is matched against when deciding what to log if null all requests are logged
*/
public ProxyClient dumpToLogAsJSON(HttpRequest httpRequest) {
sendRequest(request().withMethod("PUT").withPath(calculatePath("dumpToLog")).withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : ""));
return this;
}
/**
* Output Java code for creating all requests / responses as Expectations to the log.
* They are printed into a dedicated log called mockserver_request.log
*/
public ProxyClient dumpToLogAsJava() {
return dumpToLogAsJava(null);
}
/**
* Output Java code for creating matching requests and their responses as Expectations to the log.
* They are printed into a dedicated log called mockserver_request.log
*
* @param httpRequest the http request that is matched against when deciding what to log if null all requests are logged
*/
public ProxyClient dumpToLogAsJava(HttpRequest httpRequest) {
sendRequest(request().withMethod("PUT").withPath(calculatePath("dumpToLog?type=java")).withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : ""));
return this;
}
/**
* Returns whether the proxy is running
*/
public boolean isRunning() {
return isRunning(10, 500, TimeUnit.MILLISECONDS);
}
/**
* Returns whether the proxy is running, by polling the MockServer a configurable amount of times
*/
public boolean isRunning(int attempts, long timeout, TimeUnit timeUnit) {
try {
HttpResponse httpResponse = sendRequest(request().withMethod("PUT").withPath(calculatePath("status")));
if (httpResponse.getStatusCode() == HttpStatusCode.OK_200.code()) {
return true;
} else {
try {
timeUnit.sleep(timeout);
} catch (InterruptedException e) {
// ignore interrupted exception
}
return isRunning(attempts - 1, timeout, timeUnit);
}
} catch (SocketConnectionException sce) {
return false;
}
}
/**
* Stop the proxy gracefully (only support for Netty and Vert.X versions, not supported for WAR version)
*/
public ProxyClient stop() {
return stop(false);
}
public ProxyClient stop(boolean ignoreFailure) {
try {
sendRequest(request().withMethod("PUT").withPath(calculatePath("stop")));
if (isRunning()) {
for (int i = 0; isRunning() && i < 50; i++) {
TimeUnit.MILLISECONDS.sleep(5);
}
}
} catch (Exception e) {
if (!ignoreFailure) {
logger.warn("Failed to send stop request to proxy " + e.getMessage());
}
}
return this;
}
/**
* Reset the proxy by clearing recorded requests
*/
public ProxyClient reset() {
sendRequest(request().withMethod("PUT").withPath(calculatePath("reset")));
return this;
}
/**
* Clear all recorded requests that match the httpRequest parameter
*
* @param httpRequest the http request that is matched against when deciding whether to clear recorded requests
*/
public ProxyClient clear(HttpRequest httpRequest) {
sendRequest(request().withMethod("PUT").withPath(calculatePath("clear")).withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : ""));
return this;
}
/**
* Verify a list of requests have been sent in the order specified for example:
*
* mockServerClient
* .verify(
* request()
* .withPath("/first_request")
* .withBody("some_request_body"),
* request()
* .withPath("/second_request")
* .withBody("some_request_body")
* );
*
* @param httpRequests the http requests that must be matched for this verification to pass
* @throws AssertionError if the request has not been found
*/
public ProxyClient verify(HttpRequest... httpRequests) throws AssertionError {
if (httpRequests == null || httpRequests.length == 0 || httpRequests[0] == null) {
throw new IllegalArgumentException("verify(HttpRequest...) requires a non null non empty array of HttpRequest objects");
}
VerificationSequence verificationSequence = new VerificationSequence().withRequests(httpRequests);
String result = sendRequest(request().withMethod("PUT").withPath(calculatePath("verifySequence")).withBody(verificationSequenceSerializer.serialize(verificationSequence))).getBodyAsString();
if (result != null && !result.isEmpty()) {
throw new AssertionError(result);
}
return this;
}
/**
* Verify a request has been sent for example:
*
* mockServerClient
* .verify(
* request()
* .withPath("/some_path")
* .withBody("some_request_body"),
* VerificationTimes.exactly(3)
* );
*
* VerificationTimes supports multiple static factory methods:
*
* once() - verify the request was only received once
* exactly(n) - verify the request was only received exactly n times
* atLeast(n) - verify the request was only received at least n times
*
* @param httpRequest the http request that must be matched for this verification to pass
* @param times the number of times this request must be matched
* @throws AssertionError if the request has not been found
*/
public ProxyClient verify(HttpRequest httpRequest, VerificationTimes times) throws AssertionError {
if (httpRequest == null) {
throw new IllegalArgumentException("verify(HttpRequest, VerificationTimes) requires a non null HttpRequest object");
}
if (times == null) {
throw new IllegalArgumentException("verify(HttpRequest, VerificationTimes) requires a non null VerificationTimes object");
}
Verification verification = new Verification().withRequest(httpRequest).withTimes(times);
String result = sendRequest(request().withMethod("PUT").withPath(calculatePath("verify")).withBody(verificationSerializer.serialize(verification))).getBodyAsString();
if (result != null && !result.isEmpty()) {
throw new AssertionError(result);
}
return this;
}
/**
* Retrieve the recorded requests that match the httpRequest parameter as expectations, use null for the parameter to retrieve all requests
*
* @param httpRequest the http request that is matched against when deciding whether to return each expectation, use null for the parameter to retrieve for all requests
* @return an array of all expectations that have been recorded by the proxy
*/
public Expectation[] retrieveAsExpectations(HttpRequest httpRequest) {
HttpResponse httpResponse = sendRequest(request().withMethod("PUT").withPath(calculatePath("retrieve")).withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : ""));
return expectationSerializer.deserializeArray(httpResponse.getBodyAsString());
}
/**
* Retrieve the recorded requests that match the httpRequest parameter as a JSON array, use null for the parameter to retrieve all requests
*
* @param httpRequest the http request that is matched against when deciding whether to return each expectation, use null for the parameter to retrieve for all requests
* @return a JSON array of all expectations that have been recorded by the proxy
*/
public String retrieveAsJSON(HttpRequest httpRequest) {
HttpResponse httpResponse = sendRequest(request().withMethod("PUT").withPath(calculatePath("retrieve")).withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : ""));
return httpResponse.getBodyAsString();
}
}