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
Related
The scenario is this: I'm developing a Java EE application with an Angular 2 frontend. The client has an Apache server which is usually used to serve static resources and an Oracle Weblogic for the dynamic part. The problem is that by default the Angular 2 App and the Weblogic server will not be able to talk each other due to the Same Origin Policy.
So far I have 3 possible deployment approaches in mind:
Set up a Reverse Proxy in Apache to point the REST endpoints to Weblogic
Package the Angular App in a WAR/EAR and deploy it to Weblogic. So I would end up with something like: myserver/myapp for the UI and myserver/myapp-rest for the Backend.
Package the Angular App in the same WAR as the Java backend. So I would end up with myserver/myapp for the UI and myserver/myapp/api for the REST endpoints.
There is a 4th option which would be setting up CORS, but I'm worried about the security using that approach.
Which is the right approach?
If you are allowed to make infra decisions , change apache webserver to nginx , we switched to nginx and got lot of added values in terms of concurrent processing.
In our project the angular client is served by nginx webserver which talks to java backend hosted on tomcat 8.x(our app server) , also there are couple of tiers after app-server a separate DB server and an elastic search server.
Don't feel intimidated to set up CORS, you will eventually need to allow some origins requests which don't originate on your domain and port.
If your java tech stack has spring mvc , then setting up CORS is just a matter of adding few lines of configuration. You can even hardcode your angular url to allow backend server to serve requests only from your angular URL.
In normal JavaEE world, CORS is just another filter or interceptor where you can set response headers with all the allowed origins, http methods etc. It's very simple you can look it up.
For your given choices
seems plausible and a value addition that you get is you can
delegate SSL encryption to proxy server .
seems rather odd, you would want to separate the static content server from dynamic contents server, your angular js bundles, assets
etc are mostly static, if you keep your static server separate then
you can configure cookie-less domains down the line that would make
serving a lot faster.
3 same as 2.
I would strongly suggest the CORS option , from my past experiences.
I have learned in another question how can I detect if I am running on development or a production server. Is there some way how to get programmatically following:
protocol used (http / https)
port used (8080 / 80)
server domain (xxx.appspot.com on production)
I can special case them for a development / production, but it smells to me - getting those values from a server would seem nicer to me. Is there a way?
I need those values so that I can construct redirectUri for OAuth authentication.
It depends on the web framework you're using. If you're using webapp2, you can get it from the request attribute
https://webapp-improved.appspot.com/guide/request.html#common-request-attributes
For java servlet, http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html
I am working with a Java web application and I would like to have a reverse proxy masking some of my internal endpoints.
Requirements:
The reverse proxy maps need to be modifiable at runtime e.g if we move some components to another server we should be able to modify the mapping such that new requests are routed to this endpoint.
This must be embeddable to a standard servlet container like Jetty.
Most of the Java Reverse Proxies out there such as J2EP require mapping information available prior to starting the application.
Undertow provides an embeddable reverse proxy server that can be changed programatically at runtime.
If you want to operate at a higher level via an API then there is Backflow. It supports adding/removing proxy backends using REST calls.
As far as I can see, http://www.membrane-soa.org/service-proxy/ supports all your requirement:
Membrane has a WebUI where you can add and remove proxy connections at runtime, e.g. forward incoming request on port 80 for a virtual host to a target host:port
Membrane can be run as standalone application or deployed in an application server.
Membrane is an Open Source project under the ASF 2.0 License
I developed an Java application who request in SPARQL on Sesame repositories.
I use currently a Tomcat server what I run on console (with ./startup.sh).
I must now include my application into a web page and I choose J2EE.
But I have a problem : I can't run a Sesame connection and use JSP files, servlets,...together.
I have this error :
Etat HTTP 404 : The requested resource is not available
How to "join" us ? Is it a conflict because of the "8080" port ?
You have not provided enough information about how you have configured your Tomcat to allow a meaningful diagnosis.
But I can say with certainty that it is possible to run Sesame repositories and JSPs on the same Tomcat service ... if you configure them correctly. Indeed it is possible that you are already doing this, but you are using the wrong URL to access the resource.
How to "join" us ?
I suggest that you start by looking at the Tomcat documentation on how to configure the server, and how to build a basic webapp.
Is it a conflict because of the "8080" port ?
That is unlikely.
I have an Apache tapestry application which is running under Jetty server. As such port number of the running HTTP server can be obtained during a request from the request object. But I need to find out the port number at which the server is running during program start up (somewhere in AppModule). Is there some way to get this information programmatically? I tried to access #Symbol(SymbolConstants.HOSTPORT) String hostPort in a service but this doesn't work. It simply gives 0. Apparently 0 means that I should be looking up the port number from request.
The reason I need it is because I need to write this information in some database which is accessible to other services such that they are aware of the port / ip address at which this application is running and can call it up.
I'm pretty certain you cannot programmatically determine the servlet container's port from anything in the javax.servlet package, except for ServletRequest ie getLocalPort().
Tapestry does not provide any extra handles to your application container not already in the servlet spec.
Therefore you will need to wait for the first request to come in and store the port used (recommended), or duplicate your port configuration - once in your container's configuration (jetty) and once somewhere in your application (AppModule, web.xml or other configuration files).
The third option (which is highly NOT recommended) would be to lookup your container's configuration from within your tapestry application. Please don't do this.