Spring Framework
  1. Spring Framework
  2. SPR-9849

Incorrect resolution of handler mappings - the Allow header has wrong values

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 3.1.2
    • Fix Version/s: Waiting for Triage
    • Component/s: None
    • Labels:
      None
    • Last commented by a User:
      false

      Description

      Sending an OPTIONS request to:

      /api/myobject/count

      The controller defines the following methods:

      @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
      @ResponseStatus(HttpStatus.NO_CONTENT)
      public Privilege deleteOneById{...}
      
      @RequestMapping(method = RequestMethod.GET, value = "/count")
      @ResponseBody
      @ResponseStatus(value = HttpStatus.OK)
      public long count() {...}
      

      The DispatcherServlet - getHandler logic will fail to find a match (since OPTIONS is not mapped) but when calculating the Allow header - both of these 2 methods will be considered a match, and the value of that header will be:

      Allow: GET, DELETE

      When it should just be:

      Allow: GET

      This leads to additional and incorrect values for the Allow header.

        Activity

        Hide
        Michael Osipov added a comment - - edited

        I have hit the same issue but even worse.

        1. Create a stub project from: https://github.com/SpringSource/spring-framework-issues
        2. Start it with mvn tomcat:run.

        3. Perform a simple GET first with cURL:

        mosipov@v325:~$ curl --verbose http://v325.vanager.de:8080/11111/
        * About to connect() to v325.vanager.de port 8080 (#0)
        *   Trying 85.119.155.135... connected
        * Connected to v325.vanager.de (85.119.155.135) port 8080 (#0)
        > GET /11111/ HTTP/1.1
        > User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1
        > Host: v325.vanager.de:8080
        > Accept: */*
        >
        < HTTP/1.1 200 OK
        < Server: Apache-Coyote/1.1
        < Set-Cookie: JSESSIONID=1DC2480618B760639F75A4D50C5A1D5F; Path=/11111
        < Content-Type: text/html;charset=UTF-8
        < Content-Language: de-DE
        < Content-Length: 253
        < Date: Sat, 07 Sep 2013 16:57:57 GMT
        <
        
        <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
        <html>
        <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Home</title>
        </head>
        <body>
          <h1>Home</h1>
        </body>
        </html>
        * Connection #0 to host v325.vanager.de left intact
        * Closing connection #0
        

        4. Perform an OPTIONS request now:

        mosipov@v325:~$ curl -X OPTIONS --verbose http://v325.vanager.de:8080/11111/
        * About to connect() to v325.vanager.de port 8080 (#0)
        *   Trying 85.119.155.135... connected
        * Connected to v325.vanager.de (85.119.155.135) port 8080 (#0)
        > OPTIONS /11111/ HTTP/1.1
        > User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1
        > Host: v325.vanager.de:8080
        > Accept: */*
        >
        < HTTP/1.1 200 OK
        < Server: Apache-Coyote/1.1
        < Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
        < Content-Length: 0
        < Date: Sat, 07 Sep 2013 16:59:24 GMT
        <
        * Connection #0 to host v325.vanager.de left intact
        * Closing connection #0
        

        Now, why do I see so may allowed methods? On this resource only HEAD, GET, OPTIONS and at most POST should be/is permitted. If I do perform a DELETE or PUT, I will receive:

        mosipov@v325:~$ curl -X PUT --verbose http://v325.vanager.de:8080/11111/
        * About to connect() to v325.vanager.de port 8080 (#0)
        *   Trying 85.119.155.135... connected
        * Connected to v325.vanager.de (85.119.155.135) port 8080 (#0)
        > PUT /11111/ HTTP/1.1
        > User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1
        > Host: v325.vanager.de:8080
        > Accept: */*
        >
        < HTTP/1.1 405 Method Not Allowed
        < Server: Apache-Coyote/1.1
        < Allow: POST, HEAD, GET
        < Content-Type: text/html;charset=utf-8
        < Content-Length: 1082
        < Date: Sat, 07 Sep 2013 17:00:34 GMT
        <
        <html><head><title>Apache Tomcat/6.0.29 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 405 - Request method 'PUT' not supported</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Request method 'PUT' not supported</u></p><p><b>description</b> <u>The specified HTTP method is not allowed for the requested resource (Request method 'PUT' not supported).</u></p><HR size="1" nos* Connection #0 to host v325.vanager.de left intact
        * Closing connection #0
        hade="noshade"><h3>Apache Tomcat/6.0.29</h3></body></html>
        
        mosipov@v325:~$ curl -X DELETE --verbose http://v325.vanager.de:8080* About to connect() to v325.vanager.de port 8080 (#0)
        *   Trying 85.119.155.135... connected
        * Connected to v325.vanager.de (85.119.155.135) port 8080 (#0)
        > DELETE /11111/ HTTP/1.1
        > User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1
        > Host: v325.vanager.de:8080
        > Accept: */*
        >
        < HTTP/1.1 405 Method Not Allowed
        < Server: Apache-Coyote/1.1
        < Allow: POST, HEAD, GET
        < Content-Type: text/html;charset=utf-8
        < Content-Length: 1091
        < Date: Sat, 07 Sep 2013 17:00:52 GMT
        <
        <html><head><title>Apache Tomcat/6.0.29 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 405 - Request method 'DELETE' not supported</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Request method 'DELETE' not supported</u></p><p><b>description</b> <u>The specified HTTP method is not allowed for the requested resource (Request method 'DELETE' not supported).</u></p><HR siz* Connection #0 to host v325.vanager.de left intact
        * Closing connection #0
        e="1" noshade="noshade"><h3>Apache Tomcat/6.0.29</h3></body></html>
        

        The calculation of Allow is simply broken.

        Show
        Michael Osipov added a comment - - edited I have hit the same issue but even worse. 1. Create a stub project from: https://github.com/SpringSource/spring-framework-issues 2. Start it with mvn tomcat:run . 3. Perform a simple GET first with cURL : mosipov@v325:~$ curl --verbose http://v325.vanager.de:8080/11111/ * About to connect() to v325.vanager.de port 8080 (#0) * Trying 85.119.155.135... connected * Connected to v325.vanager.de (85.119.155.135) port 8080 (#0) > GET /11111/ HTTP/1.1 > User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1 > Host: v325.vanager.de:8080 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Set-Cookie: JSESSIONID=1DC2480618B760639F75A4D50C5A1D5F; Path=/11111 < Content-Type: text/html;charset=UTF-8 < Content-Language: de-DE < Content-Length: 253 < Date: Sat, 07 Sep 2013 16:57:57 GMT < <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Home</title> </head> <body> <h1>Home</h1> </body> </html> * Connection #0 to host v325.vanager.de left intact * Closing connection #0 4. Perform an OPTIONS request now: mosipov@v325:~$ curl -X OPTIONS --verbose http://v325.vanager.de:8080/11111/ * About to connect() to v325.vanager.de port 8080 (#0) * Trying 85.119.155.135... connected * Connected to v325.vanager.de (85.119.155.135) port 8080 (#0) > OPTIONS /11111/ HTTP/1.1 > User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1 > Host: v325.vanager.de:8080 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH < Content-Length: 0 < Date: Sat, 07 Sep 2013 16:59:24 GMT < * Connection #0 to host v325.vanager.de left intact * Closing connection #0 Now, why do I see so may allowed methods? On this resource only HEAD, GET, OPTIONS and at most POST should be/is permitted. If I do perform a DELETE or PUT, I will receive: mosipov@v325:~$ curl -X PUT --verbose http://v325.vanager.de:8080/11111/ * About to connect() to v325.vanager.de port 8080 (#0) * Trying 85.119.155.135... connected * Connected to v325.vanager.de (85.119.155.135) port 8080 (#0) > PUT /11111/ HTTP/1.1 > User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1 > Host: v325.vanager.de:8080 > Accept: */* > < HTTP/1.1 405 Method Not Allowed < Server: Apache-Coyote/1.1 < Allow: POST, HEAD, GET < Content-Type: text/html;charset=utf-8 < Content-Length: 1082 < Date: Sat, 07 Sep 2013 17:00:34 GMT < <html><head><title>Apache Tomcat/6.0.29 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 405 - Request method 'PUT' not supported</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Request method 'PUT' not supported</u></p><p><b>description</b> <u>The specified HTTP method is not allowed for the requested resource (Request method 'PUT' not supported).</u></p><HR size="1" nos* Connection #0 to host v325.vanager.de left intact * Closing connection #0 hade="noshade"><h3>Apache Tomcat/6.0.29</h3></body></html> mosipov@v325:~$ curl -X DELETE --verbose http://v325.vanager.de:8080* About to connect() to v325.vanager.de port 8080 (#0) * Trying 85.119.155.135... connected * Connected to v325.vanager.de (85.119.155.135) port 8080 (#0) > DELETE /11111/ HTTP/1.1 > User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1 > Host: v325.vanager.de:8080 > Accept: */* > < HTTP/1.1 405 Method Not Allowed < Server: Apache-Coyote/1.1 < Allow: POST, HEAD, GET < Content-Type: text/html;charset=utf-8 < Content-Length: 1091 < Date: Sat, 07 Sep 2013 17:00:52 GMT < <html><head><title>Apache Tomcat/6.0.29 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 405 - Request method 'DELETE' not supported</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Request method 'DELETE' not supported</u></p><p><b>description</b> <u>The specified HTTP method is not allowed for the requested resource (Request method 'DELETE' not supported).</u></p><HR siz* Connection #0 to host v325.vanager.de left intact * Closing connection #0 e="1" noshade="noshade"><h3>Apache Tomcat/6.0.29</h3></body></html> The calculation of Allow is simply broken.
        Hide
        Rossen Stoyanchev added a comment - - edited

        Eugen Paraschiv, I see why you might expect that only "Allow: GET" is returned in this case. However, I don't quite see how it could work based on the given configuration. After all the path "/count" matches the pattern "/{id}", i.e. there is no way to tell that "count" is not an id. In fact a request for "DELETE /count" will be matched to the method deleteOneById.

        Michael Osipov, the reason all HTTP methods are returned is most likely because the DispatcherServlet does not have its "dispatchOptionsRequest" property configured in which case OPTIONS requests are handled with the default behavior of the HttpServlet base class. See this part of the web.xml in the example project I created.

        Show
        Rossen Stoyanchev added a comment - - edited Eugen Paraschiv , I see why you might expect that only "Allow: GET" is returned in this case. However, I don't quite see how it could work based on the given configuration. After all the path "/count" matches the pattern "/{id}", i.e. there is no way to tell that "count" is not an id. In fact a request for "DELETE /count" will be matched to the method deleteOneById. Michael Osipov , the reason all HTTP methods are returned is most likely because the DispatcherServlet does not have its "dispatchOptionsRequest" property configured in which case OPTIONS requests are handled with the default behavior of the HttpServlet base class. See this part of the web.xml in the example project I created.

          People

          • Assignee:
            Rossen Stoyanchev
            Reporter:
            Eugen Paraschiv
            Last updater:
            Rossen Stoyanchev
          • Votes:
            2 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Days since last comment:
              10 weeks, 4 days ago