com.sap.cloud.yaas.servicesdk.apiconsole.utils.ApiConsoleLocationProvider Maven / Gradle / Ivy
/*
* © 2016 SAP SE or an SAP affiliate company.
* All rights reserved.
* Please see http://www.sap.com/corporate-en/legal/copyright/index.epx for additional trademark information and
* notices.
*/
package com.sap.cloud.yaas.servicesdk.apiconsole.utils;
import com.sap.cloud.yaas.servicesdk.ramlrewriter.filter.ExternalUrlHeaderUtil;
import com.sap.cloud.yaas.servicesdk.security.PathTraversalException;
import com.sap.cloud.yaas.servicesdk.security.SecurityUtils;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility class for providing the path to the API Console (with '?raml' parameter), which is different depending on
* whether the call comes from inside or outside the proxy.
*/
public class ApiConsoleLocationProvider
{
/**
* Query parameter for specifying a raml file.
*/
public static final String RAML_QUERY_PARAM = "raml";
private static final Logger LOG = LoggerFactory.getLogger(ApiConsoleLocationProvider.class);
private static final String REQUESTED_RESOURCE_DOES_NOT_EXIST = "Requested resource does not exist.";
private final RamlFilePathProvider ramlFilePathProvider = new RamlFilePathProvider();
/**
* Redirects to the given URI.
*
* @param uriToRedirectTo the URI to which to redirect
* @return the redirect response
*/
public Response processRedirect(final URI uriToRedirectTo)
{
return Response.temporaryRedirect(uriToRedirectTo).build();
}
/**
* Returns the URI of the API Console, e.g.
* "http://yaas-test.apigee.net/test/email/v2/api-console/index.html?raml=raml/api/emailservice.raml", or
* "http://email-v2.test.cf.hybris.com/api-console/index.html?raml=raml/api/emailservice.raml". It uses
* {@link RamlFilePathProvider} for resolving the value of "raml" parameter.
*
* @param baseUri the original base URI of the console
* @param externalUrlHeader the optional header appended by the proxy
* @return the full path to the console that will display the RAML-based API
*/
public URI getApiConsoleUri(final UriInfo baseUri, final String externalUrlHeader)
{
URI result = null;
if (ExternalUrlHeaderUtil.isExternal(externalUrlHeader))
{
result = ExternalUrlHeaderUtil.asExternalUri(externalUrlHeader);
}
else
{
result = baseUri.getRequestUri();
}
return UriBuilder
.fromUri(result)
.queryParam(RAML_QUERY_PARAM, RamlFilePathProvider.RAML_RESOURCE_PATH + getRelativeRamlUri())
.build();
}
/**
* Returns the URI of the main RAML file, relative to the {@link RamlFilePathProvider#RAML_RESOURCE_PATH}, e.g.
* "api/emailservice.raml"
*
* @return the relative path to the {@link #ramlFilePathProvider.RAML_RESOURCE_PATH} that will provide the RAML
*/
public String getRelativeRamlUri()
{
return ramlFilePathProvider.getRamlResourcePath();
}
/**
* Resolves given raml resource in relation to given root folder by assuring that it will not traverse outside the
* root folder.
*
* @param basePath root folder where the resource will be resolved in
* @param resource resource to resolve
* @return URL to resolved resource
*/
public URL resolveRamlResource(final Path basePath, final String resource)
{
final Path path = SecurityUtils.sanitizePath(basePath, stripApiPathFromRamlFile(resource));
if (!path.toFile().exists())
{
if (LOG.isTraceEnabled())
{
LOG.trace(String.format("RAML file located in '%s' not found ", path.toString()));
}
throw new PathTraversalException(REQUESTED_RESOURCE_DOES_NOT_EXIST);
}
try
{
return path.toUri().toURL();
}
catch (final MalformedURLException e)
{
LOG.error(String.format("RAML file located in '%s' not found, invalid url format ", path.toString()), e);
throw new PathTraversalException(REQUESTED_RESOURCE_DOES_NOT_EXIST, e);
}
}
/**
* Strips the prefix for the uri parameter.
*/
@SuppressWarnings("PMD.UnusedPrivateMethod")
private java.nio.file.Path stripApiPathFromRamlFile(final String ramlResource) throws PathTraversalException
{
if (ramlResource.startsWith(RamlFilePathProvider.API_RESOURCE_PATH))
{
return Paths.get(ramlResource.substring(RamlFilePathProvider.API_RESOURCE_PATH.length()));
}
else
{
if (LOG.isTraceEnabled())
{
LOG.trace("Retrieved RAML resource is not in the context of the api folder :" + ramlResource);
}
throw new PathTraversalException("Retrieved RAML resource is not in the context of the api folder.");
}
}
}