0

In short this is what I'm searching for: I want to create a RequestMapping that catches all URLs except a small list I don't want to catch. The minimum to exclude is everything below /webjars/, I also would like to exclude other URLS like /actuator/ and probably more.

Background information

We need to replace an old CMS which has literally thousands of different URLs. All URLs need to be detected and checked against a database and then the users shall be presented with a landing page, this landing page will then redirect the user to the new CMS target URL. The logic that needs to be applied is too complicated for some Apache / nginx magic, therefore I wrote a Spring Boot application that can accomplish this.

I've created a @RequestMapping(value = "**", method = RequestMethod.GET) that catches all GET requests (these are the one I want to grab and react on) and a @RequestMapping(value = "**") for the other http verbs like POST and DELETE which I simply abort by sending a http error status code. This works fine and the (simplified) code looks like this:

@RequestMapping(value = "**", method = RequestMethod.GET)
public String catchAccepted(HttpServletRequest request, HttpServletResponse httpServletResponse, Model model) {
    model.addAttribute("targetUrl", ua.deriveNewUrl(request));

    return "redirect";
}

@RequestMapping(value = "**")
@ResponseBody
public ResponseEntity<Object> catchDenied(HttpServletRequest request, HttpServletResponse httpServletResponse) {
    return new ResponseEntity<Object>(HttpStatus.I_AM_A_TEAPOT);
}

The page that gets displayed for all the GET requests is based on a Thymeleaf template which uses Bootstrap in order to do the layout job. In order to include Bootstrap I use the webjars-locator and org.webjars.bootstrap, the resources are included by specifying <script src="/webjars/bootstrap/js/bootstrap.min.js"></script> in the redirect.html Thymeleaf template.

Problem

The problem is, that my ** mapping on GET also gets applied to the /webjars/... call and instead of the desired js code I get whatever my redirect template returns. I found no way to tell Spring Boot about the desired order.

First I would like to have Spring Boot handle the webjars mapping, then my other mapping.

Attempts so far

I checked other posts on SO but they only work when I have access to the sourcecode where the mapping is made. And I don't have access to the webjars locator / see no point in changing it just to solve this issue.

I also tried to set up a "anything that is not related to webjars" mapping like this:

@RequestMapping(value = "^(?!webjars$|actuator$).*", method = RequestMethod.GET)

But this doesn't have the desired effect because the RequestMapping only seems to support ant-stlye paths, which doesn't support negations because Ant (in contrast to Spring Boot) has a field for includes and excludes: https://ant.apache.org/manual/dirtasks.html

Negating the mapping seems only to be possible for params, not for the path: Change @RequestMapping order

Marged
  • 10,577
  • 10
  • 57
  • 99
  • 1
    Had any luck with https://stackoverflow.com/q/1234298/5757893 ? – mohkamfer Dec 29 '19 at 22:55
  • 1
    Did you try out produces/consumes in https://www.baeldung.com/spring-requestmapping ? Maybe you can target only html sources and ignore others? – mohkamfer Dec 29 '19 at 22:57
  • @mohkamfer as for your first suggestion: I would like to avoid "messing" with the Servlet setup directly and I would like to stick with the newstyle declarations and rather not resort to xml style. But this could be the final option if I don't find a different approach, thank you – Marged Dec 29 '19 at 23:03
  • @mohkamfer regarding your second suggestion: this can be a workaround but so far I am not completely sure which other mimetypes I need to support. I've seen `.svg` in the CMS for example, in order to go for your suggested approach I need more insight into the stuff stored inside the CMS – Marged Dec 29 '19 at 23:05

1 Answers1

1

I didn't yet find a way to influence the order if other mappings come from code I can not incluence.

But I found a way to configure "catch all except of ...":

@RequestMapping(value = { "", "/", "{url:(?!webjars$|actuator$).*}/**" }, method = RequestMethod.GET)

This configures three mappings. The first two are there to handle calls to the root of the webserver. The third configures a path pariable which I could also put into a @PathVariable but in my scenario the value doesn't matter. If you configure a path variable you need to give it a default because the pattern will only be satisfied depending on the value of your URL.

The regex tells Spring Boot only to react if the url doesn't contain webjars or actuator. The regex itself is best explained by using regex101:

enter image description here

Marged
  • 10,577
  • 10
  • 57
  • 99