I have issue in my application. I have various REST enpoints which are working fine. But now I want to send POST request with body. I already have 2 endpoints for POST method, but data are send using PathParam.
I created new endpoint, but when I send request I am getting CORS error. When I use the same endpoint without body in request everything is okay but of course at backend side I do not get any data from frontend (I have breakpoint inside method).
this is how I send request from my angular application:
post(requestUrl: string, body?: any): Observable<any> {
return this.httpClient.post<any>(this.API_URL + requestUrl, {password: 'test'});
}
After sending request I got:
Access to XMLHttpRequest at 'http://localhost:8080/...' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
If I send request like this (without body) this endpoint works fine:
post(requestUrl: string, body?: any): Observable<any> {
return this.httpClient.post<any>(this.API_URL + requestUrl);
}
At backend side I have added settings for CORS:
return Response.ok(object).header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
.allow("OPTIONS").build();
When I am sending request from Insomnia everything is ok - I can send body and I am getting sent data on backend.
Should I somehow set request headers at frontend side?
Here is my AdminApiController class:
#Path("/admin")
#RequestScoped
public class AdminApiController extends BaseApiController {
#Inject
private AdminAssembler adminAssembler;
#POST
#Path("/login")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response login(LoginRequest request) {
return Response.ok(adminAssembler.login(request))
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
.header("Access-Control-Allow-Headers", "Content-Type")
.allow("OPTIONS").build();
}
}
When your angular application sends a JSON payload in a POST request, it probably adds the header Content-Type: application/json. This header classifies the POST request as a "non-simple" request (that is, a request that cannot result out of an HTML <form> element without additional Javascript). Such "non-simple" requests cause to browser to make a preceding preflight request, that is an OPTIONS request with headers
Origin: http://localhost:4200
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
to which the server must respond with an Access-Control-Allow-Origin header and Access-Control-Allow-Headers: Content-Type. If it does not, the browser will not make the POST request and show an error like you observed.
Your Java code covers only #POST, not #OPTIONS, that's why the server does not respond to the preflight request with the necessary headers. How best to handle the OPTIONS requests for all endpoints on your server is a question for Java experts (which I am not).
You need to define your httpOptions.
Try this.
httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
post(requestUrl: string, body?: any): Observable<any> {
this.httpClient.post<any>(this.API_URL + requestUrl, {password: 'test'}, this.httpOptions)
}
Let me know if it worked for you.
Related
I am trying to setup code in such as way that executes a POST request in my step definition class, and the POST request includes authorization (bearer token), content type, and Cookies in headers, as well as a request body in json format.
I have the bearer token process setup and am using the bearerToken for the authorization as header, content type is application/json, and the request body has the below structure:
I am unsure how to proceed in this way using Rest Assured. Below is a given method that sets the base uri and the bearer token based on environment, and based on that the bearer token will be used accordingly for authorization as header when executing the POST request:
#Given("Request the environment for the Master API {string}")
public void getMasterAPIBaseUrl(String region) throws JSONException {
if (region.equalsIgnoreCase("DEV")) {
bearerToken = accTokenSetup.accessTokenSetup(region);
RestAssured.baseURI = urlProps.getProperty("devMasterAPIUrl");
}
else if (region.equalsIgnoreCase("STG")) {
bearerToken = accTokenSetup.accessTokenSetup(region);
RestAssured.baseURI = urlProps.getProperty("stgMasterAPIUrl");
}
Reporter.log("Getting master api base url for the environment which is " + RestAssured.baseURI, true);
}
Now I need an #When step that will execute the mentioned POST request with the request body and the headers (authorization, content-type, and Cookies). I know what is required would be the endpoint, headers, request body, etc. but unsure of how to proceed with it. Any help would be appreciated!
I'm creating web-services in Java with Jersey2.0. Everything works as expected when I execute request from POSTMAN but when I execute request from the client application I'm not able to receive header parameter. My client application is on JavaScript. Also, I've added the CORS allows origin request parameters in ContainerResponseContext.
The following shows my ContainerResponseFilter class where I add the CORS.
#Provider
class CORSFilter : ContainerResponseFilter {
override fun filter(requestContext: ContainerRequestContext?, responseContext: ContainerResponseContext?) {
responseContext?.apply {
headers.add("Access-Control-Allow-Origin", "*")
headers.add("Access-Control-Allow-Headers", "origin, content-type, authorization, accept, privatekey")
headers.add("Access-Control-Allow-Credentials", "true")
headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
}
}
}
The privatekey is my header name for the request. Now here's my code for ContainerRequestFilter.
#Priority(AUTHENTICATION)
#Provider
class JsTokenFilterNeeded : JsBaseFilter(this::class.java.simpleName) {
override fun filter(request: ContainerRequestContext?) {
val path = request?.uriInfo?.path
val privateKeyHeaderValue = request?.getHeaderString("privatekey")
println("private key -> $privateKeyHeaderValue")
}
}
I'm always getting the null value in privateKeyHeaderValue. Both the containers are successfully registered in ResourceConfig class.
As of now, I'm getting no 'Access-Control-Allow-Origin' header is present on the requested resource here's the log.
{host=[203.***.51.***:5555], connection=[keep-alive], access-control-request-method=[GET], origin=[http://localhost:38596], user-agent=[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36], access-control-request-headers=[privatekey], accept=[*/*], alexatoolbar-alx_ns_ph=[AlexaToolbar/alx-4.0.3], referer=[http://localhost:38596/], accept-encoding=[gzip, deflate], accept-language=[en-US,en;q=0.9]}
Edit 1
Here's my Js code for the client application.
$.ajax(
{
type: "GET",
headers: {
'privatekey': privateKey
},
url: "http://***.124.**.76:5555/dcu/energy/"+active_import,
data: {
'dcu_id': '99220445',
'tariff': 0
},
error: function (result) {
console.log(result);
},
success: function (result) {
console.log(result);
}
});
Edit2
I'm using ResourceConfig in order to register my Providers. Here's my ResourceConfig class.
class MyResourceConfig : ResourceConfig() {
init {
register(CORSFilter())
register(JsTokenFilterNeeded())
}
}
There is a preflight request that happened before the real request. The preflight request doesn't send any of the headers (the key header included). It only sends headers asking the server if the request is allowed. So when the preflight request reaches the filter, the token will not be there.
What you should do is make the CorsFilter implement both a ContainerRequestFilter and a ContainerResponseFilter. Make it a #PreMatching filter. That way it will be called before the token filter. In the request filter, check to see if it is a preflight request. If it is, then abort the request. This will cause the request to skip the rest of the request filters and go straight to the response filters. In the response filter side, you can add the CORS headers.
You should read the UPDATE in this post to get a better understanding of the flow of the CORS protocol and also see a better implementation of the CorsFilter that you can use that should work for your scenario.
I have a simple java web service deployed(say /diagnosis). When i hit the URL(/diagnosis) i am getting the JSON output. When i try to hit the rest service(/diagnosis) through Angular JS i am getting:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4201' is therefore not allowed access. The response had HTTP status code 500.
My Java code is:
#GET
#Path("/DiagnosisSortProviderCost")
#Produces(MediaType.APPLICATION_JSON)
public Response DiagnosisSortProviderCost() throws Exception {
// String path_name = "C:\\Users\\526761\\Desktop\\PioDel\\";
JSONArray jsonArr = jsonread.json_extract_provider(path_name);
System.out.println("--");
System.out.println(jsonArr);
Response response = Response.status(200).entity(jsonread.pro_DiagProvCost(jsonArr))
.header("Access-Control-Allow-Origin", "*").build();
return response;
}
I added the code to resolve CORS Filter issue, i even replaced the * with IP and port. Yet i couldn't get the issue resolved.
Please help me!!!
#GET
#Path("/DiagnosisSortProviderCost")
#Produces(MediaType.APPLICATION_JSON)
Because your mapping will never work. It only support GET method, in case of different http method like OPTIONS (for CORS), it will not serve.
All browser will send OPTIONS firstly to detect which method is allowed before sending actually request. If OPTIONS is not support or http method is not supported, browser will prevent it.
Change it to #RequestMaping with method option: The HTTP request methods to map to, narrowing the primary mapping: GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
I'm using Angular 6 in the frontend and Java Spring Boot in the backend.
I want my login page to make request to server. Server redirects to dashboard page.
I have http://localhost:4200/login angular page which makes a POST request to server http://localhost:8080/login
The .ts file contains:
onLoginClickPost() {
console.log('redirect request clicked');
this.data.getUserInfoPost().subscribe(
data => {
console.log(data);
this.userInfo = data;
}
);
}
getUserInfoPost() {
return this.http.post('http://localhost:8080/login', {nextUrl: 'http://localhost:4200/dashboard'});
}
The server has #RestController with a method mapping to incoming POST request, which should redirect to http://localhost:4200/dashboard :
#CrossOrigin(origins = "http://localhost:4200")
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<?> login_post(#RequestBody LoginReqPostParam payload) {
HttpHeaders headers = new HttpHeaders();
try {
headers.setLocation(new URI(payload.getNextUrl()));
headers.add("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
} catch (URISyntaxException e) {
logger.error("URI Exception: ", e);
e.printStackTrace();
}
return new ResponseEntity<>(headers, HttpStatus.FOUND);
}
LoginReqPostParam is a simple class to have incoming JSON payload as object.
The login angular page is able to make POST request to the server. Now at the server, after returning the ResponseEntity from server, I'm getting following error in browser console:
Failed to load http://localhost:4200/dashboard: Request header field
Content-Type is not allowed by Access-Control-Allow-Headers in
preflight response.
How do I redirect to http://localhost:4200/dashboard page? Do I need to add something to angular dashboard component files?
You are using #CrossOrigin for POST request but Angular (in development) is sending a Preflight request using OPTIONS.
I recommend you to use a development profile that permit all origins (you must create a custom filter in a Bean for these profile)
Use Allow-Control-Allow-Origin: * extension for google chrome.
And enable cross origin resource sharing
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en
I am having a weird issue where my client side request is telling me I have no 'Access-Control-Allow-Origin' present when making an HTTP POST request to a java servlet I have hosted and live. I have made sure to add the necessary headers in my response to clear up CORS requests issues but it does not seem to be recognizing the headers.
Here is my angular $http.post request I am making from the client side:
var parameter = JSON.stringify(details);
var req = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
data: parameter
}
$http.post(localurl, req).
then(function(response) {
});
Here is the error I am getting from chrome:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8081' is therefore not allowed access.
Here is the beginning of my java servlet doPost function:
#Override
public void doPost(HttpServletRequest req, HttpServletResponse res) {
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, HEAD");
res.addHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept");
I have been searching various stackoverflow questions and those response headers I am setting in my servlet should clear up the CORS requests issues but it does not seem to be recognizing the response headers I am setting at the beginning of the doPost function. Any and all help is very appreciated. Thanks in advance.
The problem is on your back-end, if yours is nodejs, should be like this way to allow Access-Control-Allow-Origin:
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});