diff --git a/src/main/java/org/qortal/api/gateway/resource/GatewayResource.java b/src/main/java/org/qortal/api/gateway/resource/GatewayResource.java index 354631c0..091a0f19 100644 --- a/src/main/java/org/qortal/api/gateway/resource/GatewayResource.java +++ b/src/main/java/org/qortal/api/gateway/resource/GatewayResource.java @@ -16,6 +16,9 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.*; import javax.ws.rs.core.Context; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; @Path("/") @@ -76,50 +79,75 @@ public class GatewayResource { @GET - @Path("{name}/{path:.*}") + @Path("{path:.*}") @SecurityRequirement(name = "apiKey") - public HttpServletResponse getPathByName(@PathParam("name") String name, - @PathParam("path") String inPath) { + public HttpServletResponse getPath(@PathParam("path") String inPath) { // Block requests from localhost, to prevent websites/apps from running javascript that fetches unvetted data Security.disallowLoopbackRequests(request); - return this.get(name, ResourceIdType.NAME, Service.WEBSITE, null, inPath, null, "", true, true); + return this.parsePath(inPath, "gateway", null, "", true, true); } - @GET - @Path("{name}") - @SecurityRequirement(name = "apiKey") - public HttpServletResponse getIndexByName(@PathParam("name") String name) { - // Block requests from localhost, to prevent websites/apps from running javascript that fetches unvetted data - Security.disallowLoopbackRequests(request); - return this.get(name, ResourceIdType.NAME, Service.WEBSITE, null, "/", null, "", true, true); - } + + private HttpServletResponse parsePath(String inPath, String qdnContext, String secret58, String prefix, boolean usePrefix, boolean async) { + if (inPath == null || inPath.equals("")) { + // Assume not a real file + return ArbitraryDataRenderer.getResponse(response, 404, "Error 404: File Not Found"); + } - // Optional /site alternative for backwards support + // Default service is WEBSITE + Service service = Service.WEBSITE; + String name = null; + String identifier = null; + String outPath = ""; - @GET - @Path("/site/{name}/{path:.*}") - public HttpServletResponse getSitePathByName(@PathParam("name") String name, - @PathParam("path") String inPath) { - // Block requests from localhost, to prevent websites/apps from running javascript that fetches unvetted data - Security.disallowLoopbackRequests(request); - return this.get(name, ResourceIdType.NAME, Service.WEBSITE, null, inPath, null, "/site", true, true); - } + if (!inPath.contains("/")) { + // Assume entire inPath is a registered name + name = inPath; + } + else { + // Parse the path to determine what we need to load + List parts = new LinkedList<>(Arrays.asList(inPath.split("/"))); - @GET - @Path("/site/{name}") - public HttpServletResponse getSiteIndexByName(@PathParam("name") String name) { - // Block requests from localhost, to prevent websites/apps from running javascript that fetches unvetted data - Security.disallowLoopbackRequests(request); - return this.get(name, ResourceIdType.NAME, Service.WEBSITE, null, "/", null, "/site", true, true); - } + // Check if the first element is a service + try { + Service parsedService = Service.valueOf(parts.get(0).toUpperCase()); + if (parsedService != null) { + // First element matches a service, so we can assume it is one + service = parsedService; + parts.remove(0); + } + } catch (IllegalArgumentException e) { + // Not a service + } - - private HttpServletResponse get(String resourceId, ResourceIdType resourceIdType, Service service, String identifier, - String inPath, String secret58, String prefix, boolean usePrefix, boolean async) { + if (parts.isEmpty()) { + // We need more than just a service + return ArbitraryDataRenderer.getResponse(response, 404, "Error 404: File Not Found"); + } + + // Service is removed, so assume first element is now a registered name + name = parts.get(0); + parts.remove(0); + + if (!parts.isEmpty()) { + // Name is removed, so check if the first element is now an identifier + ArbitraryResourceStatus status = this.getStatus(service, name, parts.get(0), false); + if (status.getTotalChunkCount() > 0) { + // Matched service, name and identifier combination - so assume this is an identifier and can be removed + identifier = parts.get(0); + parts.remove(0); + } + } + + if (!parts.isEmpty()) { + // outPath can be built by combining any remaining parts + outPath = String.join("/", parts); + } + } - ArbitraryDataRenderer renderer = new ArbitraryDataRenderer(resourceId, resourceIdType, service, identifier, inPath, - secret58, prefix, usePrefix, async, "gateway", request, response, context); + ArbitraryDataRenderer renderer = new ArbitraryDataRenderer(name, ResourceIdType.NAME, service, identifier, outPath, + secret58, prefix, usePrefix, async, qdnContext, request, response, context); return renderer.render(); }