Web Service - Tomcat - Behind proxy - wsdl location - java

I have a Java webservice running on Tomcat in our internal environment. Let's say the wsdl is
http://actual:8080/app/temp?wsdl
To provide access to this webservice from outside the network, we created a proxy using Apache on another server and used ProxyPass to do something like
ProxyPass /app/temp http://actual:8080/app/temp
So externally when we access proxy/app/temp over http, it gets diverted to actual:8080/app/temp just fine. So no issues with that, and I can also access the wsdl.
But the WSDL has references to "actual" server for the "webservice location" on the port. This causes failure when an actual call is made to the webservice methods from a client.
Any ideas on how this can be fixed, please? Thanks.
Note: The client is generated using Metro. I found a way to force a different endpoint in the client using a code like below. But I am looking more for a pure proxy solution that we can do, instead of developers using our webservice having to touch their code.
((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://proxy/app/temp?wsdl");

You can use the ProxyPreserveHost directive. Quoting from the directive's section in the link:
When enabled, this option will pass the Host: line from the incoming
request to the proxied host, instead of the hostname specified in the
ProxyPass line
therefore you should have the following in your configuration file:
ProxyPreserveHost On
ProxyPass /app/temp http://actual:8080/app/temp
and then restart apache server.
using this option, you will not need to change anything in web service related code or setup.

Related

Can I get Jetty to rewrite Cookie paths?

We've got a lot of applications based on Jetty. For historical reasons; these have been sitting behind Apache servers. One of the duties of Apache has been rewrites, and we want to move to using just Jetty. But we are hitting some snags when it comes to porting it. Specifically Cookie path rewrites. Is it even possible in Jetty?
The original config for Apache looks like this:
ProxyPassMatch ^/${basePattern}/${market}/(${appContextName}/.*) http://127.0.0.1:8080/app/${symbol_dollar}1 retry=0
ProxyPassReverse / http://127.0.0.1:8080/
ProxyPassInterpolateEnv on
ProxyPassReverseCookiePath /appCookiePath /${basePattern}/${market}/${appContextName} interpolate
I've looked at the code for both Rule (from the rewrite API) as well as Jetty Handlers. I can't really find anything in those APIs that would let me rewrite the Cookies... Any pointers?
There is no built in feature of Jetty for rewriting Set-Cookie headers or Cookie headers.
If you are not afraid of Java code, you could create a CookiePathHandler that is placed at the start of the Server handler list to perform this logic for you in java code.
Pop into jetty-users mailing list or #jetty on chat.freenode.net for help (if you've never written a Jetty handler before)

tomcat port URL restriction

I am trying to configure tomcat so that my application will be accessible via two different ports, say 8080 and 8980, but certain URLs will be accessible via only 8980.
The reason is that the web tier uses 8080 and I don't want certain URLs to be exposed to the outside world. I also don't want to configure web servers to restrict this, because of the coupling it creates between the app and the web tier.
I understand that I can configure two connectors and then programmatically block calls to the URLs based on the port, but:
I would rather not hard-code the port, as it may be changed in
the future in the server.xml
I want this same behaviour in various
applications in the organization, and don't want all developers to
need to implement this separately.
Is there a configuration where I can, perhaps, exclude certain URL patterns from a connector that is defined in server.xml?
Thanks in advance!
In tomcat, you can define multiple services with different connector ports and engine settings, but an application will only be served by one engine, so you'd have to deploy your application multiple times.
For use cases like yours, tomcat is too limited, but this functionality is usually deferred to a Reverse proxy, e.g. apache or nginx.
You could for example let your tomcat serve on port 8980, and configure an apache to reverse proxy all /app calls on port 8080, except the internals:
Listen 8080
<VirtualHost *:8080>
ProxyPass /app/internal !
ProxyPass /app http://localhost:8980/app
</VirtualHost>
See http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass

Determine user-facing url in a Java application behind a reverse proxy

I have this complex Java application which is hosted behind a reverse-proxy.
What is the best practice to determine your user-facing url at the java application level when calling request.getServerName(), request.getServerPort() and friends ?
We are using Tomcat (but we might switch to an embedded jetty) behind an Apache mod_proxy (but we'll definitely switch to Amazon Elastic Load Balancer).
I have listed 4 solutions:
Use apache mod_proxy to rewrite the 303 redirects. This is part of our current solution but is ruled out because not available with Elastic Load Balancer
Let the application server read the Host HTTP header of the request
Hardcode the application location at the application server level (example config in Tomcat)
Stop using the standard ServletRequest API. Instead have the full qualified name of the server in a config file and read this config from our code.
Our current solution :
redirects are rewritten by mod_proxy (first approach)
some other parts of the application use a path that we set in a config file (last approach)
I definitely need to stop using approach 1 and I would like to settle on one of the other three propositions.
EDIT:
This can be summarized as :
Can I trust request.getServerName() ?
Is so, can I trust the Host HTTP header ?
you can trust the HOST header passed on by the mod_proxy on Tomcat if you configure tomcat to preserver the HOST from the request i.e. using Directive:
ProxyPreserveHost On

Handling X-FORWARDED-PROTO header in Java web application

Can any one guide me in working with X-FORWARDED-PROTO header in Java web application deployed to Apache Tomcat.
The application setup is in such a way that tomcat talks with Apache webserver, which in turn talks with Cisco Load Balancer, finally the balancer publishes the pages to the client (tomcat -> apache2 -> load balancer -> client).
The SSL Certificate is installed in Load Balancer and it's handling HTTPS requests. My requirement is to make the application behave in such a way that it uses the X-FORWARDED-PROTO and change the pages as HTTP or HTTPS.
Checking on the header files of my webpages I could not find the X-FORWARDED-PROTO header. I don't have access to the Load Balancer configuration either, and the IT has suggested us to use the X-FORWARDED-PROTO to differentiate between HTTP and HTTPS request.
Is there any configuration to be done in Tomcat or Apache level so that it will return the X-FORWARDED-PROTO header? Or is it that the configuration should be handled in Load Balancer?
I am pretty sure you have it all figured out by now but I will add the answer nonetheless.
You can use the class org.apache.catalina.valves.RemoteIpValve in the engine tag in conf/server.xml of tomcat.
<Valve className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="192.168.1.XXX"
remoteIpHeader="x-forwarded-for"
remoteIpProxiesHeader="x-forwarded-by"
protocolHeader="x-forwarded-proto"
/>
Something to note that is very important is to set the internalProxies value. If this is not set and you are you using a non-standard network setup it could cause some issues where tomcat will not check for x-forwarded headers and it will default to "http". For security reasons I'd recommend to set it even if it works with the defaults.
Look here for more information.
Add this to your apache vhost managing connections
<VirtualHost *:80>
...
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule !/status https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
</VirtualHost>
this assumes your health check is /status, which doesn’t require https

Test large number of webservices on a single computer

We have a large system of physical devices which all run a web service for control and a central control system for controlling these devices. I need to make a substitute for such a physical device in order to test the controlling unit. How will I go about running more than one instance of a test device on a single computer. The protocol used in SOAP with a wsdl written in stone. In addition to the webservice each test device needs a webserver to monitor state and generating events.
My first approach is to embed jetty and use axis2 for webservices, but I am having some trouble making that fly. I managed to get the axis2 SimpleHttpServer working with a webservice, but as far as I can tell SimpleHttpServer will not let me run Servlets or let alone wars. Is there a better approach I am missing?
I considered making a proxy server listening on any number of ports and forwarding the request to a webservice to a central webservice with an additional paramater saying which port the request originated from, but since the wsdl is writting in stone I can not pass this paramater along.
EDIT: I am using Netbeans to generate a webservice for me. Works as a charm but not enough for my project. For some reason wsimport chokes on the wsdl. I don't understand how Netbeans can deploy to the bundled Glassfish server, but if I drop the generated dist/my-project.war into tomcat the webservice doesn't work. Much less show up in web.xml. What am I missing?
Be aware that if you route your network requests through a SOCKS proxy, you can essentially redirect even hardcoded names and ports in the SOCKS proxy to whatever you need.
Axis2 is not meant to be used as a servlet container, so using SimpleHttpServer doesn't help you there.
But Jetty is a full featured Servlet container. If you want to make it work, you have to run your Wars with Jetty. (Or any other servlet container, but Jetty is perfectly fine)
I'm not Jetty expert, but this should work:
Server server = new Server(8080);
Context root = new Context(server, "/", Context.SESSIONS);
root.addServlet(new ServletHolder( yourServletInstance ), "/*");
server.start();
(Taken from Jetty Wiki)
Ok I've figured out a solution. I can use Glassfish. Then I deploy the same webapp multiple times under different names. Then I have a small proxy made in glassfish which listens on a number of ports and then translates the request to one of the instances running i glassfish.

Categories

Resources