AEM 6550 - Stream Binary or Text Content of Provided URL thru AEM for bypassing CORS Issues

Goal

If you are encountering CORS (Access-Control-Allow-Origin) issues when making client side ajax calls to another server (which does not provide Access-Control-Allow-Origin header in response) from browser, a quick alternative is to proxy the URL from AEM... the following post proxies images or xml content (useful when accessing Scene7 Render Server images...)

Github

                     http://localhost:4502/bin/experience-aem/proxy?format=XML&url=http%3A%2F%2Fsample.scene7.com%2Fir%2Frender%2FS7trainRender%2Fninewest_shoe%3Freq%3Dcontents




Solution

Add a servlet apps.experienceaem.assets.ProxyContentServlet to read the url, format and proxy the response through AEM...

package apps.experienceaem.assets;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.fluent.Request;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.osgi.services.HttpClientBuilderFactory;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.*;

@Component(
        name = "Experience AEM Image Proxy Servlet",
        immediate = true,
        service = Servlet.class,
        property = {
                "sling.servlet.methods=GET",
                "sling.servlet.paths=/bin/experience-aem/proxy"
        }
)
public class ProxyContentServlet extends SlingAllMethodsServlet{
    private static final Logger log = LoggerFactory.getLogger(ProxyContentServlet.class);

    private static String IMAGE = "IMAGE";
    private static String XML = "XML";

    @Reference
    private HttpClientBuilderFactory httpClientBuilderFactory;

    private CloseableHttpClient httpClient;

    protected void activate(ComponentContext ctx) {
        HttpClientBuilder builder = httpClientBuilderFactory.newBuilder();

        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000)
                .setSocketTimeout(30000).build();

        builder.setDefaultRequestConfig(requestConfig);

        httpClient = builder.build();

    }
    @Override
    protected final void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws
                                ServletException, IOException {
        try {
            String url = request.getParameter("url");
            String fileName = request.getParameter("fileName");
            String format = request.getParameter("format");

            if(StringUtils.isEmpty(url)){
                throw new Exception("Empty url");
            }

            if(StringUtils.isEmpty(format)){
                format = IMAGE;
            }

            if(format.equalsIgnoreCase(IMAGE)){
                streamImage(response, url, fileName);
            }else if(format.equalsIgnoreCase(XML)){
                streamXML(response, url);
            }
        } catch (Exception e) {
            log.error("Could not getting binary response", e);
            response.setStatus(SlingHttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    private void streamImage(SlingHttpServletResponse response, String url, String fileName) throws Exception{
        if(StringUtils.isEmpty(fileName)){
            fileName = "eaem.jpg";
        }

        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition","attachment; filename=" + fileName);

        writeContent(response, url);
    }

    private void streamXML(SlingHttpServletResponse response, String url) throws Exception{
        response.setContentType("application/xml");

        writeContent(response, url);
    }

    private void writeContent(SlingHttpServletResponse response, String url) throws Exception{
        byte[] image = Request.Get(url).execute().returnContent().asBytes();

        InputStream in = new ByteArrayInputStream(image);

        OutputStream out = response.getOutputStream();

        IOUtils.copy(in, out);

        out.close();

        in.close();
    }
}

3) For downloading scene7 renditions (smart crops or video encodes) with the file name and mime type...

    private void downloadImage(SlingHttpServletResponse response, String url) throws Exception{
        String fileName = url.substring(url.lastIndexOf("/") + 1);
        fileName = fileName.replaceAll(":", "-");

        HttpGet get = new HttpGet(url);
        CloseableHttpResponse s7Response = httpClient.execute(get);

        String contentType = ContentType.get(s7Response.getEntity()).getMimeType();
        fileName = fileName + "." + mimeTypeService.getExtension(contentType);

        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition","attachment; filename=" + fileName);

        InputStream in = s7Response.getEntity().getContent();

        OutputStream out = response.getOutputStream();

        IOUtils.copy(in, out);

        out.close();

        in.close();
    }

No comments:

Post a Comment