I'm trying to use the forecast API with my angular2 app. However, when i try to access the API I get a Cross-Origin Error. Any idea how i can fix this error ?
search(latitude: any, longitude: any){
console.log(latitude);
console.log(longitude);
let body = 'https://api.forecast.io/forecast/APIKEY/'+latitude+','+longitude ;
console.log(body);
this.http.get(body)
.map(
response => response.json()
).subscribe(
data => console.log("Data: "+data),
err => console.log("Error: "+err),
() => console.log('Get Complete')
);
}
Error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.forecast.io/forecast/APIKEY/37.8267,-122.423. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
Update
Now using JSONP
let body = 'https://api.forecast.io/forecast/APIKEY/'+latitude+','+longitude + '?callback=?' ;
console.log(body);
this.jsonp.get(body)
.map(response => response.json())
.subscribe(
data => console.log("Data: "+data),
err => console.log("Error: "+err),
() => console.log('Get Complete')
);
Error
Error0.def29191127bbc3e0100.hot-update.js:59:10
Object { _body: "JSONP injected script did not invok…", status: 200, ok: true, statusText: "Ok", headers: Object, type: 3, url: "https://api.forecast.io/forecast/60…" }0.def29191127bbc3e0100.hot-update.js:61:10
SyntaxError: expected expression, got '==='
For forecast.io, you should use JSONP. The easiest way to do this using jQuery is adding ?callback=? to request URL:
$.getJSON('https://api.forecast.io/forecast/<API KEY>/' + latitude + ',' + longitude + "?callback=?", function(data) {
console.log(data);
});
I am no expert on Angular 2 but reading the docs it looks like you need to import the Jsonp and then add a callback. More documentation here -- see the section app/wiki/wikipedia.service.ts.
I think something like the code below will work for you
let body = "https://api.forecast.io/forecast/<API KEY>/' + latitude + ',' + longitude + '?callback=?'";
return this.jsonp
.get(body)
.map(response => <string[]> response.json()[1]);
Check out the cors bits on angular.io
https://angular.io/docs/ts/latest/guide/server-communication.html#!#cors
Something like the below (from above)
return this.jsonp
.get(wikiUrl, { search: params })
.map(response => <string[]> response.json()[1]);
You are getting this problem because the header you are sending does not match the headers in the backend.
Suppose you send the following headers:
contentHeaders = new Headers();
contentHeaders.append('Authorization', 'Your token used in app');
contentHeaders.append('Content-Type', 'application/json');
contentHeaders.append('Access-Control-Allow-Origin', '*');
So those headers like Authorization, Content-type, and Access-Control-Allow-Origin should match the allowed headers in your backend.
So in the backend Access-Control-Allow-Headers should have all above headers:
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Authorization, content-type, Access-Control-Allow-Origin");
So here in Access-Control-Allow-Headers you have to pass all headers which you send from frontend: 'Authorization', 'Content-type', and 'Access-Control-Allow-Origin'.
It will work perfectly when you use above concept.
Hope this post will helpful for you
Thanks
Related
My API has following CORS setup:
(I am the owner, I can change these settings)
Middleware function:
// HeaderMiddleware ...
func HeaderMiddleware(next httprouter.Handle) httprouter.Handle {
return httprouter.Handle(func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-APIKEY")
// ! Production
// if r.Header.Get("X-APIKEY") != "fdfdsf5df6d541cd6" || r.RemoteAddr != frontendURL {
// w.WriteHeader(http.StatusForbidden)
// json.NewEncoder(w).Encode(NoContentResponse{Success: false, Error: "You aren't allowed to request the api here."})
// return
// }
// ! Production
next(w, r, p)
})
}
The X-APIKEY header is not necessary yet, a request without it just works fine:
fetch('http://localhost:8013/tobi#gmx.at/usage', { headers: { } })
.then(response => response.json())
.then(console.log)
returns {used: false} (expected response)
However, if I add the X-APIKEY header:
fetch('http://localhost:8013/tobi#gmx.at/usage', { headers: { 'X-APIKEY': 'sdfsdfsafsf' } })
.then(response => response.json())
.then(console.log)
following error is thrown:
Access to fetch at 'http://localhost:8013/tobiwibu#gmx.at/usage' from origin 'http://localhost:8080' 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 an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
If I do the request with the X-APIKEY header in Postman, it says that the Access-Control-Allow-Origin header is sent along:
P.S.: I already tried other headers, it works!
If I do the request with chrome (without X-APIKEY header), the Access-Control-Allow-Origin header is sent.
Thanks for your help!
I've now fixed it like this:
I misuse the http Accept header for my API-Token.
Example:
fetch('http://10.0.0.11:8013/lopm#htl/usage',
{"headers":{ "Accept": "fdfdsf5df6d541cd6++" }})
.then(response => response.json())
.then(console.log)
Of course, this isn't a really nice solution, but it does its job.
Thanks for all of you for giving me helpful tips!
I have set up my CORS policy using Django-cors-headers with the following settings:
APPEND_SLASH=False
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
'localhost:8000',
'localhost:3000',
'localhost'
)
I have also added it to installed_apps and middleware.
Now I am making a React app for the front end and using AXIOS for my API requests. When I make an API request to log in to my app the CORS policy allows it. But, if I make an API request that requires a Token, I get:
Access to XMLHttpRequest at 'localhost:8000/api/TestConnection/' from origin 'http://localhost:3000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
It seems that I need to allow XMLHttpRequest for supported protocol schemes but I cannot find anything in the pypi documentation about this.
EDIT:
Here is the AXIOS Request:
axios.post("localhost:8000/api/TestConnection/",
{headers:
{
'Authorization': "Bearer " + localStorage.getItem('JWTAccess')
}
},
{
testString: 'Hello API'
})
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error);
})
Thank you!
I Have had a similar issue with a ReactNative app which was happening due to ReactNative using IP 10.0.2.2 for localhost (I do not remember the details or why). I solved it by adding to my class.
componentWillMount() {
axios.defaults.baseURL = 'http://10.0.2.2:8000/api/';
axios.defaults.timeout = 1500;
}
I do not know if this is the right IP but may be worth looking at.
EDIT
handleRequest() {
const payload = { username: this.state.username, password: this.state.password }
axios
.post('login/', payload)
.then(response => {
const { token, user } = response.data;
// We set the returned token as the default authorization header
axios.defaults.headers.common.Authorization = `Token ${token}`;
// Navigate to the home screen
Actions.main();
})
.catch(error => {
console.log(error)
});
}
By saving the Token within my headers it is always sent.
The error says "from origin 'http://localhost:3000'" and to "check the cors policy"
I see your CORS policy is
CORS_ORIGIN_WHITELIST = (
'localhost:8000',
'localhost:3000',
'localhost'
)
maybe try providing the full http url. so
CORS_ORIGIN_WHITELIST = (
'localhost:8000',
'http://localhost:3000',
'localhost'
)
I solved it! The solution was very simple(of course),
For the request I needed to use part of #HenryM 's solution.
First I needed to establish the default url:
axios.defaults.baseURL = 'http://127.0.0.1:8000/api/';
Then I save the payload and header to const variables:
const header = {
headers:{
'Authorization': "Bearer " + localStorage.getItem('JWTAccess')
}
}
const payload = {
testValue: "Hello API"
}
Finally, the main issue was that my parameters were in the wrong order:
axios.post("TestConnection/", payload, header)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error);
Apparently the propper order, at least when using Django Rest Framework, is payload then header!!!
Thank you to everyone who tired to help!
This was the article that ended up helping me: https://www.techiediaries.com/django-vuejs-api-views/
I get problems when using angularjs $http in a CORS request, my success function authenticateSuccess(data, status, headers) get wrong headers. As we know, every CORS request will be twice in angularjs, I get twice response from server, the first time is the cors validation information, the second is needed response, but my success function get the headers in the first response. But it's data is from second response.
function login(credentials) {
var data = {
username: credentials.username,
password: credentials.password,
rememberMe: credentials.rememberMe
};
console.log(data);
return $http.post('//localhost:8080/api/authenticate', data).success(authenticateSuccess);
function authenticateSuccess(data, status, headers) {
console.log(headers());
console.log(data);
var bearerToken = headers('Authorization');
if (angular.isDefined(bearerToken) && bearerToken.slice(0, 7) === 'Bearer ') {
var jwt = bearerToken.slice(7, bearerToken.length);
service.storeAuthenticationToken(jwt, credentials.rememberMe);
return jwt;
}
}
}
You are getting this problem as header which you are sending is not matched with the headers in backend
So let suppose In frontend you sending headers
contentHeaders = new Headers(); contentHeaders.append('Authorization', 'your token'); contentHeaders.append('Content-Type', 'application/json'); contentHeaders.append('Access-Control-Allow-Origin', '*');
So those headers like 'Authorization','Content-type', 'Access-Control-Allow-Origin' should matched with your header allow in backend.
So in backend 'Access-Control-Allow-Headers' should have all above headers see below
res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Authorization,content-type,Access-Control-Allow-Origin");
So here in Access-Control-Allow-Headers you have to passed all headers which you send from frontend : 'Authorization','Content-type', 'Access-Control-Allow-Origin'.
It will work perfectly when you use above concept.
Thanks
I'm invoking an authentication service via javascript fetch to get an access token. The service is a simple RESTful call. I can see the call is successful using fiddler (with a 200 response and json data). However the fetch response never seems to get invoked. Below is a snippet:
const AUTHBODY = `grant_type=password&username=${username}&password=${password}&scope=roles offline_access profile`
const AUTHHEADER = new Headers({'Content-Type': 'application/x-www-form-urlencoded'})
const CONFIG = {
method: 'POST',
headers: AUTHHEADER,
body: AUTHBODY
}
fetch('http://localhost:23461/connect/token', CONFIG).then(function(response) {
console.log('response = ' + response)
return response.json()
}).then(function(json) {
console.log('json data = ' + json)
return json
}).catch(function(error) {
console.log('error = ' + error)
})
When executing the fetch above none of the console.logs gets executed... seems to just hang. But fiddler tells otherwise. Any ideas?
You probably met with the CORS origin policy problem. To tackle this you need some rights to access the server side of your API. In particular, you need to add a line in the header of php or another server endpoint:
<?php
header('Access-Control-Allow-Origin: *');
//or
header('Access-Control-Allow-Origin: http://example.com');
// Reading JSON POST using PHP
$json = file_get_contents('php://input');
$jsonObj = json_decode($json);
// Use $jsonObj
print_r($jsonObj->message);
...
// End php
?>
Also, make sure NOT to have in the header of your server endpoint:
header("Access-Control-Allow-Credentials" : true);
Model of working fetch code with POST request is:
const data = {
message: 'We send a message to the backend with fetch()'
};
const endpoint = 'http://example.com/php/phpGetPost.php';
fetch(endpoint, {
method: 'POST',
body: JSON.stringify(data)
})
.then((resp) => resp.json())
.then(function(response) {
console.info('fetch()', response);
return response;
});
I am trying to make an HTTP POST request with Angular 2 as below.
saveUserSelection() {
var json = JSON.stringify({access_token: localStorage.getItem('access_token')});
var params = 'json=' + json;
var headers = new Headers();
headers.append({ 'Content-Type': 'application/json' });
return this.http
.post('http://localhost:8080/user/selection', params, { headers: headers })
.map(res => res.json());
}
But I am getting an error as below.
angular2.dev.js:23877 EXCEPTION: Error during evaluation of "ngSubmit"
ORIGINAL EXCEPTION: SyntaxError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': '[object Object]' is not a valid HTTP header field name.
Does anyone have an idea what's wrong with my code? And how can I create a HTTP POST request with parsing body type parameter?
This should do what you want:
headers.append('Content-Type', 'application/json' );
headers.append('access_token', localStorage.getItem('access_token'));