POST request is not working, but GET is working fine. No 'Access-Control-Allow-Origin' header is present on the requested resource

I have a POST and a GET method served from the same domain from where the request is getting fired. Though, I felt that CORS wont be an issue, but it seems to be, as the port is different.

After adding the headers, I could manage to serve my GET request, but POST is not working.

I have added the headers on the server side, below is the code:

    @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;
    }

Below is the code in 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);
  }
}
I have even added an OPTIONS method, but did not help. I am unsure if its necessary. I need help on the below points:

Upvotes: 0

Views: 5192

Answers (2)

The below header was needed

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

I had to remove the 'Access-Control-Request-Method':'POST' due to error in browser console.

The annotation @CrossOrigin does add the same headers which I added manually.

Now, I found answers to my question in the below given links:

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

Its been hard for me to find the answer to my issue when I googled with the general error, cause topics posted over the websites are too specific which I wasn't aware of.

thank you for showing a direction towards the answer @tcharaf.

Upvotes: 1

tcharaf
tcharaf

Reputation: 630

May be you should add the header Access-Control-Request-Method ,added in your post request,in your allowed headers.

Try to use CrossOrigin annotation on your controller instead adding the options method, or on your method if you want to allow CORS just for one method:

@CrossOrigin
@RestController
public class Controller {

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

You can aloso make a global Cors config out of your controllers like:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

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

Upvotes: 3

Related Questions