automatic trailing slash redirection with Spring MVC - spring

I'd like to configure Spring MVC to do the following for me:
If (a controller is not found
&& controller exist for requestURI with or without trailing slash) {
redirect 301 to other URI with or without trailing slash
} else {
return 404 error
}
The above should be done by spring, not by some web.xml filter since only spring can test whether a redirect makes sense, i.e. whether there is a controller to handle the redirected request.

Related

Spring boot web app with jsp file extension in the url

We have a legacy web app that uses the url below:
https://example.com/forms/forms.jsp
We have rewritten the legacy code to use spring boot web app with the url https://example.com/forms without .jsp extension in the url.
In order to keep the old url, which is a business requirement, I followed this Spring MVC #PathVariable with a dot (.) gets truncated. However, it only works when there is a / https://example.com/forms/forms.jsp/ in the url.
I googled it, found some suggestions in stack overflow and tried a couple of different approaches. But not quite working.
UPDATES:
I just found this post on jsp in the url. I updated from #GetMapping("/forms/{jspName:.+}") to #GetMapping(path = "/forms/{jspName:.+}"). This made it possible to check the pathVariable in the if statement. However, the return statement does not return the expected forms.jsp file as before; instead it gives 404 error.
url : http://localhost:8080/forms/forms.jsp
#GetMapping(path = "/forms/{jspName:.+}")
public String getForms(#PathVariable("jspName") String jspName) {
if (jspName.equalsIgnoreCase("forms.jsp")) {
log.debug("JSP file is {}", jspName);
return "forms";
}
return "index";
}
Console:
[nio-8080-exec-1] c.n.e.c.EthicsEmailFormController : JSP file is forms.jsp
404 Error:
No webpage was found for the web address: http://localhost:8080/forms/forms.jsp
HTTP ERROR 404
application.properties - The forms.jsp is stored under /WEB-INF/views/page/forms.jsp.
spring.mvc.view.prefix=/WEB-INF/views/page/
spring.mvc.view.suffix=.jsp
For comparison:
Below works when the url is https://example.com/forms/forms.jsp/ with a / at the end of the url. But the existing url (that is specified in the requirement) does not contain a / at the end of the url. It has to be https://example.com/forms/forms.jsp.
#GetMapping("/forms/{jspName:.+}")
public String getForms(#PathVariable("jspName") String jspName) {
log.debug("Jsp file name = {} ", jspName);
return "forms";
}
I saw some suggestion is to remove below dependency. I also do NOT have below dependency in pom.xml.
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
Any suggestions? Thanks a lot!
Since this app is for training only, I moved the jsp file to webapp/forms.forms.jsp folder. This way, the jsp file can be accessed directly from the url below:
https://example.com/forms/forms.jsp
There is no need to go through a controller. Thanks to my friend Barry for his suggestion. Thanks!

Angular + Spring on same port

I deploy my angular project and add to resources/static in spring project, next I create simple controller:
#Controller
class IndexController {
#RequestMapping(value = "/")
fun index(): String {
return "index"
}
}
And now when I run tomcat and set url to localhost:8080/ everything work well I can click on buttons and browser redirect to proper site, But now if I refresh site or set diffrent url, my angular app stop working and I get 404 or spring endpoints. Question is, how I can set angular as default to load when I type diffrent url than this from controller
You need to separate your API endpoints context. For example /api/**. And then, define an endpoint with a regex, something like this ^/api (all other than /api) to resource path.

Spring boot embedded tomcat behaves differently to standalone

I have a Spring boot application that exposes a REST API via Spring MVC.
When I run my application locally using the embedded tomcat I can access resources with a trailing slash on the end - e.g POST /resource/
However, when I deploy the war to a standalone tomcat instance, I get a 404 if I include the trailing slash on the URL, but a success without the trailing slash - e.g POST /resource.
The embedded tomcat works with or without the trailing slash.
My request mapping is
#RequestMapping(value = "/resource", method = RequestMethod.POST)
I've tried all sorts of configuration options including
#Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseRegisteredSuffixPatternMatch(true);
matcher.setUseTrailingSlashMatch(true);
}
The only difference I can see is the embedded tomcat is v8 and the standalone is v7. Both running the exact same sourcecode but behaving differently.
Can anyone advise on how to correct this issue?
Thanks
I was able to resolve the issue. For anyone else finding this post...
For some reason, Tomcat 7 was trying to map requests with a trailing slash to a welcome file (index.jsp). It also does not recognise the endpoint if the request contains a trailing slash unless you specifically set a request mapping for "/" despite the setUseTrailingSlashMatch match to true.
This behavior was not mirrored in my embedded tomcat (v8).
I resolved the issue by removing the welcome files from the web.xml and updating my request mapping to:
#RequestMapping(value = {"/resource","/resource/"}, method = RequestMethod.POST)

How to send the send status code as response for 404 instead of 404.jsp as a html reponse in spring?

I created web application in spring and handled exception mappings for 404 and 500.If system doesn't find any resources for requested URL it redirects into custom 404.jsp instead of regular 404 page.Everything works fine till have decided to add a webservice in my app.I have included one more controller as a webservice there is no view for this controller and this needs to be invoke through curl command.
User may get into change the curl script.If they changed the URL it should show 404 status code.But it returns the custom 404.jsp as a html response instead of status code.Because dispatcher servlet will takes all urls with /*.
How I can solve this issue?
Please share your suggestions.
Spring 3.2 introduced the #ControllerAdvice, and as mentioned in the documentation:
It is typically used to define #ExceptionHandler
That means you can use the #ControllerAdvice to assist your #Controller like the following:
#ControllerAdvice
class GlobalControllerExceptionHandler {
#ResponseStatus(HttpStatus.NOT_FOUND) // 404
#ExceptionHandler(Exception.class)
public void handleNoTFound() {
// Nothing to do
}
}
For further details please refer to this tutorial and this answer.

Mapping to a JSON method with url-pattern

I'm creating a Spring MVC application that will have a controller with 'RequestMapping'-annotated methods, including a JSON method. It currently has static content that resides in webapps/static, and the app itself resides in webapps/myapp. I assume that Catalina's default servlet is handling the static content, and my *.htm url-pattern in web.xml is returning the request for my JSP page, but I haven't been able to get the JSON method to be called. How do I write the url-pattern in the servlet mapping to do so? Using /* has not worked; it prevents the app from being accessed at all. Is there anything else to be aware of?
I've learned of the default url-pattern, '/', which appears to be a match for my JSON request.

Resources