On 8/25/2012 5:01 AM, Konstantin Kolinko wrote:
2012/8/25 Mark Eggers <its_toas...@yahoo.com>:
On 8/24/2012 2:55 PM, Konstantin Kolinko wrote:
2012/8/25 Mark Eggers <its_toas...@yahoo.com>:
(...)
An application makes use of a PDF library which generates PDFs from JSP
pages. One of these pages includes a dynamically generated graph.
This library cannot use streaming data to include the graph.
(...)
============
3. What is your hairpinning problem?
Hairpinning is when a system is sitting behind a NAT, and it attempts to
send itself a packet to the public IP address.
+----------------<
| NAT <----------------> Server
+---------------->
public IP private IP
ww.xx.yy.zz aa.bb.cc.dd
In this environment it occurs with a host name. The server sends a packet to
itself using the publicly accessible name, which resolves to the external IP
address (ww.xx.yy.zz), which then gets sent right back to the server.
Unless you specifically configure a NAT device to allow this, the packet
will be dropped.
Is it because you use "a fully qualified URL point to a servlet" and
you cannot build that URL correctly?
Do you really need an absolute URL? You mean that you cannot call your
servlet otherwise?
This is correct. The library in use will only take relative URLs, or fully
qualified URLs (including protocol, port, and host name).
Relative URLs means I write back into the web application, which is where
getRealPath() comes into play.
I cannot use absolute URLs (/context/servlet-name?imagename=foo). This gets
interpreted by the library as an absolute file name (and no, using
/java.io.tmpdir/foo does not work).
I would love to rewrite my URL to be
http://localhost:80/context/servlet-name?imagename=foo
That will only work if there are no virtual hosts in any front end proxy and
no additional hosts in server.xml.
I could write a separate application that serves the image files internally.
It would be quite simple to do, but it would potentially require server
modifications.
1. Listens to requests on a separate port (server.xml modification)
2. Application resides in the default host (for multi-host configs)
Then the path would look something like the following.
A. Request
Browser ------------> NAT ------------> Server
public IP private IP
ww.xx.yy.zz aa.bb.cc.dd
B. Image
+-----< Server
| ^
| | localhost - some arbitrary port
+---------+
C. Resulting PDF
Browser <------------ NAT <------------ Server
public IP private IP
ww.xx.yy.zz aa.bb.cc.dd
That PDF-generating library - where it sits? Is it on Server?
It sits in the application. It's actually two jar files - one that does
the PDF translation proper and the other is a tag library.
How does the library get its source data (an XSL-FO document?) that is
converted to PDF? Which of the following:
This I don't know, but I suspect not. The library is obfuscated, but
there doesn't appear to be the standard XSL-FO translation.
a) It uses HTTP to request a JSP page. Then it uses HTTP to request the image.
This is the way I think it operates when you use a tag library. Why the
library requires a relative URL or a fully qualified URL but does not
work with an absolute URL I do not know.
b) You prepare the data and feed it to the library programmatically
(e.g. as an InputStream). The library performs a request to get the
image.
It can work this way. The advantage of using a JSP (at least from the
programmer's standpoint) is that the library understands a lot of (but
not all) CSS. This means that if you're careful, what the user sees on
the page with a JSP will be how the PDF looks.
If it is a) you could use UrlRewriteFilter + forward to serve the
image from any arbitrary URL.
Hmm, I think I tried UrlRewriteFilter before, but maybe not in quite the
right way. You are thinking along the lines of rewriting
http://some-host:80/context/servlet?name=imagename
to
../servlet-location/servlet?name=imagename
and letting the servlet dig it out of java.io.tmpdir?
Ah, as I write this maybe there's another way. I wonder if the filter
has a way of getting the local (ie., private) IP address. Then the
rewrite could be:
http://internal-ip:80/context/servlet?name=imagename
I know that when the tester used the internal IP address, everything
worked as planned (the image appeared) and that it was using
java.io.tmpdir (per my logging info).
This actually tells me two things.
1. Such a rewrite has the chance of working
2. In the staging system they are either
a. Not using multiple hosts or
b. Deploying the war file in the default host
This will only work if either Tomcat is running on port 80, or any front
end server is on the same machine.
If Tomcat is connected via mod_jk to a front end machine, I'll have to
figure out how to get the front end IP address and rewrite appropriately.
There are lots of other permutations, but I'll not bore the list with those.
If it is b),
- How the library knows the base URL of the document, to resolve relative links?
- Could you use a "file:///" URL for the image?
- Does the library use some resolver before looking for the image
(e.g. javax.xml.stream.XMLResolver, org.xml.sax.EntityResolver),
so that you can intercept the lookup.
- In theory, it is possible to use custom URL schemes, like Tomcat's
internal jndi:// one.
Actually, I wish it was b). Managing this environment in a POJO would be
much nicer. I could possibly play games with memory-based files and
eliminate writing to disk (the images are small, not reused).
I could even work on convincing people to move away from this PDF
library (creates permgen leaks when images are included) to something a
bit more sane. Maybe even something that read stream data and didn't
cause a permgen memory leak . . . .
However, that's not going to happen in the time frame for this
deployment. The filter might solve the problem.
Best regards,
Konstantin Kolinko
Thanks again for your insite Konstantin . . .
. . . just my (now busy weekend) two cents.
/mde/
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org