Bad file upload request when served from Tomcat, but works fine when served with mvn tomcat7: run

I have an AngularJS application with Spring REST api.

AngularJS static resources can be served by the grunt serve command, either by the Apache server or by Tomcat itself.

The api can be served by manual deployment on a standalone Tomcat or by the mvn tomcat7: run command.

Tomcat version is 7.

All of these commands are executed under the same Linux user.

There is a controller file upload handler Spring

.

Serving with grunt + Tomcat service fails and it fails when served from grunt + Tomcat build and fails when serving with Apache + Tomcat

It works great when served with grunt serve + mvn tomcat7: runs and works great when served with grunt: dist + mvn tomcat7: runs and works great when served with apache + mvn tomcat7: run

All of the above commands are executed on my development server.

It also fails in the same way on the production server Tomcat.

I understand that the grunt build does the job then.

The error is the same in Chromium and Firefox.

Removing the method = annotation RequestMethod.POST from the controller handler didn't change anything in the console error output.

The problem must be running on the server side ... Error message: Request method "POST" is not supported

Failure of the request, as shown in the Chromium browser:

Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/nitro-manager-rest/api/rollouts/import
Request Method:POST
Status Code:400 Bad Request
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,fr;q=0.6,es;q=0.4,et;q=0.2,nb;q=0.2,ru;q=0.2,sv;q=0.2,it;q=0.2,de;q=0.2
Connection:keep-alive
Content-Length:2389
Content-Type:multipart/form-data; boundary=----WebKitFormBoundarykinGH3Nf0BBnRvRW
Host:localhost:8080
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/34.0.1847.116 Chrome/34.0.1847.116 Safari/537.36
X-Auth-Token:eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MTc4NjY2NjAsInN1YiI6Im5zbkBuc24uY29tIn0.OhfS2HFFjXC64Ql7h6--PkrUvFbBis8CiFPb4HGn1_k
Request Payload
------WebKitFormBoundarykinGH3Nf0BBnRvRW
Content-Disposition: form-data; name="file"; filename="SFR-rollout-rollout-export.zip"
Content-Type: application/zip


------WebKitFormBoundarykinGH3Nf0BBnRvRW--
Response Headersview source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Accept-Language,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-Filename,Content-Disposition,Content-Length,X-Auth-Token
Access-Control-Allow-Methods:POST, PUT, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:http://localhost:9000
Access-Control-Expose-Headers:Accept-Language,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-Filename,Content-Disposition,Content-Length,X-Auth-Token
Access-Control-Max-Age:3600
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Connection:close
Content-Type:application/json;charset=UTF-8
Date:Mon, 01 Dec 2014 15:41:04 GMT
Expires:0
Pragma:no-cache
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block

      

Successful request as shown in the Chromium browser:

Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/nitro-manager-rest/api/rollouts/import
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,fr;q=0.6,es;q=0.4,et;q=0.2,nb;q=0.2,ru;q=0.2,sv;q=0.2,it;q=0.2,de;q=0.2
Connection:keep-alive
Content-Length:2389
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryJHnXN3HjJJNYTURZ
Host:localhost:8080
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/34.0.1847.116 Chrome/34.0.1847.116 Safari/537.36
X-Auth-Token:eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MTc4NjY2NjAsInN1YiI6Im5zbkBuc24uY29tIn0.OhfS2HFFjXC64Ql7h6--PkrUvFbBis8CiFPb4HGn1_k
Request Payload
------WebKitFormBoundaryJHnXN3HjJJNYTURZ
Content-Disposition: form-data; name="file"; filename="SFR-rollout-rollout-export.zip"
Content-Type: application/zip


------WebKitFormBoundaryJHnXN3HjJJNYTURZ--
Response Headersview source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Accept-Language,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-Filename,Content-Disposition,Content-Length,X-Auth-Token
Access-Control-Allow-Methods:POST, PUT, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:http://localhost:9000
Access-Control-Expose-Headers:Accept-Language,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-Filename,Content-Disposition,Content-Length,X-Auth-Token
Access-Control-Max-Age:3600
Cache-Control:no-store
Cache-Control:no-cache
Content-Type:application/json;charset=UTF-8
Date:Sun, 30 Nov 2014 21:51:40 GMT
Expires:Thu, 01 Jan 1970 00:00:00 GMT
Location:http://localhost:8080/nitro-manager-rest/api/rollouts/import?file=[org.springframework.web.multipart.commons.CommonsMultipartFile@2a52c0]
Pragma:no-cache
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block

      

Controller handler:

@ProductManager
@Controller
@RequestMapping(RESTConstants.SLASH + RESTConstants.ROLLOUTS)
public class RolloutImportController {

    private static Logger logger = LoggerFactory.getLogger(RolloutImportController.class);

    @Autowired 
    private ResourceService resourceService;

    @Autowired 
    private RolloutService rolloutService;

    @Autowired 
    private ExportService exportService;

    @Autowired
    private RolloutResourceAssembler rolloutResourceAssembler;

