I'm trying to consume my (CORS compatible) RESTful service
#Path("/greeting")
#GET
#Produces("application/json")
public Response greeting() {
String result = "{\"id\":1,\"content\":\"Hello, World!\"}";
return Response.ok() //200
.entity(result)
.header("Access-Control-Allow-Origin", "*")
.build();
}
from my AngularJS application.
function ($scope, $http) {
$scope.dashboard = "ESCO Dashboard";
console.log('start');
// Simple GET request example:
$http({
method: 'GET',
url: 'http://localhost:8080/NobelGrid/api/users/greeting'
}).then(function successCallback(response) {
console.log('success');
$scope.greeting = response.data;
}, function errorCallback(response) {
console.log('error');
});
console.log('end');
}
but I have this error:
XMLHttpRequest cannot load http://localhost:8080/NobelGrid/api/users/greeting. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.
Using Console Network of Chrome this seems true cause the Response Header is:
Anyway accessing to the REST service from the browser and not from the Angular app, the header is correct
I also tried this tutorial:
https://spring.io/guides/gs/consuming-rest-angularjs/
with their RESTful service (also CORS compatible, they said), but the result is the same.
ps: I'm using WebStorm as IDE.
UPDATE - SOLVED
Writing this handler at server-side:
#Path("/greeting")
#OPTIONS
#Produces("application/json")
public Response greetingOPT() {
return Response.status(200) //200
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, X-Codingpedia,Authorization")
.build();
}
it works. At the beginning it gives to me another error:
Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight [..]
but adding Authorization to the Access-Control-Allow-Headers of the GET and POST resolve the problem.
Look at the error message:
Response to preflight request
Look at the Network log:
Request Method: OPTIONS
Look at your API:
#GET
You need to write a handler for the preflight OPTIONS request before the browser will make the GET request to the handler you have written.
Related
I try to get issues from redmine via them Rest Api. When I call it from Postman I get response, but when I do it from my angular App I get such error
OPTIONS https://redmine.ourDomain.net/issues.json 404 (Not Found)
XMLHttpRequest cannot load https://redmine.ourDomain.net/issues.json. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 404.
Its how I do it in Angular
login(user: User): Observable<boolean> {
var headers: Headers = new Headers();
headers.append("Authorization", "Basic " + btoa(user.login + ":" + user.password));
let options = new RequestOptions({ headers: headers });
return this.http.get("https://redmine.ourDomain.net/issues.json", options)
.map((response: Response) => {
debugger;
if (response.status == 200) {
// set token property
// store username and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify({ user }));
// return true to indicate successful login
return true;
} else {
// return false to indicate failed login
return false;
}
});
}
And there how request looks in my browser
You'll need to enable CORS access on the backend: http://www.redmine.org/plugins/redmine_cors
Here's a nice extension that will let you test frontend code outside of normal CORS restrictions. It's strictly for testing and won't help a production app, but nice to have: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi
CORS must be set up in the backend. Please note that is NOT a good practice to allow all origins Access-Control-Allow-Origin: '*' and that you will need to specify the other headers as well:
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: authorization.
I am using Laravel Lumen to create an API for my MeteorJS App. This is my code inm y meteorJS on imports\api\tasks.js
...
import { HTTP } from 'meteor/http';
import { WebApp } from 'meteor/webapp';
if (Meteor.is_client) {
// Calling our Meteor server's function
// and simply storing data into current session
Meteor.call('fetchDataFromUrl', function (error, response) {
Session.set('external_server_data', response)
});
// Providing meteor data for template (it renders on data received)
Template.data.server_data = function () {
return Session.get('external_server_data');
};
}
if (Meteor.is_server) {
Meteor.methods({
// Declaring a method
retrieve_doc_types: function () {
this.unblock();
return Meteor.http.get(api_url);
}
});
}
Meteor.methods({
'tasks.insert'(make, model, year) {
check(make, String);
check(model, String);
check(year, String);
if (! Meteor.userId()) {
throw new Meteor.Error('not-authorized');
}
HTTP.call("POST", "http://localhost:8000/api/v1/car",
{data: {"make":make, "model":model, "year":year}},
function (error, result) {
if (!error) {
console.log(result);
} else{
console.log("http post error");
};
});
},
....
but when I got this error:
XMLHttpRequest cannot load http://localhost:8000/api/v1/car. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 405.
tasks.js:81 http post error
do anyone have an idea? I am new with MeteorJS
try this in your server/main.js
WebApp.rawConnectHandlers.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
return next();
});
Where do you call the Method? The method is called tasks.insert but the code you provide only calls fetchDataFromUrl method.
Here are some ideas.
Check your call on the client is used asynchronously. From the Metor HTTP doc: On the client, this function must be used asynchronously by passing a callback. Note that some browsers first send an OPTIONS request before sending your request (in order to determine CORS headers).
I had CORS problem too in one of my project and I ended up by using HTTP library server side only. You can do it by surrounding your HTTP call with a Meteor.isServer.
Somebody tried to answer But I am not getting it. You try your luck.
https://codexample.org/questions/9358/no-access-control-allow-origin-error-in-meteor-app.c
Try package - simple:json-routes and put following code at serverside startup.
// Enable cross origin requests for all endpoints
JsonRoutes.setResponseHeaders({
"Cache-Control": "no-store",
"Pragma": "no-cache",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, PUT, POST, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With"
});
I Am not able to fetch data from Rest Server.Following Error is coming:
"Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access."
Response is coming as "0", This is not hitting the Rest Method also.
Rest APT:
#POST
#Timed
#Path("updateScore")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response updateScore(Player player)
{
StringBuilder returnStr = new StringBuilder("Sucess");
return Response.ok().
header("Access-Control-Allow-Origin", "http://localhost:8080").
header("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS").
header("Access-Control-Allow-Headers", "Origin, Content-Type, X-Auth-Token").
allow("OPTIONS").
status(200).
entity("Hello").build();
}
JavaScript Call
var url = "http://192.168.0.101:9090/api/FGame/updateScore/";
var client = new XMLHttpRequest();
client.open('POST', url, true);
client.setRequestHeader('Content-Type', 'application/json');
client.send('{"Name" : 12}');
client.onreadystatechange = function() {
alert(client.status);
alert(client.data)
};
But if I am changing to JavaScript call as following then working fine.
JavaScript Call
var url = "http://192.168.0.101:9090/api/FGame/updateScore/";
var client = new XMLHttpRequest();
client.open('POST', url, true);
client.send(null);
client.onreadystatechange = function() {
alert(client.status);
alert(client.data)
};
In my scenario I am using an angular front-end Api to collect the data from a form object and a Java rest Api to write the data to a MySql database. But I was always having the "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource." error in the browser console. None of the suggested header modifications in the frontend like;
const headers: {
'Access-Control-Allow-Origin' : '*',
};
worked for me.
After hours of research in the internet one of my friends showed me the answer in not in the frontend but in the backend. Adding a WebConfig class to my java code fixed my problem.
#EnableWebMvc
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000/", "http://localhost:4200/")
.allowedMethods("*")
.allowedHeaders("*");
}
}
Hope this finds those who is looking for an answer to the same error.
I have application where I getting code from stash raw file. Scrapping from public repositories is simple, it looks like this:
public getRawFile(rawLink: string) {
return this.http.get(rawLink).map((res: Response) => res.text());
}
But now I would like to get code from stash raw file, but from private repository. If user have access(is logged into stash) than source code from raw file is loaded.
If I trying same way, I getting respone:
XMLHttpRequest cannot load 'private_stash_file_link'. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.
EXCEPTION: Response with status: 0 for URL: null
Uncaught Response with status: 0 for URL: null
How can I handle this, cookies, specific options for get request, is it even possible?
EDIT 1.
Tried:
public getRawFile(link: string) {
let headers = new Headers();
headers.append('Access-Control-Allow-Headers', 'Content-Type');
headers.append('Access-Control-Allow-Methods', 'GET, OPTIONS');
headers.append('Access-Control-Allow-Origin', '*');
let options = new RequestOptions({headers: headers, withCredentials: true});
return this.http.get(link, options).map((res: Response) => res.text());
}
but same result for private repository..
plunker
The server that you are making the request to has to implement CORS to grant JavaScript from your website access (Cross Origin Resource Sharing (CORS)). So if you have access to the place where you are scraping, then add the following HTTP headers at the response of the receiving end:
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *.example.com
Make sure to replace "*.example.com" with the domain name of the host that is sending the data/getting the data. Doing this should fix your problem.
Following is the request i used so far
$http.get(url)
.success(function (data){})
.error(function (data){})
works without any CORS issues. My server side Allows all origins, methods, all headers
when i add http header like
$http.get(url, { headers: { "USERID": user, "SESSIONID": sessionId}})
the request changes into OPTIONS method when i see in chrome dev tools network tab
What is the reason for this? if it is expected then how to add custom http headers.
I have gone thru this link angularjs-performs-an-options-http-request-for-a-cross-origin-resource but it didnt help
Here i am expecting that server should allow different origins . But it is allowing headers, only if i were in a same server. But not sure about this is by angular or by server side.
after headers
$http.get(url,{ headers: { "USERID": user, "SESSIONID": sessionId } })
in chrome dev tools i am seeing like
Request Method:OPTIONS
Status Code:404 Not Found
but without headers
Request Method:GET
Status Code:200 OK
When i do this in REST Client, i can send headers to the backend.
$http({method: 'GET', url: '/someUrl', headers: { "USERID": user, "SESSIONID": sessionId}}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
will work.
$http.get is a shortcut method.
Check the config in the docs
This is a known bug, see for instance https://github.com/angular/angular.js/issues/1585 .
A workaround is to use a jQuery request.
I had the same massive issue when trying to pass header in my get, where it changes get to options and wouldn't work. In order to make it work I added the following in my php api
<?php if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) && $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'GET') {
header("Access-Control-Allow-Headers: Authorization, X-Auth-Token");
}
exit;
} ?>
You can allow for any headers that you wish to pass.
Hope this helps
For my particular problem with my C# Web API solution I had to have something handle the Options request. Angular was sending a preflight request method OPTIONS which I did allow in my web.config with
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS, PATCH" />
But that wasn't enough I also included a method to handle the Options Request and I returned nothing
[ResponseType( typeof( void ) )]
public IHttpActionResult OptionsPost() {
return StatusCode( HttpStatusCode.NoContent );
}