Reputation: 153
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);
}
}
Upvotes: 0
Views: 5192
Reputation: 153
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
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