1

I am trying to write an InputStream, which I get from an URL by the doGet method of Servlet. Here is my code:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String requestedUrl = request.getParameter("url");

    if (StringUtils.isNotBlank(requestedUrl)) {
        ReadableByteChannel inputChannel = null;
        WritableByteChannel outputChannel = null;

        try {
            URL url = new URL(requestedUrl);
            HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
            int responseCode = httpConnection.getResponseCode();

            System.out.println(responseCode);

            if (responseCode == HttpURLConnection.HTTP_OK) {
                response.setContentType("image/jpg");
                httpConnection.connect();
                InputStream imageStream = url.openStream();
                OutputStream outputStream = response.getOutputStream();

                inputChannel = Channels.newChannel(imageStream);
                outputChannel = Channels.newChannel(outputStream);
                ByteBuffer buffer = ByteBuffer.allocate(10240);

                while (inputChannel.read(buffer) != -1) {
                    buffer.flip();
                    outputChannel.write(buffer);
                    buffer.clear();
                }
            }
        } catch (Exception ex) {
            Log.error(this, ex.getMessage(), ex);
        } finally {
            if (ObjectUtils.notEqual(outputChannel, null)) {
                try {
                    outputChannel.close();
                } catch (IOException ignore) {
                }
            }

            if (ObjectUtils.notEqual(inputChannel, null)) {
                try {
                    inputChannel.close();
                } catch (IOException ignore) {
                }
            }
        }
    }
}

I can see in console that the responseCode is 200 but it is not writing anything in the page. In Firefox I am getting:

The image “the_context_root/dam/no-image-aware-servlet?url=http%3A//localhost%3A80/file/MHIS044662&Rendition=164FixedWidth&noSaveAs=1” cannot be displayed because it contains errors.

I am unable to find what I am doing wrong. Any pointer would be very helpful.

Tapas Bose
  • 28,796
  • 74
  • 215
  • 331
  • Can you use response code prior to httpConnection.connect()? – Taylor Nov 22 '13 at 15:57
  • @Taylor I am not sure I catch you. Did you mean to call `httpConnection.connect()` before httpConnection.getResponseCode();? – Tapas Bose Nov 22 '13 at 15:59
  • Yes. I'd be surprised if you had a response code before connecting. – Taylor Nov 22 '13 at 16:00
  • @TapasBose getResponseCode() only returns something useful if you do the httpConnection.connect() BEFORE. – isnot2bad Nov 22 '13 at 16:01
  • Did you set the correct content type for the response? – isnot2bad Nov 22 '13 at 16:02
  • The url you're using for your test has 'localhost' as domain. From the point of view of the server, this points to itself. So the image is somewhere on the server, isn't it? – isnot2bad Nov 22 '13 at 16:04
  • @Taylor I did. It is also returning 200. – Tapas Bose Nov 22 '13 at 16:08
  • @isnot2bad yes all the images are jpg. The images are not in my development server. It is in a content server. Which is running in a different place. I have Apache configured in such a manner that http://localhost:80/file/MHIS044662&Rendition=164FixedWidth&noSaveAs=1 would return the image I an seeking to. – Tapas Bose Nov 22 '13 at 16:10
  • @TapasBose The source for getResponseCode() shows it fetching an input stream if there's no cached response code which may muck up your connection. I'd really recommend moving your call to connect() to before the call to getResponseCode() – Taylor Nov 22 '13 at 16:24

1 Answers1

2

I've tried to modify your code a little bit to address the wrong order of getResponseCode() and connect() as well as some other minor issues.

Especially make sure to ALWAYS return an error status code (other than 2xx) if something goes wrong (e.g. file not found on other server, IOException, illegal URL, ...), otherwise the browser always gets 200 - OK but no data!

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String requestedUrl = request.getParameter("url");

    if (StringUtils.isBlank(requestedUrl)) {
        // TODO: send error code 400 - Bad Request
        return;
    }

    try {
        URL url = new URL(requestedUrl);
        HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
        response.setContentType("image/jpg");
        httpConnection.connect();

        int responseCode = httpConnection.getResponseCode();

        if (responseCode == HttpURLConnection.HTTP_OK) {
            // TODO: set correct content type to response

            OutputStream outputStream = response.getOutputStream();

            try (InputStream imageStream = url.openStream()) {
                IOUtils.copy(imageStream, outputStream );
            }
        } else {
            // TODO: send error code (depends on responseCode), probably 500
        }
    } catch (Exception ex) {
        Log.error(this, ex.getMessage(), ex);
        // TODO: send error code 400 if malformed url
        // TODO: send error code 404 if image not found (responseCode == 404)
        // TODO: send error code 500 else
    }
    // Don't close the response-OutputStream! You didn't open it either!
}
isnot2bad
  • 24,105
  • 2
  • 29
  • 50