aspose file tools*
The moose likes Servlets and the fly likes Tomcat servlet-mapping bypass if real file requested Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Servlets
Bookmark "Tomcat servlet-mapping bypass if real file requested" Watch "Tomcat servlet-mapping bypass if real file requested" New topic
Author

Tomcat servlet-mapping bypass if real file requested

Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Is this possible at all? I know I can use a prefix or a suffix to be specific about the URI, but say I wanted to pass *all* requests via one particular servlet (front controller), except those which are directed a real file, can I do that?



It's even crossed my mind to have the servlet look if the file exists and then stream it back if it does, but dealing with mime types doesn't stike me as a fun task, and the overhead of doing this seems a bit silly really.

Even this would be a suitable solution for me if it were possible:



Where "void" means "don't use a servlet".

I'm basically looking to produce a clean URL mapper where the URL is parsed at runtime to determine what request parameters are in it (without the ?foo=bar mess).

Like this: http://www.symfony-project.com/book/trunk/09-Links-and-the-Routing-System

I guess if I were to check the URL at the first instance in the front controller I could minimize the overhead, and I can steal apache's mime-type list.
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

It's usually easier to do things the other way around and set up specific mappings when you DO want to go to a servlet.

This usually done with a prefix that looks like a directory
/command/* or with a specific file extension like *.do.

Then you don't need specific mappings for css, js, jpg, gif, pdf, and whatever else you might need to access from the client.


Java API J2EE API Servlet Spec JSP Spec How to ask a question... Simple Servlet Examples jsonf
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Yep, I do acknowledge that I'm experimenting as much as anything else really.

I got this to work pretty quickly. The first thing that happens in my front controller is the URI gets examined to see which action controller to dispatch. It's here that I do a simple check for a resource and stream it back as early as possible if something really does exist.



The CloseServletException is a bit of a hack really, but it gets my front controller to jump to the end of processing and just return.

Tested downloading a 684MB file (adobe photoshop dmg image), displaying images and using CSS. All works nice and fast

My inexperience probably shows in my coding though.

This probably all looks a bit pointless to you right now but there is method in my logic for doing this... somewhere
ramprasad madathil
Ranch Hand

Joined: Jan 24, 2005
Posts: 489

You could also fo it this way

Map all requests to your front controller servlet.
Place a Filter before your Servlet.

In the filter's doFilter() method, examine the request (the same logic as in your Front Controller from your last post). If the request is for a file, have the Filter serve the response back and don't pass on the request to the Servlet. Else do nothing, just pass it straight through.



You achieve 2 things this way.

1. The Servlet is still mapped to all requests.
2. The logic check is refactored away from the Servlet.

Just a suggestion.

cheers,
ram.
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Thanks for the tip. I didn't know you could do that. Refactoring now

I'm hoping this will fix a big i've found in using my code with safari. Image/CSS etc are not understood in safri, unless you go directly to them in the browser. I can only conclude that Safari sends some other requests that aren't for files bceause:

This fails (unless you point your browser directly to the image, and dont <img src /> to it):



But this works (which I though would have the same effect):



The second one still pushes everything I *thought* was in the request through the servlet, but clearly I was wrong because Safari gives a broken image if you link to it via <img>, yet it works if you copy the <img src=??? > into the address bar. Confusing.

I'll lt you know if your method solves that I'll add some ETag and Last-Modified checks too which would speed things up further.
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
FYI, your suggestion worked a peach It fixed my wierd bug and it feels like it's being done in the proper place now. I've also moved my request routing/mapping logic into a filter.

The file check:


The request mapping is this:


Which builds a request router using a series of strategies checking how well they can interpret the URI and offering a "score". Config looks like this (suffixes and prefixes non-important).



The idea is that you can comletely configure the URL schema based on this XML file and you'll never need to use ?foo=bar style queries in the URL (like the symfony link I posted earlier).
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

Safari (or any other browser for that matter) has no way of knowing what content on the server is static and what is dynamic. It just makes an HTTP request and receives an HTTP response.
[ August 19, 2007: Message edited by: Ben Souther ]
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Understood I'm not 100% what the problem was really with my first version, I just know that moving the code back a layer has helped, unless I inadvertently changed some logic along the way. I studied the headers that were being sent for a real file, and those for my streamed files and the only difference was ETag and Last-Modified.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Tomcat servlet-mapping bypass if real file requested