Enabling CORS using Spring Boot 1.3.3-RELEASE

2019-08-12 21:12发布

I'm trying to enable CORS in a sample project using Spring Boot 1.3.3

I try to follow all the instructions from this link however I still not able to see results.

In my Application.java I have the following code.

@SpringBootApplication
public class Application {

    private static final String[] REQUEST_METHOD_SUPPORTED = { "GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD" };

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/rest/**").allowedOrigins("*").allowedHeaders("*").allowedMethods(REQUEST_METHOD_SUPPORTED);
            }
        };
    }
}

Everything works when I use GET and POST, but when I try to use PUT, DELETE, OPTIONS or PATCH. Also, I try to add this property spring.mvc.dispatch-options-request:true but still I don't get it work

I'm getting the following error:

Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'OPTIONS' not supported
Invoking @ExceptionHandler method: public final org.springframework.http.ResponseEntity<java.lang.Object> org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler.handleException(java.lang.Exception,org.springframework.web.context.request.WebRequest)
Request method 'OPTIONS' not supported
Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling

Successfully completed request

Do you guys have an idea how can I solved this issue? Do you have a tutorial where I can see a sample working with CORS using PUT or PATCH?

--- UPDATE ---

Here is my controller

@RestController
@RequestMapping(value = "/api/rest/accounts", produces =      MediaType.APPLICATION_JSON_VALUE)
public class AccountRestController {
private static final Logger LOGGER = LoggerFactory.getLogger(AccountRestController.class);

@RequestMapping(method = RequestMethod.POST)
public Account createAccount(@RequestBody Account messageBody) {
    Account account = buildAccount(messageBody);
    return dbPersistAccount(account);
}

@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
public void deleteAccount(@PathVariable("id") String id) {
    dbRemoveAccount(id);
}

@RequestMapping(method = RequestMethod.PUT, value = "/{id}")
public void updateAccount(@PathVariable("id") String id, @RequestBody Account messageBody) {
    Account account = dbGetAccount(id);

    if (account == null) {
        throw new ResourceNotFoundException("Account not found with id=[" + id + "]");
    }
}

@RequestMapping(method = RequestMethod.PATCH, value = "/{id}")
public void markAccount(@PathVariable("id") String id) {
    Account account = dbGetAccount(id);

    if (account == null) {
        throw new ResourceNotFoundException("Account not found with id=[" + id + "]");
    }
}

@RequestMapping(method = RequestMethod.GET, value = "/{id}")
public Account getAccount(@PathVariable("id") String id) {
    Account account = dbGetAccount(id);

    if (account == null) {
        throw new ResourceNotFoundException("Account not found with id=[" + id + "]");
    }

    return account;
}

}

Do I need to create the method OPTIONS manually? I don't have in my controller a method that handles the OPTIONS request

1条回答
一夜七次
2楼-- · 2019-08-12 21:25

Thanks for your answers and comments.

At the end the answer has to be with a combination of the answers posted in here; we were getting consume by a client that did not send a content-type so we were getting a 403 when it try to do a OPTIONS before a PATCH or PUT; after the rest client sent a content-type we were able to handle the request.

So, in my case the following code works, if the request includes content-type and you don't need to do any work around.

 @Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/api/rest/**").allowedOrigins("*").allowedHeaders("*").allowedMethods(REQUEST_METHOD_SUPPORTED);
        }
    };
}

However, if somebody has the requirement to allow requests OPTIONS without content-type, you need to use a simple filter which is mentioned in this Simple CORS Filter and change the following line:

response.setHeader("Access-Control-Allow-Headers", "");

I hope this can help somebody in the future.

查看更多
登录 后发表回答