I am trying to create an angularjs application as a cbssports plugin.
They provide a RESTful API.
The following is my $http request:
$http.get(basePath + 'league/owners?access_token=' + cbssportsTokens['access_token'] + '&response_format=JSON')
.success(function(data) {
return data;
});
That is wrapped up in a factory and used in a controller. As far as I can tell this is getting executed correctly. When I look at the chrome developer tools I can see the following error on my request from the console:
OPTIONS http://api.cbssports.com/fantasy/league/owners?access_token=U2FsdGVkX18Hyd0…J9DrpO7C-OXQQNXGMh0ej0iXVfPf5DkQwkLwSpCqGhipd6HogV_gZ&response_format=JSON angular.js:8560
(anonymous function) angular.js:8560
sendReq angular.js:8354
$http.serverRequest angular.js:8087
wrappedCallback angular.js:11572
wrappedCallback angular.js:11572
(anonymous function) angular.js:11658
Scope.$eval angular.js:12701
Scope.$digest angular.js:12513
Scope.$apply angular.js:12805
done angular.js:8378
completeRequest angular.js:8592
xhr.onreadystatechange
XMLHttpRequest cannot load http://api.cbssports.com/fantasy/league/owners?access_token=U2FsdGVkX18xBod…oQWvjDVSbpZCOVsoIKeVXKRSYdo6dBbIE0rgMWTkWhmgPUTyr_xnS&response_format=JSON. The 'Access-Control-Allow-Origin' header has a value 'https://www.cbssports.com' that is not equal to the supplied origin. Origin 'http://xx.xx.xx.xx:9001' is therefore not allowed access. ?access_token=U2FsdGVkX18xBodWEOfeqys5X4aDpghYrE22FGljlJd_TtKRHlWh4LHWFwVxay95BbAWvn4te1foQWvjDVSbp…:1
When I click the link that it said it couldn't load, it takes me to a new page with the expected output!! So clearly CORS shouldn't be an issue here from the server.
I have read many different issues with CORS about changing the headers. The follow is how I have set it up:
$httpProvider.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
$httpProvider.defaults.headers.common['Access-Control-Allow-Headers'] = 'Origin';
Any advice would be greatly appreciated, also my first post to SO, so please let me know if more info would help.
So I didn't exactly get it to work. But I found a sort of workaround.
function _get(url) {
return $resource(basePath + url, {
access_token: cbssportsTokens['access_token'],
response_format: 'JSON',
callback: 'JSON_CALLBACK'
}, {
get: {
method: 'JSONP'
}
});
}
I went ahead and used a JSONP request instead of a GET, the cbs server seems to be happier with that.
Related
I have the following code which worked 6 days ago:
function showProduct(barcode) {
let url = "https://api.barcodelookup.com/v2/products?barcode=" + barcode + "&key=mj1pm32ylcctxj1byaiaxxxxxxxxxx";
const options = { method: 'GET' };
fetch(url, options)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
setTimeout(function(){
if (myJson == undefined)
{
console.log("fetch failed")
}
else
{
//inspect the data that the WebAPI returned
console.log("myJson: ", myJson);
console.log(myJson.products[0].barcode_formats);
Quagga.stop();
}
}, 3000);
});
}
and the value being passed into the function is 5000159459228. When I executed this code last week, I was receiving a response back from the API and I was able to pick up the individual fields being returned.
Today, I started debugging a different feature of my app and now I receive this error when executing the above listed code:
Failed to load https://api.barcodelookup.com/v2/products?barcode=5000159459228&key=mj1pm32ylcctxj1byaiaxxxxxxxxxx: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
followed by this error:
Uncaught (in promise) TypeError: Failed to fetch
and then this:
newscan:91 Cross-Origin Read Blocking (CORB) blocked cross-origin response https://api.barcodelookup.com/v2/products?barcode=5000159459228&key=mj1pm32ylcctxj1byaiaxxxxxxxxxx with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
If I manually paste the string that I build into the url variable into a browser, I do get a valid response back.
Any suggestions?
Jonathan what you have there is a cors problem. A quick way to solve that if you are using express in your backend is just add CORS module with npm i --save cors and then use it as a middleware:
const cors = require('cors');
app.use(cors());
You can always add the headers yourself. Take a deepr look at Enable CORS.org
Your question was also answered here: [No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API
When I do a POST request using my angular app to my laravel api I get an error bad request 400 , however GET requests work normally, also I do POST requests using POSTMAN and it works , here is my code :
$http.get('http://localhost/laravel/datingApp/jobapi/public/api/user/users');
this get request works, this post request doesn't (data is an js object {'email': 'value','password': 'value'}) :
$http({
url: 'http://localhost/laravel/datingApp/jobapi/public/api/user/login',
method: 'POST',
contentType: "application/json",
data: data
}).success(function(data) {
console.log(data);
});
also I tried doing that just regular way: $http.post('blabla'); but it doesn't work either :(
edit: sorry didn't include error:
angular.js:12011 POST
http://localhost/laravel/datingApp/jobapi/public/api/user/login 400 (Bad Request)
(anonymous function) # angular.js:12011
sendReq # angular.js:11776
serverRequest # angular.js:11571
processQueue # angular.js:16383
(anonymous function) # angular.js:16399
$eval # angular.js:17682
$digest # angular.js:17495
$apply # angular.js:17790
(anonymous function) # angular.js:25890
dispatch # jquery.min.js:3
q.handle # jquery.min.js:3
That was a stupid error, but thanks to #piscator I have found it, Laravel by default returns 400 when validation rules are not met , So my input was wrong all the time that is the reason I got 400.
If the post request is working via postman, it seems that when your angular app does an post request it gets stuck due to browser CORS policy.
You need to have a access-control-allow-origin present in the header of the response for the post requests to works.
The code I am using is:
var frisby = require('frisby');
frisby.create('Get paf data')
.get('https://services.....')
.expectStatus(200)
.expectHeaderContains('content-type', 'application/json')
.toss();
The error I get while running it from CLI using
jasmine-node EndpointTest_spec.js
The error I get is:
Error: Expected 500 to equal 200
Error: Header 'content-type' not present in HTTP response
So do I need to first load my website and call services through my application and then run frisby ?
But then it defeats the purpose of just making a quick check for all the endpoints used in application without running it.
You are calling request with https:// which may be secure server so use
{ strictSSL: false} in your get method .get('https://services.....',{ strictSSL: false}). It will solve your problem.
var frisby = require('frisby');
frisby.create('Get paf data')
.get('https://services.....',{ strictSSL: false})
.expectStatus(200)
.expectHeaderContains('content-type', 'application/json')
.toss();
How to post JSON data to web-service via AngularJS
here is the code snippet
.controller('MessagePostCtrl', function($scope, $http) {
$scope.postMessage = function() {
var msg = document.getElementById('message').value;
var msgdata = {
message : msg
};
var res = $http.post('http://<domain-name>/messenger/api/posts/savePost',msgdata);
res.success(function(data, status, headers, config) {
console.log(data);
});
}
})
OPTIONS http:///messenger/api/posts/savePost
ionic.bundle.js:16185(anonymous function) ionic.bundle.js:16185
sendReq ionic.bundle.js:15979 serverRequest ionic.bundle.js:15712
wrappedCallback ionic.bundle.js:19197 wrappedCallback
ionic.bundle.js:19197(anonymous function) ionic.bundle.js:19283
Scope.$eval ionic.bundle.js:20326 Scope.$digest ionic.bundle.js:20138
Scope.$apply ionic.bundle.js:20430(anonymous function)
ionic.bundle.js:43025(anonymous function) ionic.bundle.js:10478
forEach ionic.bundle.js:7950 eventHandler ionic.bundle.js:10477
triggerMouseEvent ionic.bundle.js:2648 tapClick ionic.bundle.js:2637
tapMouseUp ionic.bundle.js:2707
XMLHttpRequest cannot load
http:///messenger/api/posts/savePost. Invalid HTTP
status code 404
But when I remove the msgdata from $http.post method, everything is working fine.
Can anyone tell me where the issue is or else guide me how to send JSON data to web-service
Thanks for the help
**Edited:
The Issue was with the CORS, Im using codeigniter REST Controller for web-services.
Modified the headers. If anyone has the same issue add the below header in the construct
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method");
if ( "OPTIONS" === $_SERVER['REQUEST_METHOD'] ) {
die();
}
Thanks to Linial for the break-through, telling me where the issue is.**
Okay,
You mixed up couple of things:
First as I can see your request has changed from POST to OPTIONS.
Why?
You are performing Cross-site HTTP requests ( CORS ), which means that your WebApp and your backend API are not in the same domain.
What happens live is that the request is being preflighted.
Preflighted request: by Mozilla MDN:
It uses methods other than GET, HEAD or POST. Also, if POST is used
to send request data with a Content-Type other than
application/x-www-form-urlencoded, multipart/form-data, or text/plain,
e.g. if the POST request sends an XML payload to the server using
application/xml or text/xml, then the request is preflighted.
Which means, any request beside GET, HEAD or POST will be change to OPTIONS
AND: Also POST if used to send data with Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain
I now understand, but what to do? I have to make POST request!
You don't have many options, since CORS is defined on the server.
But on the client you could do so (Example):
change the encode type in angular like so:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
OR
Set your server to approve CORS like so:
Access-Control-Allow-Headers: Content-Type \\ This will allow you to set content type header in the client.
Access-Control-Allow-Methods: GET, POST, OPTIONS \\ This will allow you to send GET POST and OPTIONS, which is necessary because of preflighted requests.
Access-Control-Allow-Origin: * \\ This will allow anyone to perform CORS requests.
Good Luck!
In AngularJS, I had the following function, which worked fine:
$http.get( "fruits.json" ).success( $scope.handleLoaded );
Now I would like to change this from a file to a url (that returns json using some sweet Laravel 4):
$http.get( "http://localhost/fruitapp/fruits").success( $scope.handleLoaded );
The error I get is:
"NetworkError: 405 Method Not Allowed - http://localhost/fruitapp/fruits"
What's the problem? Is it because fruit.json was "local" and localhost is not?
From w3:
10.4.6 405 Method Not Allowed
The method specified in the Request-Line is not allowed for the resource
identified by the Request-URI. The response MUST include an Allow header
containing a list of valid methods for the requested resource.
It means the for the URL: http://localhost/fruitapp/fruits The server is responding that the GET method isn't allowed. Is it a POST or PUT?
The angular js version you are using would be <= 1.2.9.
If Yes, try this.
return $http({
url: 'http://localhost/fruitapp/fruits',
method: "GET",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
I had a similar issue with my SpringBoot project, I was getting the same error in the browser console but I saw a different error message when I looked at the back-end log, It was throwing this error: "org.springframework.web.HttpRequestMethodNotSupportedException, message=Request method 'DELETE' not supported " It turned out that I was missing the {id} parameter in the back-end controller:
** Wrong code :**
#RequestMapping(value="books",method=RequestMethod.DELETE)
public Book delete(#PathVariable long id){
Book deletedBook = bookRepository.findOne(id);
bookRepository.delete(id);
return deletedBook;
}
** Correct code :**
#RequestMapping(value="books/{id}",method=RequestMethod.DELETE)
public Book delete(#PathVariable long id){
Book deletedBook = bookRepository.findOne(id);
bookRepository.delete(id);
return deletedBook;
}
For me, it was the server not being configured for CORS.
Here is how I did it on Azure: CORS enabling on Azure
I hope something similar works with your server, too.
I also found a proposal how to configure CORS on the web.config, but no guarantee: configure CORS in the web.config. In general, there is a preflight request to your server, and if you did a cross-origin request (that is from another url than your server has), you need to allow all origins on your server (Access-Control-Allow-Origin *).