    @RequestMapping(value = RESTConstants.SLASH + RESTConstants.SLASH + RESTConstants.IMPORT, method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<List<String>> rolloutImport(@RequestParam(value = "file") List<MultipartFile> files, UriComponentsBuilder builder) {
        logger.debug("==========>> In rolloutImport");
        HttpHeaders responseHeaders = new HttpHeaders();
        List<String> messages = exportService.rolloutImport(files);
        responseHeaders.setLocation(builder.path(RESTConstants.SLASH + RESTConstants.ROLLOUTS + RESTConstants.SLASH + RESTConstants.IMPORT).queryParam("file", files).buildAndExpand().toUri());
        return new ResponseEntity<List<String>>(messages, responseHeaders, HttpStatus.OK);
    }

}

      

On my development server, the log says:

2014-11-30 17:08:29,967 DEBUG  [DispatcherServlet] DispatcherServlet with name 'NITRo' processing POST request for [/nitro-manager-rest/api/rollouts/import] 
2014-11-30 17:08:30,145 DEBUG  [CommonsMultipartResolver] Found multipart file [file] of size 2194 bytes with original filename [Orange-rollout-rollout-export.zip], stored in memory 
2014-11-30 17:08:30,151 DEBUG  [RequestMappingHandlerMapping] Looking up handler method for path /rollouts/import 
2014-11-30 17:08:30,180 DEBUG  [RequestMappingHandlerMapping] Returning handler method [public org.springframework.http.ResponseEntity<java.util.List<java.lang.String>> com.nsn.nitro.project.rest.controller.RolloutImportController.rolloutImport(java.util.List<org.springframework.web.multipart.MultipartFile>,org.springframework.web.util.UriComponentsBuilder)] 

      

But my production server says:

2014-11-30 17:26:35,839 DEBUG  [RequestMappingHandlerMapping] Looking up handler method for path /rollouts/import 
2014-11-30 17:26:35,858 DEBUG  [ExceptionHandlerExceptionResolver] Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported 

      

EDIT: I added the log access output and the console log shows this:

POST /nitro-manager-rest/api/rollouts/import HTTP/1.1
host: localhost:8080
connection: keep-alive
content-length: 2389
origin: http://localhost:9000
x-auth-token: eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MTc4NjY2NjAsInN1YiI6Im5zbkBuc24uY29tIn0.OhfS2HFFjXC64Ql7h6--PkrUvFbBis8CiFPb4HGn1_k
user-agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/34.0.1847.116 Chrome/34.0.1847.116 Safari/537.36
content-type: multipart/form-data; boundary=----WebKitFormBoundaryEDbGOJFhgA4Olleb
accept: */*
referer: http://localhost:9000/
accept-encoding: gzip,deflate,sdch
accept-language: en-US,en;q=0.8,fr;q=0.6,es;q=0.4,et;q=0.2,nb;q=0.2,ru;q=0.2,sv;q=0.2,it;q=0.2,de;q=0.2    

HTTP/1.1 400 Bad Request
Access-Control-Expose-Headers: Accept-Language,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-Filename,Content-Disposition,Content-Length,X-Auth-Token
X-XSS-Protection: 1; mode=block
Expires: 0
Access-Control-Max-Age: 3600
Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
Connection: close
Access-Control-Allow-Credentials: true
X-Content-Type-Options: nosniff
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
X-Frame-Options: DENY
Access-Control-Allow-Headers: Accept-Language,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-Filename,Content-Disposition,Content-Length,X-Auth-Token
Date: Mon, 01 Dec 2014 14:37:18 GMT
Transfer-Encoding: chunked
Access-Control-Allow-Origin: http://localhost:9000
Content-Type: application/json;charset=UTF-8

      

EDIT: The problem comes from the controller class that the handler is in. Moving the handler to another controller class solves the problem. Changing the mapping value attribute of the controller class does not solve the problem. Hope to resolve this issue soon.

EDIT: I could find work on this issue. This is not a solution. Just work. By moving the handler:

@RequestMapping(value = RESTConstants.SLASH + RESTConstants.IMPORT, method = RequestMethod.POST)
@ResponseBody
public ResponseEntity<List<String>> rolloutImport(@RequestParam(value = "file") List<MultipartFile> files, UriComponentsBuilder builder) {
    HttpHeaders responseHeaders = new HttpHeaders();
    List<String> messages = exportService.rolloutImport(files);
    responseHeaders.setLocation(builder.path(RESTConstants.SLASH + RESTConstants.ROLLOUTS + RESTConstants.SLASH + RESTConstants.IMPORT).queryParam("file", files).buildAndExpand().toUri());
    return new ResponseEntity<List<String>>(messages, responseHeaders, HttpStatus.OK);
}

      

outside the controller class:

@Controller
@RequestMapping(RESTConstants.SLASH + RESTConstants.ROLLOUTS)
public class RolloutImportController {

      

to any other controller class, for example a controller class:

@Controller
@RequestMapping(RESTConstants.SLASH + RESTConstants.ROLLOUTS)
public class RolloutExportController {

      

did the job perfectly.

I have no idea why.

I suspected that the two controller classes have the same mapping:

@RequestMapping(RESTConstants.SLASH + RESTConstants.ROLLOUTS)

      

might be a problem and renamed to one of them, but that didn't change anything about this problem.

Then I assumed that the word "import" in the handler display is part of the problem, for example, it appears in some Spring security config or something else (searching for source code returns nothing with "import") and so I also changed the display itself handler:

@RequestMapping(value = RESTConstants.SLASH + RESTConstants.IMPORT, method = RequestMethod.POST)

      

in

@RequestMapping(value = RESTConstants.SLASH + "myimp", method = RequestMethod.POST)

      

but that also didn't change anything about this issue.

At the moment I am happy with my work, but I am still confused about this issue.

+3


source to share





All Articles