RequestDispatcher.forward to a media file?
Asked Answered
E

1

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.

Emrich answered 22/10, 2013 at 22:15 Comment(6)
Exactly how do the headers differ, aside from mime type?Sialoid
@Leigh, I would have to inspect them. If I have enough time I'll have a look tomorrow.Emrich
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).Heterogenesis
@Heterogenesis 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.Emrich
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 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 itHeterogenesis
@Heterogenesis 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.Emrich
G
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();
}
Grandstand answered 30/10, 2013 at 16:31 Comment(12)
@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 mediaGrandstand
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.Emrich
You should never close() the OutputStream (or PrintWriter) of a HttpServletResponse. This is the container's responsibility (flush() is fine)Acro
@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?Grandstand
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.Acro
@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.Grandstand
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.Acro
Well, not so many answers. I guess there isin't any other solution that the one I crafted. Thanks for the idea anyway.Emrich
@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.Grandstand
@DigvijayYadav StackOverflow gave you the bounty automatically ;)Emrich
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.Grandstand
@DigvijayYadav Perhaps you misunderstood my current solution. I do not perform any redirect. I updated my related question's answer if you are interested. #19385723Emrich

© 2022 - 2024 — McMap. All rights reserved.