Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get request only works with trailing slash (spring REST annotations)

I have a Spring REST Controller:

@RestController
@RequestMapping(value = "/myresource")
public class MyResourceController {
  ...
}

With a GET request method:

@RequestMapping(method = GET, value = "/{value1}/{value2}/{value3}", produces = MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8")    
public ResponseEntity<MyResponseType> getMyResource(
  @ApiParam(value = "...",...)
  @PathVariable("value1") String value1,
  @ApiParam(value = "...",...)
  @PathVariable("value2") String value2,
  @ApiParam(value = "...",...)
  @PathVariable("value3") String value3) {
//...
}

I would expect this method to be callable with:

http://myserver:8080/myresource/value1/value2/value3

But it is only reachable with a trailing slash:

http://myserver:8080/myresource/value1/value2/value3/

Why is that so or what is causing this?

Swagger assumes there are no trailing slashes and I can't send a request with swagger now.

What can I do to only make the first URL work but not the second?

Thanks a lot in advance for your comments and answers.


Edited 2:

I found out that without the slash the information of value3 is incomplete. value3 must be an email address but everything from the final dot is cut off. So instead of "[email protected]" I am getting "myemail@something".

This explains why I can't get a proper result (no content and HTTP status code 404). But I still don't understand why this happens. Further than that, if I have an email address with three letters in the top level domain (like .com) the request never reaches the GET method "getMyResource" ....


Edited 1: My web.xml looks like that:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/j2ee"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>(my) Services</display-name>
<filter>
    <filter-name>SetCharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>SetCharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Provide ServletContext -->
<listener>
    <listener-class>my.ServletContextUtils</listener-class>
</listener>

<!-- Expose request to current thread (required for session and request-scoping) -->
<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

<servlet>
    <servlet-name>spring-mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            WEB-INF/config/spring-mvc-servlet.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>spring-mvc</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

</web-app>

And my spring-mvc-servlet.xml looks like that:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"   xmlns:util="http://www.springframework.org/schema/util"
xmlns:env="http://my/schema"
xsi:schemaLocation="
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util-3.1.xsd
    http://my/schema
    http://my/schema/env-0.3.xsd">

<env:initialization />
<context:annotation-config />
<mvc:annotation-driven />
<mvc:default-servlet-handler/>
<context:component-scan base-package="my.myresource.restapi" />

<context:property-placeholder
    ignore-unresolvable="true"
    location="
        WEB-INF/config/${my.environment}/webapp.properties" />

<!-- Swagger -->

<!-- swagger config -->
<bean class="my.restapi.swagger.SwaggerConfig"/>

webapp.properties does not contain much:

swagger.include-pattern=/(?!api-docs|version).*
like image 891
Nina Avatar asked Jun 29 '15 13:06

Nina


People also ask

Should Apis have a trailing slash?

Always use trailing slashes for any resource that may contain children. Just consider "GET" on a public_html directory with files. So if "hello. html" can ever have children then it is always and forevermore "/hello.

Can RestController return view?

@RestController is not meant to be used to return views to be resolved. It is supposed to return data which will be written to the body of the response, hence the inclusion of @ResponseBody .

What happens when annotating a class with @RestController?

@Controller annotation indicates that the class is a “controller” like a web controller. @RestController annotation indicates that class is a controller where @RequestMapping methods assume @ResponseBody semantics by default. In @Controller, we need to use @ResponseBody on every handler method.


2 Answers

I have a lot of applications using Spring Rest annotations and my APIs works with or without the trailing slashes.

It may be a problem with your Spring MVC configuration or with the http server you are using.

Could you post some code snippets with you Spring MVC configurations. It would be good to known which Spring version you are using and how are you serving the webapp.

Edit 1:

As I read in your second edit you are having problems with email parameters right?

Can you try using something like that and let me known if it resolves the issue?

@RequestMapping(method = GET, value = "/{value1}/{value2}/{value3:.+}"...

The problem seems to be with the dot in the url.

Reference: Spring MVC @PathVariable with dot (.) is getting truncated

like image 109
Lucas Saldanha Avatar answered Oct 01 '22 03:10

Lucas Saldanha


I found the answer here:

Spring MVC @PathVariable getting truncated

This seems to happen only with the last parameter and the solution is to use a regex for the last value:

@RequestMapping(method = GET, value = "/{value1}/{value2}/{value3:.+}"

This works for me.

like image 20
Nina Avatar answered Oct 01 '22 05:10

Nina