I'm deploying and angular 6 application that works with a tomcat server in localhost, when I try to execure this http request
this.http
.post<LoginResult>( API_URL + '/login', JSON.stringify(json)/*, { headers: myHeader }*/).pipe(
catchError(this.handleError('get-token', []))).subscribe((response) => {
if(response['result_code'] == 'result_ok') {
this.auth.doSignIn(response['token'], response['name']);
this.router.navigate(['user_manager']);
return true;
}else {
return false;
}
});
everitying works well, but when I add header field
let myHeader = new HttpHeaders().append("Authorization", 'Basic' + this.session.getAccessToken());
this.http
.post<LoginResult>( API_URL + '/login', JSON.stringify(json), { headers: myHeader }).pipe(
catchError(this.handleError('get-token', []))).subscribe((response) => {
if(response['result_code'] == 'result_ok') {
this.auth.doSignIn(response['token'], response['name']);
this.router.navigate(['user_manager']);
return true;
}else {
return false;
}
});
this is my output error:
Access to XMLHttpRequest at 'http://localhost:8095/login' 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.
HttpErrorResponse
I checked also that the request doesn't arrive to my tomcat server, it is blocked before, that oesn't allow angular to check response headers
Thank you for your help
I'm providing you a generic answer as you have not mention that your server side code is written in which language. You should provide a header from your server code. Provide Access-Control-Allow-Origin header with value as localhost:4200 which will resolve your issue. Or if you want to allow every origin then change its value from localhost:4200 to *.
After reading all the comments I have change something for you.
change your this code let myHeader = new HttpHeaders().append("Authorization", 'Basic' + this.session.getAccessToken()); with const myHeader = new HttpHeaders({'Authorization': 'Bearer ' + localStorage.getItem('api_token')});
and make your post request as
this.http
.post<LoginResult>( API_URL + '/login', json, myHeader).pipe(
catchError(this.handleError('get-token', []))).subscribe((response) => {
if(response['result_code'] == 'result_ok') {
this.auth.doSignIn(response['token'], response['name']);
this.router.navigate(['user_manager']);
return true;
}else {
return false;
}
});
You need to configure CORS on your tomcat server.
You need to tell tomcat which headers the application is allowed to send, so it can include it in the preflight response:
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Authorization,Content-Type,...</param-value>
</init-param>
Take a look at
cors.allowed.methods under CORS Filter section here:
https://tomcat.apache.org/tomcat-7.0-doc/config/filter.html
Related
vanilla JS here, trying to use fetch to delete a resource via an api - getting the following error: "Invalid request method DELETE" - I'm able to Postman / curl the same endpoint without any problems and the status code upon completion is 204 in those cases. Any idea what I'm doing wrong here?
function btnTrash(e) {
var uuid = this.parentNode.parentNode.parentNode.id
var url = "http://10.10.10.10:8080/api/v1/delete/" + uuid
fetch(url, {
method: 'DELETE',
mode: 'no-cors'
});
}
Edit: Managed to solve this - I wasn't setting the allowed methods on the backend "Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE") and finally removing mode: no-cors.
Keeping in mind that removing mode: no-cors only works because I'm setting the access-control-allow-origin to "*" on the response.
function btnTrash(e) {
var uuid = this.parentNode.parentNode.parentNode.id
var url = "http://192.168.0.16:8080/api/v1/delete/" + uuid
fetch(url, {
method: 'DELETE',
})
.then(response => {
if (response.status == 204){
// do something
}
})
}
I am trying to send authorized Firebase requests to HTTP Cloud Functions following the official documentation.
However, I keep getting the error message:
Access to XMLHttpRequest at '[CLOUD-FUNCTION-SOURCE-URL]' from origin
'http://127.0.0.1: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.
I tried the following:
def cors_enabled_function_auth(request):
# For more information about CORS and CORS preflight requests, see
# https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
# for more information.
# Set CORS headers for preflight requests
if request.method == 'OPTIONS':
# Allows POST requests from origin * Authorization header
headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Headers': ['Authorization', 'Content-Type'] ,
'Access-Control-Max-Age': '3600',
'Access-Control-Allow-Credentials': 'true'
}
return ('', 204, headers)
# Set CORS headers for main requests
headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true'
}
print('core logic here')
return ('Hello World!', 200, headers)
On the front (using AngularJS) I make a request as follows:
self.getDownloadUrl = function(gcs_reference) {
var url = '[CLOUD-FUNCTION-URL]';
var params = {'param1': 'hello'};
var headers = {
'Content-Type': 'application/json'
}
return firebase.auth().onAuthStateChanged().then(
function (user) {
headers['Authorization'] = user['refreshToken']
return postRequestHTTP(params, url, headers)
},
function (error) {
console.log('error', error)
return error;
}
)
};
function postRequestHTTP(params, url, headers) {
// Generic HTTP post request to an url with parameters
var q = $q.defer();
var body = params;
var req = {
headers: headers
};
$http.post(url, body, req).then(
function(response) {
q.resolve(response)
}, function(error) {
q.reject(error)
}
);
return q.promise;
}
Does anyone know what is the cause of this heresy?
I can't reproduce this. With your function and a request like:
function reqListener () {
console.log(this.responseText);
}
xhr = new XMLHttpRequest();
xhr.open('POST', "[CLOUD-FUNCTION-URL]");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.addEventListener("load", reqListener);
xhr.send('test');
I get a successful request. Perhaps the latest version of your function is not actually deployed, or your frontend is pointing at a different endpoint?
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