简体   繁体   English

Spring Boot - 如何在 REST 控制器 HTTP PUT 上允许 CORS

[英]Spring Boot - how to allow CORS on REST Controller HTTP PUT

I'm my Spring Boot REST controller, I'm able to allow CORS for HTTP POST, but for some reason HTTP PUT is still being blocked.我是我的 Spring Boot REST 控制器,我可以允许 CORS 用于 HTTP POST,但由于某种原因 HTTP PUT 仍然被阻止。 I have placed my CORS decorator at the Controller level - HTTP PUT handler still being blocked.我已将 CORS 装饰器置于控制器级别 - HTTP PUT 处理程序仍被阻止。 Here is my controller:这是我的控制器:

package com.khoubyari.example.api.rest;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

import com.khoubyari.example.domain.Hotel;
import com.khoubyari.example.exception.DataFormatException;
import com.khoubyari.example.service.HotelService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RestController
@RequestMapping(value = "/example/v1/hotels")
@Api(tags = {"hotels"})
//@CrossOrigin(origins = "http://localhost:4200")
@CrossOrigin( origins = "*" , allowedHeaders = "*")
public class HotelController extends AbstractRestHandler {

    @Autowired
    private HotelService hotelService;

    @RequestMapping(value = "",
            method = RequestMethod.POST,
            consumes = {"application/json", "application/xml"},
            produces = {"application/json", "application/xml"})
    @ResponseStatus(HttpStatus.CREATED)
    @ApiOperation(value = "Create a hotel resource.", notes = "Returns the URL of the new resource in the Location header.")
    public void createHotel(@RequestBody Hotel hotel,
                                 HttpServletRequest request, HttpServletResponse response) {
        Hotel createdHotel = this.hotelService.createHotel(hotel);
        response.setHeader("Location", request.getRequestURL().append("/").append(createdHotel.getId()).toString());
    }

    @RequestMapping(value = "",
            method = RequestMethod.GET,
            produces = {"application/json", "application/xml"})
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "Get a paginated list of all hotels.", notes = "The list is paginated. You can provide a page number (default 0) and a page size (default 100)")
    public
    @ResponseBody
    Page<Hotel> getAllHotel(@ApiParam(value = "The page number (zero-based)", required = true)
                                      @RequestParam(value = "page", required = true, defaultValue = DEFAULT_PAGE_NUM) Integer page,
                                      @ApiParam(value = "Tha page size", required = true)
                                      @RequestParam(value = "size", required = true, defaultValue = DEFAULT_PAGE_SIZE) Integer size,
                                      HttpServletRequest request, HttpServletResponse response) {
        return this.hotelService.getAllHotels(page, size);
    }

    @RequestMapping(value = "/{id}",
            method = RequestMethod.GET,
            produces = {"application/json", "application/xml"})
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(value = "Get a single hotel.", notes = "You have to provide a valid hotel ID.")
    public
    @ResponseBody
    Hotel getHotel(@ApiParam(value = "The ID of the hotel.", required = true)
                             @PathVariable("id") Long id,
                             HttpServletRequest request, HttpServletResponse response) throws Exception {
        Hotel hotel = this.hotelService.getHotel(id);
        checkResourceFound(hotel);
        return hotel;
    }

    @RequestMapping(value = "/{id}",
            method = RequestMethod.PUT,
            consumes = {"application/json", "application/xml"},
            produces = {"application/json", "application/xml"})
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @ApiOperation(value = "Update a hotel resource.", notes = "You have to provide a valid hotel ID in the URL and in the payload. The ID attribute can not be updated.")
    public void updateHotel(@ApiParam(value = "The ID of the existing hotel resource.", required = true)
                                 @PathVariable("id") Long id, @RequestBody Hotel hotel,
                                 HttpServletRequest request, HttpServletResponse response) {
        checkResourceFound(this.hotelService.getHotel(id));
        if (id != hotel.getId()) throw new DataFormatException("ID doesn't match!");
        this.hotelService.updateHotel(hotel);
    }

    //todo: @ApiImplicitParams, @ApiResponses
    @RequestMapping(value = "/{id}",
            method = RequestMethod.DELETE,
            produces = {"application/json", "application/xml"})
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @ApiOperation(value = "Delete a hotel resource.", notes = "You have to provide a valid hotel ID in the URL. Once deleted the resource can not be recovered.")
    public void deleteHotel(@ApiParam(value = "The ID of the existing hotel resource.", required = true)
                                 @PathVariable("id") Long id, HttpServletRequest request,
                                 HttpServletResponse response) {
        checkResourceFound(this.hotelService.getHotel(id));
        this.hotelService.deleteHotel(id);
    }
}

What should I change in order for the HTTP PUT handler to allow updates?为了让 HTTP PUT 处理程序允许更新,我应该更改什么?

Note : By default, all origins and GET, HEAD, and POST methods are allowed.注意:默认情况下,允许所有来源和 GET、HEAD 和 POST 方法。 https://spring.io/guides/gs/rest-service-cors/ https://spring.io/guides/gs/rest-service-cors/

Explicitly enable the allowedMethods显式启用 allowedMethods

allowed-methods="GET,PUT,HEAD,OPTIONS,POST,DELETE,PATCH" in your code or via allowed-methods="GET,PUT,HEAD,OPTIONS,POST,DELETE,PATCH"在您的代码中或通过

registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedHeaders("*")
                    .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
                    .maxAge(-1)   // add maxAge
                    .allowCredentials(false);

Ref: Spring Global CORS configuration not working but Controller level config does参考: Spring Global CORS 配置不起作用,但控制器级别的配置起作用

To resolve CORS issue, you can write another method in service as follows要解决 CORS 问题,您可以在服务中编写另一种方法,如下所示

Please check following link addressing same CORS issue GET request working on postman but not in browser请检查以下链接解决相同的 CORS 问题GET 请求在邮递员上工作但不在浏览器中

You may need to specify allowed methods explicitely like this in your CORS config (I'm using Kotlin and implementing WebMvcConfigurer ):您可能需要在 CORS 配置中像这样明确指定允许的方法(我正在使用 Kotlin 并实现WebMvcConfigurer ):

override fun addCorsMappings(registry: CorsRegistry) {
    log.info("CORS: {}", origins)
    registry.addMapping("/**").allowedOrigins(*origins)
        .allowedMethods("GET", "POST", "PUT", "OPTIONS")
}

PUT is not allowed by default, as can be seen in CorsConfiguration#DEFAULT_PERMIT_METHODS :默认情况下不允许 PUT,如CorsConfiguration#DEFAULT_PERMIT_METHODS

private static final List<String> DEFAULT_PERMIT_METHODS = Collections.unmodifiableList(
        Arrays.asList(HttpMethod.GET.name(), HttpMethod.HEAD.name(), HttpMethod.POST.name()));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM