0

Is it possible to serve the REST API and the static content from different ports with Spring Boot? This becomes of interest when using CORS. Means, a plugged in nginx would route requests to api.example.com to one port and requests to static.example.com to another port. Example:

GET :8080/index.html should serve src/main/resources/static/index.html
GET :8090/customers/1 should serve content provided by a (e.g.) CustomerController

Requests with swapped port numbers (so 8080 for REST API, 8090 for static content) should not work.

Level 1 answer: How to accomplish this with an Embedded Tomcat?
Level 2 answer: How to accomplish this with a Managed Tomcat in which the Spring Boot Application runs?

Not a solution, because this is obvious: "Split it into two applications".

jonas
  • 145
  • 6
  • maybe this helps https://stackoverflow.com/questions/36357135/configure-spring-boot-with-two-ports – jmhostalet Oct 18 '17 at 14:52
  • If the content is truly static and you're fronting your service with a web server (nginx) then why don't you deploy your static content to the web server? – Andy Brown Oct 18 '17 at 15:45
  • @jmhostalet Unfortunately not, because this answer is not getting far enough. I know how to enable a second port. However the original question is how to serve different content on the two ports. Thanks anyway! – jonas Oct 18 '17 at 15:50
  • @AndyBrown Thanks for the hint, however this is not an option because nginx serves as a gateway for several applications. – jonas Oct 18 '17 at 15:51
  • It'd probably be easier if internally your rest calls would be hiding behind a subpath such as /rest, then you can configure nginx to route everything on 8080 to /static/bla and everything on 8090 to /rest/bla. If people switch around the ports it should automatically not work because the content won't exist under the re-routed subpath. – Gimby Oct 18 '17 at 15:58
  • @Gimby That's an option, yes. However when configuring this in nginx there is the danger of configuration mistakes that will expose endpoints or content where it isn't supposed to be. – jonas Oct 18 '17 at 16:26
  • @jonas that's not an argument, it can be automatically tested that the configuration is wrong. If this is a risk for you, apparently you do not have a proper monitoring environment yet. – Gimby Oct 19 '17 at 06:51

2 Answers2

0

Not sure how to do this with Spring but you could use Camel which is integrated in Spring. I should say though this just feels like it's a bad idea. Would be better to have a different server for serving static content and create a proxy(s) as you need. But anyway all you need to do is create a camel route and then either redirect that back to Spring world or simply serve your content from camel. You can bind camel routes to a different port. Someone pretty much asked the same question here: How to run @RestController on a different port? and someone else suggested Spring Actutator could be an option as well.

Derrops
  • 5,723
  • 4
  • 21
  • 43
0

"How to accomplish this with an Embedded Tomcat?"

It might be possible, but not recommended. That will cause you too much stress to be worth it.

Instead, use a prefix of "/api/v1/" and place all of your restful endpoints behind that path.

The "/api" path can then be specifically managed by spring security (allowing CORS etc).

The "v1" path allows you to version your api for your customers, or for cases where you may have date dependent business logic.

"How to accomplish this with a Managed Tomcat in which the Spring Boot Application runs?"

I get why you would do this; I have had "people"(?) ask me to do weird things like like too/

I recommend the same "/api"approach for restful endpoints in this scenario as well, but block all requests to Tomcat for static content. Spring Security can be configured such that only restful endpoints under "api" can be requested through tomcat,and block any request to Tomcat for static content.

Configure Nginx to be on that same server as tomcat and set the NgineX docbase to where ever the static content will be after the war is expanded.

Do NOT make that directory anywhere inside of "META-INF" nor "WEB-INF"; files in those directories should only ever be served by Tomcat,and do anything else would not be secure.

Also, do not use Nginx to redirect to Tomcat so that Tomcat is serving the static content to Nginx who passes it to the client. IF Tomcat is going to do anything other than just extract the content from the war, then having Nginx is superfluous.

The end result is that Nginx is running on a different port and it appears as if you have two apps, but not really.

It's not as good as just keeping your angular app separate, but you know ... "people".

If you are going to use tomcat for serving static content from a war file, then do not put it under "src/main/resources/static/". The static directory is good for jar deployments, but it is troublesome when deploying content from a war. Instead, have it under "src/main/webapp/". You would need to make sure Spring Security allows it still, but standard tomcat allows all requests for content that is not under "META-INF" or "WEB-INF".

And if all of that is still not the way you have to do things, then you could define a seperate host and connector in tomcats "server.xml", and define the two different contexts with their own "docbase" in context.xml.

Context docs: https://tomcat.apache.org/tomcat-8.5-doc/config/context.html

Host docs: https://tomcat.apache.org/tomcat-8.5-doc/config/host.html

Pytry
  • 4,806
  • 2
  • 30
  • 52