10

I have a Web Application that users deploy on their own Java Web Servers (e.g. Tomcat). The Java side of Web Application needs to report the URL of the Web Application itself (e.g. http://aServer.com:8080/MyApp or https://blah.blahSever/MyApp). However since a number of users use port-forwarding and other network techniques, the Web Application often reports the wrong name.

I have tried the following techniques but often they don't actually produce what the user requires.

Note (request is an HttpServletRequest)

request.getLocalAddr();    // Returns: 127.0.0.1
request.getLocalName();    // Returns: localhost
request.getServerName();   // Returns: localhost
request.getServerPort();   // Returns: 8080
request.getContextPath();  // Returns: /MyApp

request.getScheme();       // Returns: http

InetAddress.getLocalHost().getHostName();           // Returns: serverXXX-XXX-XXX-XX.xxxx-xxxxxxx.net
InetAddress.getLocalHost().getHostAddress();        // Returns: xxx.xxx.xxx.xxx (ip address)
InetAddress.getLocalHost().getCanonicalHostName();  // Returns: serverXXX-XXX-XXX-XX.xxxx-xxxxxxx.net

The use of InetAddress gets close to what I want but since we are using Server Aliases and ProxyPass in our Apache2 server, the value from InetAddress is the actual values of the server rather than the Alias.

The only technique I can think of to get round this, is that the user provides a property in a properties file, which the Web Application reads on startup. If the property is set, this value is used to return the full web application path (e.g. serverUrl = https://blah.blahServer/MyApp) . This technique would work, but involves more deployment work for my customers.

Does anyone have any ideas as to how I can achieve a more elegant solution?

Thanks, Phil

5
  • 1
    Put the address in a system property and use that. If you put it on a different server, modify the property. Make the app refuse startup if the property isn't set. Commented Jan 31, 2014 at 14:11
  • Have you tried request.getRequestURL()? Commented Jan 31, 2014 at 14:15
  • @Mustafa Genc - Unfortunately getRequestUrl simply returns: localhost:8080/MyApp - which is nice and complete (it includes http and the port and the Web App name), but unfortunately returns "localhost" ! Commented Jan 31, 2014 at 15:18
  • @Kayaman - I think that your approach may be the one I go for! Commented Jan 31, 2014 at 15:21
  • @Phil It's definitely the easiest (and works well, unless you often switch domain names) approach. Commented Jan 31, 2014 at 16:01

3 Answers 3

7

Check the 'host' request header. Most client add that header to indicate the host they're trying to contact.

This is the same header that's used for VirtualHosts, so it's pretty standard. It's also obligatory in HTTP1.1 requests.

In fact, you cannot get the value purely from the server side, since it's possible that the user has defined its own hostname for your server.

request.getHeader("Host")

If your server is behind an apache reserve proxy, use the ProxyPreserveHost directive to make sure the Host header is kept intact. I'm sure other reverse proxies have similar options.

Sign up to request clarification or add additional context in comments.

6 Comments

I tried getHeader("Host") and it simply returns "localhost:8080". I really want a solution that doesn't involve informing the customers that they have to modify their Apache, proxies, whatever. I think what I am asking for (in terms of Pure Java) is actually impossible.
If the client doesnt send you the hostname it used to contact you, there is no way for you to know it, since it can differ per client. Of course if you want to define a canonical name then it's different en you should just use some configuration property (lots of apps do it this way). As for the localhost, check with Firebug (or similar) which header was sent in the request. If it's really localhost, that means somehow your browser switched your hostname with localhost, or of course, you really used 'localhost' in the url :)
The host request header is unsafe to use, as it can be altered by anyone
@deiga Any header can be altered by anyone in the chain -- still, as there is no such thing as a single name for a host, the closest thing to a reliable source on what the client used as a hostname to contact you, is the client itself. You'll just have to take the risk.
@Wrinn Well sure, but that assumes you 'need' a specific value (as you say yourself). I suppose in the large majority of the cases (i.e. on the internet) you have a canonical hostname and you prefer to answer that - but for the general case you cannot know how the client resolved your name without asking it (which dns did it use, or was it a private hostfile?). Also if you're going to distrust the host header, you can throw any sort of vhost config (which is fairly common) out the window...
|
4

This solved the issue for me:

InetAddress.getLocalHost().getHostName();

Comments

0

i think your problem is not the java api to access the values you need.

In tomcat for example there is a server.xml file containing a pair of lines like

<Engine name="Catalina" defaultHost="**localhost**">

<Host name="**localhost**"  appBase="webapps"  ...

if you replace localhost with the name you want like "myhost.com" and the host where tomcat runs knows its own host name, then when you retrieve the url with the specified hostname , it will show the name you ask for

Regards

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.