POST请求无法正常工作,但是GET工作正常。请求的资源上不存在“ Access-Control-Allow-Origin”标头

时间:2019-08-28 22:24:29

标签: angular spring rest cors

我有一个POST和GET方法,它们从触发请求的同一域中提供。虽然,我认为CORS不会成为问题,但似乎是这样,因为端口不同。

添加标头后,我可以设法处理GET请求,但POST无法正常工作。

我已经在服务器端添加了标头,下面是代码:

    @SuppressWarnings("unchecked")
    @RequestMapping(method=RequestMethod.OPTIONS,value="/refer")
    public ResponseEntity<?> options(){
        return new ResponseEntity(getHeaders(), HttpStatus.OK);

    }


    @RequestMapping(method=RequestMethod.GET,value="/search",produces="application/json")
    public ResponseEntity<?> searchCook(@ModelAttribute("cookSearch") CookSearch cookSearch){

        ResponseDto<List<DtoCook>> response = new ResponseDto<>();
        List<DtoCook> results = serviceCook.search(cookSearch);
        response.setData(results);
        response.setMessage(results.size()+" found.");
        return new ResponseEntity<>(response, getHeaders(),HttpStatus.OK);

    }


    @SuppressWarnings("unchecked")
    @RequestMapping(method=RequestMethod.POST,value="/refer",produces="application/json",consumes="application/json")
    public ResponseEntity<?> referCookPost(@ModelAttribute("dtoCookRefer") DtoCookRefer dtoCookRefer,BindingResult result) {

        System.out.println("in cook rest controller");

        // set the headers to allow CORS
        MultiValueMap<String, String> headers = getHeaders();

        System.out.println(dtoCookRefer.getCookName()+ " phone");
        ResponseDto<DtoCookRefer> respDto = new ResponseDto<>();
        respDto.setData(dtoCookRefer);

        //run Spring validator manually
        new CookReferValidator().validate(dtoCookRefer, result);

        if(serviceCookRefer.checkUniquePhNum(dtoCookRefer)) {
            respDto.setMessage("Phone number already present");
            return new ResponseEntity<>(respDto, headers,HttpStatus.UNPROCESSABLE_ENTITY);
        }


        // validate cook data
        if(result.hasErrors()) {
            //TODO set message source
            respDto.setMessage("Improper data");
            return new ResponseEntity<>(respDto, headers,HttpStatus.UNPROCESSABLE_ENTITY);


        }else {
            // save data to database
            serviceCookRefer.referCook(dtoCookRefer);
            // return proper response
            respDto.setMessage("Processed Successfully");
            return new ResponseEntity(respDto, headers, HttpStatus.OK);
        }


    }

    private MultiValueMap<String, String> getHeaders(){

        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String,String>();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        headers.add("Access-Control-Allow-Origin","http://example.org");
        headers.add("Access-Control-Allow-Methods","GET,PUT,POST,DELETE,OPTIONS");
        headers.add("Access-Control-Allow-Headers", 
                "Cache-Control,Pragma,Expires,Access-Control-Allow-Origin,"
                + "Access-Control-Allow-Methods,Content-Type,Transfer-Encoding,Date");
        return headers;
    }

下面是Angular中的代码:

import { Injectable } from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import { CookRefer } from './cook-refer';

@Injectable({
  providedIn: 'root'
})
export class CookReferService {
  private _url : string = "http://123.121.166.243:8080/ffc/ext/cook/refer";
  constructor(private _http : HttpClient) { }

  headers = new HttpHeaders({
    'Content-Type':'application/json',
    'Access-Control-Request-Method':'POST'
  });

  options={headers:this.headers};

  
  refer(cook : CookRefer){
    return this._http.post<any>(this._url,cook,this.options);
  }
}
我什至添加了一个OPTIONS方法,但没有帮助。我不确定是否有必要。我在以下几点上需要帮助:

  • 浏览器似乎阻止了CORS请求。该请求甚至没有到达服务器。
  • 尤其是对于POST,它甚至在我在客户端(角度)端添加标头之前也会触发预检请求,但对于GET则不然。
  • 为什么GET有效,但POST不起作用?

2 个答案:

答案 0 :(得分:2)

也许您应该在允许的标题中添加添加在帖子请求中的标题Access-Control-Request-Method。

尝试在控制器上使用CrossOrigin注释,而不要添加options方法,或者如果您只想为一种方法允许CORS,请在方法上使用:

@CrossOrigin
@RestController
public class Controller {

    // @CrossOrigin
    @RequestMapping("/link")
    public String retrieve() {
       // ...
    }
}

您可以像这样通过控制器来进行全局Cors配置:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

答案 1 :(得分:1)

需要以下标题

headers.add("Access-Control-Allow-Credentials","true");

由于浏览器控制台中的错误,我不得不删除了'Access-Control-Request-Method':'POST'

注释@CrossOrigin确实添加了我手动添加的标头。

现在,我在以下给定的链接中找到了问题的答案:

Tells why we need Access-Control-Allow-Credentials header

What exactly does the Access-Control-Allow-Credentials header do?

Why is there no preflight in CORS for POST requests with standard content-type

当我搜索一般错误时,我很难找到问题的答案,原因是网站上发布的主题太具体了,我不知道。

感谢您向@tcharaf回答。