use of org.apache.synapse.api.dispatch.RESTDispatcher in project wso2-synapse by wso2.
the class API method process.
public void process(MessageContext synCtx) {
auditDebug("Processing message with ID: " + synCtx.getMessageID() + " through the " + "API: " + name);
synCtx.setProperty(RESTConstants.PROCESSED_API, this);
synCtx.setProperty(RESTConstants.SYNAPSE_REST_API, getName());
synCtx.setProperty(RESTConstants.SYNAPSE_REST_API_VERSION, versionStrategy.getVersion());
synCtx.setProperty(RESTConstants.REST_API_CONTEXT, context);
synCtx.setProperty(RESTConstants.SYNAPSE_REST_API_VERSION_STRATEGY, versionStrategy.getVersionType());
synCtx.setProperty(SynapseConstants.ARTIFACT_NAME, SynapseConstants.FAIL_SAFE_MODE_API + getName());
// get API log for this message and attach to the message context
((Axis2MessageContext) synCtx).setServiceLog(apiLog);
// Calculate REST_URL_POSTFIX from full request path
String restURLPostfix = (String) synCtx.getProperty(RESTConstants.REST_FULL_REQUEST_PATH);
if (!synCtx.isResponse() && restURLPostfix != null) {
// Skip for response path
if (!restURLPostfix.startsWith("/")) {
restURLPostfix = "/" + restURLPostfix;
}
if (restURLPostfix.startsWith(context)) {
restURLPostfix = restURLPostfix.substring(context.length());
}
if (versionStrategy instanceof URLBasedVersionStrategy) {
String version = versionStrategy.getVersion();
if (restURLPostfix.startsWith(version)) {
restURLPostfix = restURLPostfix.substring(version.length());
} else if (restURLPostfix.startsWith("/" + version)) {
restURLPostfix = restURLPostfix.substring(version.length() + 1);
}
}
((Axis2MessageContext) synCtx).getAxis2MessageContext().setProperty(NhttpConstants.REST_URL_POSTFIX, restURLPostfix);
}
if (synCtx.isResponse()) {
org.apache.axis2.context.MessageContext context = ((Axis2MessageContext) synCtx).getAxis2MessageContext();
context.setProperty(NhttpConstants.ACTIVITY_ID_STATUS, true);
Map headers = (Map) context.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
String sysRestrictedHeaders = System.getProperty(CorrelationConstants.RESTRICT_HEADERS_SYS_PROP);
List<String> headerList;
if (sysRestrictedHeaders != null) {
headerList = Arrays.asList(sysRestrictedHeaders.split(","));
if (headerList.contains(PassThroughConstants.CORRELATION_DEFAULT_HEADER)) {
((Axis2MessageContext) synCtx).getAxis2MessageContext().setProperty(NhttpConstants.ACTIVITY_ID_STATUS, false);
}
}
Object status = context.getProperty(NhttpConstants.ACTIVITY_ID_STATUS);
if ((status != null) && ((boolean) status)) {
if (headers != null) {
headers.put(PassThroughConfiguration.getInstance().getCorrelationHeaderName(), context.getProperty(CorrelationConstants.CORRELATION_ID));
}
}
}
for (Handler handler : handlers) {
auditDebug("Processing message with ID: " + synCtx.getMessageID() + " through " + "handler: " + handler.getClass().getName());
boolean proceed;
if (synCtx.isResponse()) {
proceed = handler.handleResponse(synCtx);
} else {
proceed = handler.handleRequest(synCtx);
}
if (!proceed) {
return;
}
}
if (synCtx.isResponse()) {
String resourceName = (String) synCtx.getProperty(RESTConstants.SYNAPSE_RESOURCE);
if (resourceName != null) {
Resource resource = resources.get(resourceName);
if (resource != null) {
resource.process(synCtx);
}
} else if (log.isDebugEnabled()) {
auditDebug("No resource information on the response: " + synCtx.getMessageID());
}
return;
}
String path = ApiUtils.getFullRequestPath(synCtx);
String subPath;
if (versionStrategy.getVersionType().equals(VersionStrategyFactory.TYPE_URL)) {
// for URL based
// request --> http://{host:port}/context/version/path/to/resource
subPath = path.substring(context.length() + versionStrategy.getVersion().length() + 1);
} else {
subPath = path.substring(context.length());
}
if ("".equals(subPath)) {
subPath = "/";
}
synCtx.setProperty(RESTConstants.REST_SUB_REQUEST_PATH, subPath);
org.apache.axis2.context.MessageContext msgCtx = ((Axis2MessageContext) synCtx).getAxis2MessageContext();
String hostHeader = getHostHeader(msgCtx);
if (hostHeader != null) {
synCtx.setProperty(RESTConstants.REST_URL_PREFIX, msgCtx.getIncomingTransportName() + "://" + hostHeader);
}
Set<Resource> acceptableResources = new LinkedHashSet<Resource>();
for (Resource r : resources.values()) {
if (isBound(r, synCtx) && r.canProcess(synCtx)) {
acceptableResources.add(r);
}
}
boolean processed = false;
if (!acceptableResources.isEmpty()) {
for (RESTDispatcher dispatcher : ApiUtils.getDispatchers()) {
Resource resource = dispatcher.findResource(synCtx, acceptableResources);
if (resource != null) {
if (synCtx.getEnvironment().isDebuggerEnabled()) {
if (!synCtx.isResponse()) {
SynapseWireLogHolder wireLogHolder = (SynapseWireLogHolder) ((Axis2MessageContext) synCtx).getAxis2MessageContext().getProperty(SynapseDebugInfoHolder.SYNAPSE_WIRE_LOG_HOLDER_PROPERTY);
if (wireLogHolder == null) {
wireLogHolder = new SynapseWireLogHolder();
}
if (synCtx.getProperty(RESTConstants.SYNAPSE_REST_API) != null && !synCtx.getProperty(RESTConstants.SYNAPSE_REST_API).toString().isEmpty()) {
wireLogHolder.setApiName(synCtx.getProperty(RESTConstants.SYNAPSE_REST_API).toString());
if (resource.getDispatcherHelper() != null) {
if (resource.getDispatcherHelper().getString() != null && !resource.getDispatcherHelper().getString().isEmpty()) {
wireLogHolder.setResourceUrlString(resource.getDispatcherHelper().getString());
}
}
}
((Axis2MessageContext) synCtx).getAxis2MessageContext().setProperty(SynapseDebugInfoHolder.SYNAPSE_WIRE_LOG_HOLDER_PROPERTY, wireLogHolder);
}
}
resource.process(synCtx);
return;
}
}
handleResourceNotFound(synCtx);
} else {
// This will get executed only in unhappy path. So ok to have the iterator.
boolean resourceFound = false;
boolean matchingMethodFound = false;
for (RESTDispatcher dispatcher : ApiUtils.getDispatchers()) {
Resource resource = dispatcher.findResource(synCtx, resources.values());
if (resource != null) {
resourceFound = true;
String method = (String) msgCtx.getProperty(Constants.Configuration.HTTP_METHOD);
matchingMethodFound = resource.hasMatchingMethod(method);
break;
}
}
if (!resourceFound) {
handleResourceNotFound(synCtx);
} else if (!matchingMethodFound) {
handleMethodNotAllowed(synCtx);
} else {
// Resource found, and matching method also found, which means request is BAD_REQUEST(400)
msgCtx.setProperty(SynapseConstants.HTTP_SC, HttpStatus.SC_BAD_REQUEST);
msgCtx.setProperty("NIO-ACK-Requested", true);
}
}
}
use of org.apache.synapse.api.dispatch.RESTDispatcher in project carbon-apimgt by wso2.
the class CORSRequestHandler method handleResourceNotFound.
private void handleResourceNotFound(MessageContext messageContext, List<Resource> allAPIResources) {
Resource uriMatchingResource = null;
for (RESTDispatcher dispatcher : RESTUtils.getDispatchers()) {
uriMatchingResource = dispatcher.findResource(messageContext, allAPIResources);
// If a resource with a matching URI was found.
if (uriMatchingResource != null) {
onResourceNotFoundError(messageContext, HttpStatus.SC_METHOD_NOT_ALLOWED, APIMgtGatewayConstants.METHOD_NOT_FOUND_ERROR_MSG);
return;
}
}
// If a resource with a matching URI was not found.
// Respond with a 404.
onResourceNotFoundError(messageContext, HttpStatus.SC_NOT_FOUND, APIMgtGatewayConstants.RESOURCE_NOT_FOUND_ERROR_MSG);
}
use of org.apache.synapse.api.dispatch.RESTDispatcher in project carbon-apimgt by wso2.
the class InboundWebSocketProcessor method setMatchingResource.
/**
* Get matching resource for invoking handshake request.
*
* @param ctx Channel context
* @param req Handshake request
* @param inboundMessageContext InboundMessageContext
* @throws WebSocketApiException If an error occurs
* @throws ResourceNotFoundException If no matching API or resource found
*/
private void setMatchingResource(ChannelHandlerContext ctx, FullHttpRequest req, InboundMessageContext inboundMessageContext) throws WebSocketApiException, ResourceNotFoundException {
String matchingResource;
try {
MessageContext synCtx = getMessageContext(inboundMessageContext);
API api = InboundWebsocketProcessorUtil.getApi(synCtx, inboundMessageContext);
if (api == null) {
throw new ResourceNotFoundException("No matching API found to dispatch the request");
}
inboundMessageContext.setApi(api);
reConstructFullUriWithVersion(req, synCtx, inboundMessageContext);
inboundMessageContext.setApiContext(api.getContext());
Resource selectedResource = null;
Utils.setSubRequestPath(api, synCtx);
Set<Resource> acceptableResources = new LinkedHashSet<>(Arrays.asList(api.getResources()));
if (!acceptableResources.isEmpty()) {
for (RESTDispatcher dispatcher : ApiUtils.getDispatchers()) {
Resource resource = dispatcher.findResource(synCtx, acceptableResources);
if (resource != null) {
selectedResource = resource;
if (APIUtil.isAnalyticsEnabled()) {
WebSocketUtils.setApiPropertyToChannel(ctx, APIMgtGatewayConstants.SYNAPSE_ENDPOINT_ADDRESS, WebSocketUtils.getEndpointUrl(resource, synCtx));
}
break;
}
}
}
setApiPropertiesToChannel(ctx, inboundMessageContext);
if (selectedResource == null) {
throw new ResourceNotFoundException("No matching resource found to dispatch the request");
}
if (APIConstants.GRAPHQL_API.equals(inboundMessageContext.getElectedAPI().getApiType())) {
inboundMessageContext.setGraphQLSchemaDTO(DataHolder.getInstance().getGraphQLSchemaDTOForAPI(inboundMessageContext.getElectedAPI().getUuid()));
}
matchingResource = selectedResource.getDispatcherHelper().getString();
if (log.isDebugEnabled()) {
log.info("Selected resource for API dispatch : " + matchingResource);
}
} catch (AxisFault | URISyntaxException e) {
throw new WebSocketApiException("Error while getting matching resource for Websocket API");
}
inboundMessageContext.setMatchingResource(matchingResource);
}
use of org.apache.synapse.api.dispatch.RESTDispatcher in project carbon-apimgt by wso2.
the class APIKeyValidator method findMatchingVerb.
public List<VerbInfoDTO> findMatchingVerb(MessageContext synCtx) throws ResourceNotFoundException, APISecurityException {
List<VerbInfoDTO> verbInfoList = new ArrayList<>();
String resourceCacheKey;
String httpMethod = (String) ((Axis2MessageContext) synCtx).getAxis2MessageContext().getProperty(Constants.Configuration.HTTP_METHOD);
String apiContext = (String) synCtx.getProperty(RESTConstants.REST_API_CONTEXT);
String apiVersion = (String) synCtx.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION);
String fullRequestPath = (String) synCtx.getProperty(RESTConstants.REST_FULL_REQUEST_PATH);
String electedResource = (String) synCtx.getProperty(APIConstants.API_ELECTED_RESOURCE);
ArrayList<String> resourceArray = null;
if (electedResource != null) {
if (APIConstants.GRAPHQL_API.equalsIgnoreCase((String) synCtx.getProperty(APIConstants.API_TYPE))) {
resourceArray = new ArrayList<>(Arrays.asList(electedResource.split(",")));
} else {
resourceArray = new ArrayList<>(Arrays.asList(electedResource));
}
}
String requestPath = getRequestPath(synCtx, apiContext, apiVersion, fullRequestPath);
if ("".equals(requestPath)) {
requestPath = "/";
}
if (log.isDebugEnabled()) {
log.debug("Setting REST_SUB_REQUEST_PATH in msg context: " + requestPath);
}
synCtx.setProperty(RESTConstants.REST_SUB_REQUEST_PATH, requestPath);
// verb has been put into the cache.
if (resourceArray != null) {
for (String resourceString : resourceArray) {
VerbInfoDTO verbInfo;
if (isGatewayAPIResourceValidationEnabled) {
String apiCacheKey = APIUtil.getAPIInfoDTOCacheKey(apiContext, apiVersion);
if (!getResourceCache().containsKey(apiCacheKey)) {
break;
}
resourceCacheKey = APIUtil.getResourceInfoDTOCacheKey(apiContext, apiVersion, resourceString, httpMethod);
verbInfo = (VerbInfoDTO) getResourceCache().get(resourceCacheKey);
// Cache hit
if (verbInfo != null) {
if (log.isDebugEnabled()) {
log.debug("Found resource in Cache for key: " + resourceCacheKey);
}
verbInfoList.add(verbInfo);
} else {
if (log.isDebugEnabled()) {
log.debug("Resource not found in cache for key: " + resourceCacheKey);
}
}
}
}
if (resourceArray.size() == verbInfoList.size()) {
return verbInfoList;
}
} else {
API selectedApi = Utils.getSelectedAPI(synCtx);
Resource selectedResource = null;
String resourceString;
if (selectedApi != null) {
Resource[] selectedAPIResources = selectedApi.getResources();
Set<Resource> acceptableResources = new LinkedHashSet<Resource>();
for (Resource resource : selectedAPIResources) {
// If the requesting method is OPTIONS or if the Resource contains the requesting method
if (RESTConstants.METHOD_OPTIONS.equals(httpMethod) || (resource.getMethods() != null && Arrays.asList(resource.getMethods()).contains(httpMethod))) {
acceptableResources.add(resource);
}
}
if (acceptableResources.size() > 0) {
for (RESTDispatcher dispatcher : RESTUtils.getDispatchers()) {
Resource resource = dispatcher.findResource(synCtx, acceptableResources);
if (resource != null && Arrays.asList(resource.getMethods()).contains(httpMethod)) {
selectedResource = resource;
break;
}
}
}
}
if (selectedResource == null) {
// No matching resource found.
String msg = "Could not find matching resource for " + requestPath;
log.error(msg);
throw new ResourceNotFoundException(msg);
}
resourceString = selectedResource.getDispatcherHelper().getString();
resourceCacheKey = APIUtil.getResourceInfoDTOCacheKey(apiContext, apiVersion, resourceString, httpMethod);
if (log.isDebugEnabled()) {
log.debug("Selected Resource: " + resourceString);
}
// Set the elected resource
synCtx.setProperty(APIConstants.API_ELECTED_RESOURCE, resourceString);
if (isGatewayAPIResourceValidationEnabled) {
VerbInfoDTO verbInfo;
verbInfo = (VerbInfoDTO) getResourceCache().get(resourceCacheKey);
// Cache hit
if (verbInfo != null) {
if (log.isDebugEnabled()) {
log.debug("Got Resource from cache for key: " + resourceCacheKey);
}
verbInfoList.add(verbInfo);
return verbInfoList;
} else if (log.isDebugEnabled()) {
log.debug("Cache miss for Resource for key: " + resourceCacheKey);
}
}
}
String apiCacheKey = APIUtil.getAPIInfoDTOCacheKey(apiContext, apiVersion);
APIInfoDTO apiInfoDTO = null;
if (isGatewayAPIResourceValidationEnabled) {
apiInfoDTO = (APIInfoDTO) getResourceCache().get(apiCacheKey);
}
// Cache miss
if (apiInfoDTO == null) {
if (log.isDebugEnabled()) {
log.debug("Could not find API object in cache for key: " + apiCacheKey);
}
String apiType = (String) synCtx.getProperty(APIMgtGatewayConstants.API_TYPE);
if (APIConstants.ApiTypes.PRODUCT_API.name().equalsIgnoreCase(apiType)) {
apiInfoDTO = doGetAPIProductInfo(synCtx, apiContext, apiVersion);
} else {
apiInfoDTO = doGetAPIInfo(synCtx, apiContext, apiVersion);
}
if (isGatewayAPIResourceValidationEnabled) {
getResourceCache().put(apiCacheKey, apiInfoDTO);
}
}
if (apiInfoDTO.getResources() != null) {
for (ResourceInfoDTO resourceInfoDTO : apiInfoDTO.getResources()) {
Set<VerbInfoDTO> verbDTOList = resourceInfoDTO.getHttpVerbs();
for (VerbInfoDTO verb : verbDTOList) {
if (verb.getHttpVerb().equals(httpMethod)) {
for (String resourceString : resourceArray) {
if (isResourcePathMatching(resourceString, resourceInfoDTO)) {
resourceCacheKey = APIUtil.getResourceInfoDTOCacheKey(apiContext, apiVersion, resourceString, httpMethod);
verb.setRequestKey(resourceCacheKey);
verbInfoList.add(verb);
if (isGatewayAPIResourceValidationEnabled) {
// Set cache key in the message c\ontext so that it can be used by the subsequent handlers.
if (log.isDebugEnabled()) {
log.debug("Putting resource object in cache with key: " + resourceCacheKey);
}
getResourceCache().put(resourceCacheKey, verb);
synCtx.setProperty(APIConstants.API_RESOURCE_CACHE_KEY, resourceCacheKey);
}
}
}
}
}
}
}
if (verbInfoList.size() == 0) {
verbInfoList = null;
}
return verbInfoList;
}
use of org.apache.synapse.api.dispatch.RESTDispatcher in project carbon-apimgt by wso2.
the class CORSRequestHandler method handleRequest.
@MethodStats
public boolean handleRequest(MessageContext messageContext) {
Timer.Context context = startMetricTimer();
TracingSpan CORSRequestHandlerSpan = null;
if (Util.tracingEnabled()) {
TracingSpan responseLatencySpan = (TracingSpan) messageContext.getProperty(APIMgtGatewayConstants.RESOURCE_SPAN);
TracingTracer tracer = Util.getGlobalTracer();
CORSRequestHandlerSpan = Util.startSpan(APIMgtGatewayConstants.CORS_REQUEST_HANDLER, responseLatencySpan, tracer);
}
if (Utils.isGraphQLSubscriptionRequest(messageContext)) {
if (log.isDebugEnabled()) {
log.debug("Skipping GraphQL subscription handshake request.");
}
return true;
}
try {
if (!initializeHeaderValues) {
initializeHeaders();
}
String apiContext = (String) messageContext.getProperty(RESTConstants.REST_API_CONTEXT);
String apiVersion = (String) messageContext.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION);
String httpMethod = (String) ((Axis2MessageContext) messageContext).getAxis2MessageContext().getProperty(Constants.Configuration.HTTP_METHOD);
API selectedApi = Utils.getSelectedAPI(messageContext);
org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).getAxis2MessageContext();
Map headers = (Map) axis2MC.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
String corsRequestMethod = (String) headers.get(APIConstants.CORSHeaders.ACCESS_CONTROL_REQUEST_METHOD);
Resource selectedResource = null;
Utils.setSubRequestPath(selectedApi, messageContext);
if (selectedApi != null) {
Resource[] allAPIResources = selectedApi.getResources();
Set<Resource> acceptableResources = new LinkedHashSet<>();
for (Resource resource : allAPIResources) {
// If the requesting method is OPTIONS or if the Resource contains the requesting method
if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resource.getMethods() != null && Arrays.asList(resource.getMethods()).contains(corsRequestMethod)) || (resource.getMethods() != null && Arrays.asList(resource.getMethods()).contains(httpMethod))) {
acceptableResources.add(resource);
}
}
if (!acceptableResources.isEmpty()) {
for (RESTDispatcher dispatcher : RESTUtils.getDispatchers()) {
Resource resource = dispatcher.findResource(messageContext, acceptableResources);
if (resource != null) {
selectedResource = resource;
break;
}
}
if (selectedResource == null) {
handleResourceNotFound(messageContext, Arrays.asList(allAPIResources));
return false;
}
} else // If no acceptable resources are found
{
// We're going to send a 405 or a 404. Run the following logic to determine which.
handleResourceNotFound(messageContext, Arrays.asList(allAPIResources));
return false;
}
// No matching resource found
if (selectedResource == null) {
// Respond with a 404
onResourceNotFoundError(messageContext, HttpStatus.SC_NOT_FOUND, APIMgtGatewayConstants.RESOURCE_NOT_FOUND_ERROR_MSG);
return false;
}
}
String resourceString = selectedResource.getDispatcherHelper().getString();
String resourceCacheKey = APIUtil.getResourceInfoDTOCacheKey(apiContext, apiVersion, resourceString, httpMethod);
messageContext.setProperty(APIConstants.API_ELECTED_RESOURCE, resourceString);
messageContext.setProperty(APIConstants.API_RESOURCE_CACHE_KEY, resourceCacheKey);
messageContext.setProperty(APIConstants.REST_METHOD, httpMethod);
// If this is an OPTIONS request
if (APIConstants.SupportedHTTPVerbs.OPTIONS.name().equalsIgnoreCase(httpMethod)) {
// If the OPTIONS method is explicity specified in the resource
if (Arrays.asList(selectedResource.getMethods()).contains(APIConstants.SupportedHTTPVerbs.OPTIONS.name())) {
// We will not handle the CORS headers, let the back-end do it.
return true;
}
setCORSHeaders(messageContext, selectedResource);
Mediator corsSequence = messageContext.getSequence(APIConstants.CORS_SEQUENCE_NAME);
if (corsSequence != null) {
corsSequence.mediate(messageContext);
}
Utils.send(messageContext, HttpStatus.SC_OK);
return false;
} else if (APIConstants.IMPLEMENTATION_TYPE_INLINE.equalsIgnoreCase(apiImplementationType)) {
setCORSHeaders(messageContext, selectedResource);
messageContext.getSequence(APIConstants.CORS_SEQUENCE_NAME).mediate(messageContext);
}
setCORSHeaders(messageContext, selectedResource);
return true;
} catch (Exception e) {
if (Util.tracingEnabled() && CORSRequestHandlerSpan != null) {
Util.setTag(CORSRequestHandlerSpan, APIMgtGatewayConstants.ERROR, APIMgtGatewayConstants.CORS_REQUEST_HANDLER_ERROR);
}
throw e;
} finally {
stopMetricTimer(context);
if (Util.tracingEnabled()) {
Util.finishSpan(CORSRequestHandlerSpan);
}
}
}
Aggregations