Last active
May 11, 2023 16:19
-
-
Save cpilsworth/cb006177cbc51585708dc414bc7d668e to your computer and use it in GitHub Desktop.
Cloud Storage Direct Asset Download URL generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.chrisp.rde.core.servlets; | |
import org.apache.commons.lang3.StringUtils; | |
import org.apache.jackrabbit.api.binary.BinaryDownload; | |
import org.apache.jackrabbit.api.binary.BinaryDownloadOptions; | |
import org.apache.sling.api.SlingHttpServletRequest; | |
import org.apache.sling.api.SlingHttpServletResponse; | |
import org.apache.sling.api.resource.Resource; | |
import org.apache.sling.api.servlets.OptingServlet; | |
import org.apache.sling.api.servlets.SlingSafeMethodsServlet; | |
import org.apache.sling.servlets.annotations.SlingServletResourceTypes; | |
import org.osgi.service.component.annotations.Component; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import javax.jcr.Binary; | |
import javax.jcr.Node; | |
import javax.servlet.Servlet; | |
import javax.servlet.ServletException; | |
import java.io.IOException; | |
import java.net.URI; | |
import java.util.Map; | |
import java.util.regex.Matcher; | |
import java.util.regex.Pattern; | |
@Component(service = {Servlet.class}) | |
@SlingServletResourceTypes( | |
resourceTypes = "dam/Asset", | |
methods = "GET", | |
selectors = "woi" | |
) | |
/** | |
* Returns a redirect to the cloud storage of the underlying original asset when `woi` selector added. | |
* e.g. https://author-p31359-e934772.adobeaemcloud.com/content/dam/xxxx/sample.jpg.woi/image.png | |
*/ | |
public class ImageSignedUrlRedirectServlet extends SlingSafeMethodsServlet implements OptingServlet { | |
private static final Logger log = LoggerFactory.getLogger(ImageSignedUrlRedirectServlet.class); | |
public static final String DEFAULT_FILENAME_PATTERN = "(image|img)\\.(.+)"; | |
private final Pattern lastSuffixPattern = Pattern.compile(DEFAULT_FILENAME_PATTERN); | |
private String cacheHeader; | |
/** | |
* Only accept requests that. | |
* - Are not null | |
* - Have a suffix | |
* - Whose first suffix segment is a registered transform name | |
* - Whose last suffix matches the image file name pattern | |
* | |
* @param request SlingRequest object | |
* @return true if the Servlet should handle the request | |
*/ | |
@Override | |
public final boolean accepts(final SlingHttpServletRequest request) { | |
if (request == null) { | |
return false; | |
} | |
final String suffix = request.getRequestPathInfo().getSuffix(); | |
if (StringUtils.isBlank(suffix)) { | |
return false; | |
} | |
final String lastSuffix = PathInfoUtil.getLastSuffixSegment(request); | |
final Matcher matcher = lastSuffixPattern.matcher(lastSuffix); | |
return matcher.matches(); | |
} | |
@Override | |
protected final void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response) throws | |
ServletException, IOException { | |
final Resource resource = request.getResource(); | |
if (!isAsset(resource)) { | |
response.setStatus(404); | |
return; | |
} | |
try { | |
Resource rendition = resource.getChild("jcr:content/renditions/original"); | |
Node ntFile = rendition.adaptTo(Node.class); | |
Node ntResource = ntFile.getNode("jcr:content"); | |
Binary binary = ntResource.getProperty("jcr:data").getBinary(); | |
if (binary instanceof BinaryDownload) { | |
BinaryDownload binaryDownload = (BinaryDownload) binary; | |
BinaryDownloadOptions.BinaryDownloadOptionsBuilder builder = BinaryDownloadOptions.builder() | |
.withFileName(ntFile.getName()) | |
.withMediaType(ntResource.getProperty("jcr:mimeType").getString()); | |
if (ntResource.hasProperty("jcr:encoding")) { | |
builder.withCharacterEncoding(ntResource.getProperty("jcr:encoding").getString()); | |
} | |
// if you need to prevent the browser from potentially executing the response | |
// (for example js, flash, html), you can enforce a download with this option | |
// builder.withDispositionTypeAttachment(); | |
final URI uri = binaryDownload.getURI(builder.build()); | |
log.info("redirect: {}", uri); | |
response.sendRedirect(uri.toString()); | |
} | |
} catch (Throwable e) { | |
log.error("Exception fetching signed url", e); | |
response.setStatus(500); | |
} | |
} | |
public static boolean isAsset(Resource resource) { | |
return null != resource && "dam:Asset".equals(resource.getResourceType()); | |
} | |
protected void activate(Map<String, Object> properties) { | |
// this.cacheHeader = properties.get("cacheControl").toString(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* #%L | |
* ACS AEM Commons Bundle | |
* %% | |
* Copyright (C) 2013 Adobe | |
* %% | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
* #L% | |
*/ | |
package com.chrisp.rde.core.servlets; | |
import org.apache.commons.lang.StringUtils; | |
import org.apache.sling.api.SlingHttpServletRequest; | |
import org.apache.sling.api.request.RequestPathInfo; | |
import org.osgi.annotation.versioning.ProviderType; | |
/** | |
* Util class to help with parsing URIs and PathInfos. | |
*/ | |
@ProviderType | |
public final class PathInfoUtil { | |
private PathInfoUtil() { | |
} | |
/** | |
* Get a named Query Parameter from the Request. | |
* | |
* @param request | |
* @param key | |
* @return | |
*/ | |
public static String getQueryParam(final SlingHttpServletRequest request, final String key) { | |
return request.getParameter(key); | |
} | |
/** | |
* Get a named Query Parameter from the Request. | |
* | |
* @param request | |
* @param key | |
* @param dfault Value to return if Query Parameter value is blank | |
* @return | |
*/ | |
public static String getQueryParam(final SlingHttpServletRequest request, final String key, final String dfault) { | |
String tmp = request.getParameter(key); | |
if (StringUtils.isBlank(tmp)) { | |
return dfault; | |
} | |
return tmp; | |
} | |
/** | |
* Gets the selector at the supplied index. | |
* <p> | |
* Given: /content/page.selA.selB.html | |
* <br> | |
* getSelector(request, 0) // --> "selA" | |
* <br> | |
* getSelector(request, 1) // --> "selB" | |
* | |
* @param request | |
* @param index | |
* @return null if selector cannot be found at the specified index | |
*/ | |
public static String getSelector(final SlingHttpServletRequest request, final int index) { | |
return getSelector(request, index, null); | |
} | |
/** | |
* <p> | |
* Gets the selector at the supplied index, using a default if | |
* there is no selector at that index. | |
* </p><p> | |
* Given: /content/page.selA.html | |
* <br> | |
* getSelector(request, 0, "default") // --> "selA" | |
* <br> | |
* getSelector(request, 1, "default2") // --> "default2" | |
* </p> | |
* | |
* @param request the request | |
* @param index the index | |
* @param defaultValue the default value | |
* @return the selector value or the default | |
*/ | |
public static String getSelector(final SlingHttpServletRequest request, | |
final int index, final String defaultValue) { | |
RequestPathInfo pathInfo = request.getRequestPathInfo(); | |
if (pathInfo == null) { | |
return null; | |
} | |
String[] selectors = pathInfo.getSelectors(); | |
if (selectors == null) { | |
return null; | |
} | |
if (index >= 0 && index < selectors.length) { | |
return selectors[index]; | |
} else { | |
return defaultValue; | |
} | |
} | |
/** | |
* Gets the suffixes as an array; each segment is the text between the /'s. | |
* | |
* /segment-0/segment-1/segment-2 | |
* | |
* @param request | |
* @return and array of the suffix segments or empty array | |
*/ | |
public static String[] getSuffixSegments(final SlingHttpServletRequest request) { | |
RequestPathInfo pathInfo = request.getRequestPathInfo(); | |
if (pathInfo == null || pathInfo.getSuffix() == null) { | |
return new String[] {}; | |
} | |
return StringUtils.split(pathInfo.getSuffix(), '/'); | |
} | |
/** | |
* <p> | |
* Gets the suffix segment at the supplied index. | |
* </p><p> | |
* Given: /content/page.html/suffixA/suffixB | |
* <br> | |
* getSuffixSegment(request, 0) // --> "suffixA" | |
* <br> | |
* getSuffixSegment(request, 1) // --> "suffixB" | |
* </p> | |
* | |
* @param request | |
* @param index | |
* @return null if suffix segment cannot be found at the specified index | |
*/ | |
public static String getSuffixSegment(final SlingHttpServletRequest request, int index) { | |
final String[] suffixes = getSuffixSegments(request); | |
if (index >= 0 && index < suffixes.length) { | |
return suffixes[index]; | |
} else { | |
return null; | |
} | |
} | |
/** | |
* Get the entire suffix. | |
* | |
* @param request | |
* @return Returns null if Request's pathInfo or Suffix is null | |
*/ | |
public static String getSuffix(final SlingHttpServletRequest request) { | |
RequestPathInfo pathInfo = request.getRequestPathInfo(); | |
if (pathInfo == null || pathInfo.getSuffix() == null) { | |
return null; | |
} | |
return pathInfo.getSuffix(); | |
} | |
/** | |
* Get the first suffix segment. | |
* | |
* @param request | |
* @return the String in the first suffix segment or null if no suffix | |
*/ | |
public static String getFirstSuffixSegment(final SlingHttpServletRequest request) { | |
return getSuffixSegment(request, 0); | |
} | |
/** | |
* Gets the last suffix segment. | |
* | |
* @param request | |
* @return the String in the last suffix segment or null if no suffix | |
*/ | |
public static String getLastSuffixSegment(final SlingHttpServletRequest request) { | |
final String[] suffixes = getSuffixSegments(request); | |
if (suffixes.length < 1) { | |
return null; | |
} else { | |
return suffixes[suffixes.length - 1]; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment