3

I recently had an issue to resolve and found a solution, but that solution could potentially be greatly simplified if I could somehow use RequestDispatcher.forward to forward a request to a media URL.

From the docs, it says that it only supports servlet, JSP file, or HTML file. I tried with a media URL anyway and it did not complain, however it's not returning the correct headers (e.g. mime type) and perhaps there or other faulty things but anyway it did not worked as expected.

Is there a way I could use RequestDispatcher.forward with a media URL so that the response is served exactly as if the media URL was requested to the web server directly?

EDIT:

I can attest that at least the Content-Type is correct, since it's returning Content-Type text/html; charset=iso-8859-1 for any media file. Also, I have tried opening the url directly in Window Media Player and it seems to be downloading the entire video before starting to play, which is unacceptable. Therefore I can safely assume that forward doesn't just hand back the control to IIS or at least does it incorrectly for media files.

Community
  • 1
  • 1
plalx
  • 42,889
  • 6
  • 74
  • 90
  • 1
    Exactly how do the headers differ, aside from mime type? – Leigh Oct 30 '13 at 22:00
  • @Leigh, I would have to inspect them. If I have enough time I'll have a look tomorrow. – plalx Oct 31 '13 at 00:51
  • Perhaps you could go about this whole thing a different way. Is your initial issue here being able to control who can access these video files and when they can access these video files? IIS can handle the serving of these files for you correctly but you cannot set the required restrictions using only IIS. Right? Are there any other appliances/software sitting between your users and the web site that you could utilize? A load balancer, proxy server, etc. that might be able to restrict traffic during certain times. The user restriction part could be handled by IIS (assuming active directory). – Miguel-F Nov 01 '13 at 14:06
  • @Miguel-F There's nothing else under my control unfortunately and it has to be done through ColdFusion since users go online to *rent* the listening rights on videos for a specific period of time, so I must enforce the restrictions using application-specific logic. The only other solution I thought of would be to dynamically change NTFS rights on the files, but I really dislike this solution. I'm surprised there's no built-in mechanism to just delegate a request. The solution I crafted works, but it has it's drawbacks, like having to use Anonymous authentication. – plalx Nov 01 '13 at 14:17
  • Thanks for the clarification. I will have to think about this some more. Did you see this post from Ben Nadel? [Streaming Secure Files Efficiently With ColdFusion And MOD XSendFile](http://www.bennadel.com/blog/2170-Streaming-Secure-Files-Efficiently-With-ColdFusion-And-MOD-XSendFile.htm) Although it deals with the Apache module XSendFile he also mentions that _there are ways that you can run Apache configurations in IIS (ex. Helicon Ape)_. If you haven't seen that article you might want to check it out. He always has great detailed information. **I just saw that you already commented on it** – Miguel-F Nov 01 '13 at 15:06
  • @Miguel-F Yeah that would have been great and that's very unfortunate that I cannot install any plugins/modules/extensions that aren't approved. I guess I could potentially start looking at how this could be solved by using a similar approach writing an IIS module myself. – plalx Nov 01 '13 at 15:46

1 Answers1

2

The solution you found points to the right direction, but I have no knowledge of coldfusion, but with servlets the same thing can be done very easily.

If you want to use RequestDispatcher.forward method then you can specify a servlet url in the forward method. And in that servlet all you need to do is read the media and send it using OutputStream as the response.

For example:

In your servlets doGet or doPost method you just need to set the content type according to your media, read it and send it.

Below is a simple example you can use to send the media as response from the servlet:

public void doGet(HttpServletRequest request, HttpServletResponse response)  {
    response.setContentType("video/x-ms-wmx");
    ServletContext ctx = getServletContext();

    InputStream is = ctx.getResourceAsStream("/path/to/media/file");

    int read = 0;
    byte bytes[] = new byte[1024];

    OutputStream os = response.getOutputStream();
    while((read = is.read(bytes)) != -1) {
        os.write(bytes, 0, read);
    }
    os.flush();
    os.close();
}
me_digvijay
  • 5,374
  • 9
  • 46
  • 83
  • @plalx: I think it should not matter where the request is coming from. I don't think headers will change during this and even if they do then they will be changed according to the content of the response Also the Window Media Player should be able to handle the response for the media – me_digvijay Oct 31 '13 at 04:42
  • I have tested and the request headers will not change, that's fine however the response headers aren't the same as if IIS directly served the request and that's a major issue. I basically want to hand back the control to IIS or whatever my Web Server is, without redirecting the browser. – plalx Oct 31 '13 at 18:00
  • You should *never* close() the OutputStream (or PrintWriter) of a HttpServletResponse. This is the container's responsibility (flush() is fine) – lance-java Nov 06 '13 at 10:13
  • @uklance: Why `never`, I think it should be ok to close it if the response is 100% complete and that after `os.close` nowhere the `os` or response is used? – me_digvijay Nov 06 '13 at 17:02
  • No, the servlet container (eg tomcat/jetty) is responsible for creating and closing the response OutputStream or Writer. If you ```close()``` it, the container may throw exception when it attempts to ```close()``` a stream/writer which is already closed. – lance-java Nov 06 '13 at 17:05
  • @uklance: Right but this `outputstream` is explicitly created by me not by the container. So isn't it my responsibility to close it. If hadn't opened it, then it makes more sense to me to leave it like that. – me_digvijay Nov 06 '13 at 17:09
  • No, it was created by the container. You only did a ```get``` for it. Try wrapping the response using a filter in an implementation that logs when ```close()``` is called. In your code, you will see 2 log statements. – lance-java Nov 06 '13 at 17:13
  • Well, not so many answers. I guess there isin't any other solution that the one I crafted. Thanks for the idea anyway. – plalx Nov 07 '13 at 15:59
  • @plalx: I am not sure if Bounties are meant for questions without any accepted answers, and you haven't found any proper solution for your problem. – me_digvijay Nov 07 '13 at 16:40
  • @DigvijayYadav StackOverflow gave you the bounty automatically ;) – plalx Nov 07 '13 at 16:52
  • I just wanted to let you know that the servlets `requestDispatcher.forward` method sends the request to some other resource behind the scenes i.e., the browser does not know who serverd . The `sendRedirect` method is for telling the browser to make another request to some other url (redirecting). As you have specified in your second comment you are having the `redirect` issue with this method. – me_digvijay Nov 07 '13 at 16:58
  • @DigvijayYadav Perhaps you misunderstood my current solution. I do not perform any redirect. I updated my related question's answer if you are interested. http://stackoverflow.com/questions/19385223/how-to-transparently-stream-a-file-to-the-browser – plalx Nov 07 '13 at 20:30