use of io.github.microcks.domain.Header in project microcks by microcks.
the class RestController method execute.
@RequestMapping(value = "/{service}/{version}/**", method = { RequestMethod.HEAD, RequestMethod.OPTIONS, RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.PATCH, RequestMethod.DELETE })
public ResponseEntity<?> execute(@PathVariable("service") String serviceName, @PathVariable("version") String version, @RequestParam(value = "delay", required = false) Long delay, @RequestBody(required = false) String body, HttpServletRequest request) {
log.info("Servicing mock response for service [{}, {}] on uri {} with verb {}", serviceName, version, request.getRequestURI(), request.getMethod());
log.debug("Request body: {}", body);
long startTime = System.currentTimeMillis();
// Extract resourcePath for matching with correct operation.
String requestURI = request.getRequestURI();
String serviceAndVersion = null;
String resourcePath = null;
// Build the encoded URI fragment to retrieve simple resourcePath.
serviceAndVersion = "/" + UriUtils.encodeFragment(serviceName, "UTF-8") + "/" + version;
resourcePath = requestURI.substring(requestURI.indexOf(serviceAndVersion) + serviceAndVersion.length());
// resourcePath = UriUtils.decode(resourcePath, "UTF-8");
log.debug("Found resourcePath: {}", resourcePath);
// If serviceName was encoded with '+' instead of '%20', remove them.
if (serviceName.contains("+")) {
serviceName = serviceName.replace('+', ' ');
}
// If resourcePath was encoded with '+' instead of '%20', replace them .
if (resourcePath.contains("+")) {
resourcePath = resourcePath.replace("+", "%20");
}
Service service = serviceRepository.findByNameAndVersion(serviceName, version);
Operation rOperation = null;
for (Operation operation : service.getOperations()) {
// Select operation based onto Http verb (GET, POST, PUT, etc ...)
if (operation.getMethod().equals(request.getMethod().toUpperCase())) {
// ... then check is we have a matching resource path.
if (operation.getResourcePaths() != null && operation.getResourcePaths().contains(resourcePath)) {
rOperation = operation;
break;
}
}
}
// using a Fallback dispatcher. Try again, just considering the verb and path pattern of operation.
if (rOperation == null) {
for (Operation operation : service.getOperations()) {
// Select operation based onto Http verb (GET, POST, PUT, etc ...)
if (operation.getMethod().equals(request.getMethod().toUpperCase())) {
// ... then check is current resource path matches operation path pattern.
if (operation.getResourcePaths() != null) {
// Produce a matching regexp removing {part} and :part from pattern.
String operationPattern = getURIPattern(operation.getName());
operationPattern = operationPattern.replaceAll("\\{.+\\}", "(.)+");
operationPattern = operationPattern.replaceAll("(/:[^:^/]+)", "\\/(.+)");
if (resourcePath.matches(operationPattern)) {
rOperation = operation;
break;
}
}
}
}
}
if (rOperation != null) {
log.debug("Found a valid operation {} with rules: {}", rOperation.getName(), rOperation.getDispatcherRules());
String violationMsg = validateParameterConstraintsIfAny(rOperation, request);
if (violationMsg != null) {
return new ResponseEntity<Object>(violationMsg + ". Check parameter constraints.", HttpStatus.BAD_REQUEST);
}
// We must find dispatcher and its rules. Default to operation ones but
// if we have a Fallback this is the one who is holding the first pass rules.
String dispatcher = rOperation.getDispatcher();
String dispatcherRules = rOperation.getDispatcherRules();
FallbackSpecification fallback = MockControllerCommons.getFallbackIfAny(rOperation);
if (fallback != null) {
dispatcher = fallback.getDispatcher();
dispatcherRules = fallback.getDispatcherRules();
}
//
String dispatchCriteria = computeDispatchCriteria(dispatcher, dispatcherRules, getURIPattern(rOperation.getName()), UriUtils.decode(resourcePath, "UTF-8"), request, body);
log.debug("Dispatch criteria for finding response is {}", dispatchCriteria);
Response response = null;
// Filter depending on requested media type.
List<Response> responses = responseRepository.findByOperationIdAndDispatchCriteria(IdBuilder.buildOperationId(service, rOperation), dispatchCriteria);
response = getResponseByMediaType(responses, request);
if (response == null) {
// When using the SCRIPT or JSON_BODY dispatchers, return of evaluation may be the name of response.
responses = responseRepository.findByOperationIdAndName(IdBuilder.buildOperationId(service, rOperation), dispatchCriteria);
response = getResponseByMediaType(responses, request);
}
if (response == null && fallback != null) {
// If we've found nothing and got a fallback, that's the moment!
responses = responseRepository.findByOperationIdAndName(IdBuilder.buildOperationId(service, rOperation), fallback.getFallback());
response = getResponseByMediaType(responses, request);
}
if (response == null) {
// In case no response found (because dispatcher is null for example), just get one for the operation.
// This will allow also OPTIONS operations (like pre-flight requests) with no dispatch criteria to work.
log.debug("No responses found so far, tempting with just bare operationId...");
responses = responseRepository.findByOperationId(IdBuilder.buildOperationId(service, rOperation));
if (!responses.isEmpty()) {
response = getResponseByMediaType(responses, request);
}
}
if (response != null) {
HttpStatus status = (response.getStatus() != null ? HttpStatus.valueOf(Integer.parseInt(response.getStatus())) : HttpStatus.OK);
// Deal with specific headers (content-type and redirect directive).
HttpHeaders responseHeaders = new HttpHeaders();
if (response.getMediaType() != null) {
responseHeaders.setContentType(MediaType.valueOf(response.getMediaType() + ";charset=UTF-8"));
}
// Deal with headers from parameter constraints if any?
recopyHeadersFromParameterConstraints(rOperation, request, responseHeaders);
// Adding other generic headers (caching directives and so on...)
if (response.getHeaders() != null) {
for (Header header : response.getHeaders()) {
if ("Location".equals(header.getName())) {
// We should process location in order to make relative URI specified an absolute one from
// the client perspective.
String location = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/rest" + serviceAndVersion + header.getValues().iterator().next();
responseHeaders.add(header.getName(), location);
} else {
if (!HttpHeaders.TRANSFER_ENCODING.equalsIgnoreCase(header.getName())) {
responseHeaders.put(header.getName(), new ArrayList<>(header.getValues()));
}
}
}
}
// Render response content before waiting and returning.
String responseContent = MockControllerCommons.renderResponseContent(body, resourcePath, request, response);
// Setting delay to default one if not set.
if (delay == null && rOperation.getDefaultDelay() != null) {
delay = rOperation.getDefaultDelay();
}
MockControllerCommons.waitForDelay(startTime, delay);
// Publish an invocation event before returning if enabled.
if (enableInvocationStats) {
MockControllerCommons.publishMockInvocation(applicationContext, this, service, response, startTime);
}
return new ResponseEntity<Object>(responseContent, responseHeaders, status);
}
return new ResponseEntity<Object>(HttpStatus.BAD_REQUEST);
} else // Handle OPTIONS request if CORS policy is enabled.
if (enableCorsPolicy && "OPTIONS".equals(request.getMethod().toUpperCase())) {
log.debug("No valid operation found but Microcks configured to apply CORS policy");
return handleCorsRequest(request);
}
log.debug("No valid operation found and Microcks configured to not apply CORS policy...");
return new ResponseEntity<Object>(HttpStatus.NOT_FOUND);
}
use of io.github.microcks.domain.Header in project microcks by microcks.
the class AMQPMessageConsumptionTask method buildHeaders.
/**
* Build set of Microcks headers from RabbitMQ headers.
*/
private Set<Header> buildHeaders(Map<String, Object> headers) {
if (headers == null || headers.isEmpty()) {
return null;
}
Set<Header> results = new HashSet<>();
for (String key : headers.keySet()) {
Header result = new Header();
result.setName(key);
result.setValues(Set.of(headers.get(key).toString()));
results.add(result);
}
return results;
}
use of io.github.microcks.domain.Header in project microcks by microcks.
the class KafkaMessageConsumptionTask method buildHeaders.
/**
* Build set of Microcks headers from Kafka headers.
*/
private Set<Header> buildHeaders(Headers headers) {
if (headers == null || !headers.iterator().hasNext()) {
return null;
}
Set<Header> results = new HashSet<>();
Iterator<org.apache.kafka.common.header.Header> headersIterator = headers.iterator();
while (headersIterator.hasNext()) {
org.apache.kafka.common.header.Header header = headersIterator.next();
Header result = new Header();
result.setName(header.key());
result.setValues(Set.of(new String(header.value())));
results.add(result);
}
return results;
}
use of io.github.microcks.domain.Header in project microcks by microcks.
the class PostmanCollectionImporter method buildResponse.
private Response buildResponse(JsonNode responseNode, String dispatchCriteria) {
Response response = new Response();
response.setName(responseNode.path("name").asText());
if (isV2Collection) {
response.setStatus(responseNode.path("code").asText("200"));
response.setHeaders(buildHeaders(responseNode.path("header")));
response.setContent(responseNode.path("body").asText(""));
} else {
response.setStatus(responseNode.path("responseCode").path("code").asText());
response.setHeaders(buildHeaders(responseNode.path("headers")));
response.setContent(responseNode.path("text").asText());
}
if (response.getHeaders() != null) {
for (Header header : response.getHeaders()) {
if (header.getName().equalsIgnoreCase("Content-Type")) {
response.setMediaType(header.getValues().toArray(new String[] {})[0]);
}
}
}
// assume it is its content-type.
if (!isV2Collection && response.getMediaType() == null) {
if ("json".equals(responseNode.path("language").asText())) {
response.setMediaType("application/json");
}
}
// assume it is its content-type.
if (isV2Collection && response.getMediaType() == null) {
if ("json".equals(responseNode.path("_postman_previewlanguage").asText())) {
response.setMediaType("application/json");
} else if ("xml".equals(responseNode.path("_postman_previewlanguage").asText())) {
response.setMediaType("text/xml");
}
}
response.setDispatchCriteria(dispatchCriteria);
return response;
}
use of io.github.microcks.domain.Header in project microcks by microcks.
the class PostmanTestStepsRunner method runTest.
@Override
public List<TestReturn> runTest(Service service, Operation operation, TestResult testResult, List<Request> requests, String endpointUrl, HttpMethod method) throws URISyntaxException, IOException {
if (log.isDebugEnabled()) {
log.debug("Launching test run on " + endpointUrl + " for " + requests.size() + " request(s)");
}
if (endpointUrl.endsWith("/")) {
endpointUrl = endpointUrl.substring(0, endpointUrl.length() - 1);
}
// Microcks-postman-runner interface object building.
ObjectNode jsonArg = mapper.createObjectNode();
jsonArg.put("operation", operation.getName());
jsonArg.put("callbackUrl", testsCallbackUrl + "/api/tests/" + testResult.getId() + "/testCaseResult");
// First we have to retrieved and add the test script for this operation from within Postman collection.
JsonNode testScript = extractOperationTestScript(operation);
if (testScript != null) {
log.debug("Found a testScript for this operation !");
jsonArg.set("testScript", testScript);
}
// Then we have to add the corresponding 'requests' objects.
ArrayNode jsonRequests = mapper.createArrayNode();
for (Request request : requests) {
ObjectNode jsonRequest = mapper.createObjectNode();
String operationName = operation.getName().substring(operation.getName().indexOf(" ") + 1);
String customizedEndpointUrl = endpointUrl + URIBuilder.buildURIFromPattern(operationName, request.getQueryParameters());
log.debug("Using customized endpoint url: " + customizedEndpointUrl);
jsonRequest.put("endpointUrl", customizedEndpointUrl);
jsonRequest.put("method", operation.getMethod());
jsonRequest.put("name", request.getName());
if (request.getContent() != null && request.getContent().length() > 0) {
jsonRequest.put("body", request.getContent());
}
if (request.getQueryParameters() != null && request.getQueryParameters().size() > 0) {
ArrayNode jsonParams = buildQueryParams(request.getQueryParameters());
jsonRequest.set("queryParams", jsonParams);
}
// Set headers to request if any. Start with those coming from request itself.
// Add or override existing headers with test specific ones for operation and globals.
Set<Header> headers = new HashSet<>();
if (request.getHeaders() != null) {
headers.addAll(request.getHeaders());
}
if (testResult.getOperationsHeaders() != null) {
if (testResult.getOperationsHeaders().getGlobals() != null) {
headers.addAll(testResult.getOperationsHeaders().getGlobals());
}
if (testResult.getOperationsHeaders().get(operation.getName()) != null) {
headers.addAll(testResult.getOperationsHeaders().get(operation.getName()));
}
}
if (headers != null && headers.size() > 0) {
ArrayNode jsonHeaders = buildHeaders(headers);
jsonRequest.set("headers", jsonHeaders);
}
jsonRequests.add(jsonRequest);
}
jsonArg.set("requests", jsonRequests);
URI postmanRunnerURI = new URI(postmanRunnerUrl + "/tests/" + testResult.getId());
ClientHttpRequest httpRequest = clientHttpRequestFactory.createRequest(postmanRunnerURI, HttpMethod.POST);
httpRequest.getBody().write(mapper.writeValueAsBytes(jsonArg));
httpRequest.getHeaders().add("Content-Type", "application/json");
// Actually execute request.
ClientHttpResponse httpResponse = null;
try {
httpResponse = httpRequest.execute();
} catch (IOException ioe) {
log.error("IOException while executing request ", ioe);
} finally {
if (httpResponse != null) {
httpResponse.close();
}
}
return new ArrayList<>();
}
Aggregations