views:

736

answers:

2

I am looking into a solution that would allow to load an external URL content into an <iframe> element in a JSP page. However, before displaying any content, JSP code would first check for HTTP response of included in iframe's src URL and if 200/OK returned then display it otherwise a custom message or another page is displayed instead. I'd like to do it on the server side only.

Is there a way of achieving it without AJAX / user side scripting that could have potential cross-browser incompatibilities?

+1  A: 

You can make use of JSTL (just drop jstl-1.2.jar in /WEB-INF/lib) c:import tag to import an external resource, which will throw FileNotFoundException if the URL is invalid, which in turn can be catched using JSTL c:catch tag. You can finally use JSTL c:choose to check whether to display the iframe or the eventual error.

Here's an SSCCE, copy'n'paste'n'run it (with JSTL installed):

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 2291085</title>
    </head>
    <body>
        <c:set var="url" value="http://google.com" />
        <c:catch var="e">
            <c:import url="${url}" varReader="ignore" />
        </c:catch>
        <c:choose>
            <c:when test="${empty e}">
                <iframe src="${url}"></iframe>
            </c:when>
            <c:otherwise>
                <p>Error! ${e}</p>
            </c:otherwise>
        </c:choose>
    </body>
</html>

Change http://google.com to http://google.com/foo or something invalid, you'll see that the error shows instead.

Note that I used varReader="ignore" to have it buffered but unread, so that it won't entirely hauled in which may be expensive because after all you're requesting the same URL twice.

Update: Alternatively, you can use a Servlet for this which preprocesses the request inside doGet() method with help of java.net.URLConnection. Here's a kickoff example.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    URL url = new URL("http://google.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    int status = connection.getResponseCode(); // 200 = OK, 404 = Not Found, etc.

    if (status == 200) {
        request.setAttribute("url", url);
    } else {
        // Do your thing to set custom message or request another page.
    }

    request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);
}

...and in page.jsp then just have something like

<c:if test="${not empty url}">
    <iframe src="${url}"></iframe>
</c:if>

Map the servlet on an url-pattern of something like /foo and call it on http:/example.com/contexty/foo instead of the JSP.

BalusC
A: 

The actual loading of the <iframe> is going to take place because the client loads it. There have simply got to be better ways of validating the URL than by trying to include it via JSP. Do it in Java, or just don't do it at all: have the server return a "not found" page that runs some Javascript to hide the iframe. (Have it show an error for people browsing with Javascript turned off.)

Pointy