POST call to Add place to Google Maps fails on preflight - google-places-api

I'm trying to add custom places to Google Maps, and for that I try to send a POST request using this code:
httpPostAsync('https://maps.googleapis.com/maps/api/place/add/json?key=<MY_KEY>',
{
location: {
"lat": 32.12345,
"lng": 32.12345
},
"accuracy": 50,
"name": "Test123"
},
function(response) {
console.log(response);
});
function httpPostAsync(theUrl, params, callback)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(xmlHttp.responseText);
}
xmlHttp.open("POST", theUrl, true); // true for asynchronous
//Send the proper header information along with the request
xmlHttp.setRequestHeader("Content-type", "application/json");
xmlHttp.setRequestHeader("Host", "maps.googleapis.com");
xmlHttp.send(JSON.stringify(params));
}
I run it from my site, lets say the address is https://www.example.com/maps.html.
I have an API key that has key restrictions from www.example.com/*.
Whenever I run this code, I receive this error:
XMLHttpRequest cannot load https://maps.googleapis.com/maps/api/place/add/json?key=<MY_KEY>. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://www.example.com' is therefore not allowed access. The response had HTTP status code 400.
Any ideas what may be the problem?

Related

Access to fetch at '' from origin '' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

I have this api (method get) that is connected to a lambda function that does a simple select from a database, if i test the endpoint with postman with a null body it does work (if i understood, postman is not under the same CORS policy), as well as typing the endpoint on the browser.
But when i try to do a fetch from a simple js, i get the error :
Access to fetch at '...' from origin 'http://localhost' has been blocked by CORS policy: 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.
I enabled CORS in API Gateway, both with the Enable CORS option
and with the Enable API Gateway CORS when creating a new resource
If i test my endpoint with gateway, i also get that Allow-content-allow-origin : * is in my response header :
What should i do to fix this problem?
here is the JS fetch :
console.log("pre fetch");
Show();
console.log("post fetch");
function Show(){
fetch("...").then(onResponse);//.then(onJson);
}
function onResponse(response){
console.log(response);
return response.json();
}
I removed the onJson to avoid confusion, but even with that in its the same problem.
Try to include that in your function too, like this,
I hope this would work:
const headers = {'Content-Type':'application/json',
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods':'POST,PATCH,OPTIONS'}
const response = {
statusCode: 200,
headers:headers,
body: JSON.stringify(X),
};
return response;
Here X is the response that you want to return.
If you are using Node.js you needs to install cors.
npm install cors.
After installing cors, include it in the page where you are using fetch function as shown below;
const cors = require('cors');
app.use(cors());
and the error will be solved.
I made a video on how to fix this.
You need to go into the Lambda function and add special code:
original (does NOT work):
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
new one, that works:
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
You can find this solution in here: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html
Only you need to replace the:
"Access-Control-Allow-Origin": "https://www.example.com",
with
"Access-Control-Allow-Origin": "*",
Special thanks to user, KnowledgeGainer
ALSO, you need to enable CORS on Gateway API side, just follow instruction from here: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html

Cross Origin Put Request Methods

What are some successful methods for performing Cross Origin Put requests? I successfully used a Proxy to make a GET request and put it into a Dropdown list as can be seen here >> Create Dropdown list from API Query >>but have not been able to use the same process in making a PUT Request?
Thoughts?
I was able to successfully get a PUT request to work just peachy through the use of the proxy in javascript.
$.ajaxPrefilter( function (options) {
if (options.crossDomain && jQuery.support.cors) {
var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
//options.url = "http://cors.corsproxy.io/url=" + options.url;
}
});
Once the Proxy was established, I used the chrome extension (now a desktop app) Postman to get the PUT HTML code. This was done by first getting the PUT request to work in Postman and then selecting the "code" link (below the "send" button) and selecting "JavaScript Jquery AJAX" from the drop-down. Here is an example of outputted code from Postman.
var settings = {
"async": true,
"crossDomain": true,
"url": "https://[apiurl].com",
"method": "PUT",
"headers": {
"content-type": "text/xml",
"cache-control": "no-cache",
"postman-token": "[token]"
},
"data": "<this_is_the_xml_data_youre_sending>"
}
$.ajax(settings).done(function (response) {
console.log(response);
});
Once the code is copied from Postman, put the proxy code and Postman javascript into an HTML page and watch the PUT request happen.

Response headers in Angular interceptor

I have an interceptor for authentication.
I want to get a header out of the response when I get a 401 response error.
Interceptor is:
function ($httpProvider, fileUploadProvider) {
$httpProvider.interceptors.push(function($q, $localStorage) {
return {
'request': function(config) {
if ($localStorage.token) {
config.headers.Authorization = 'Bearer ' + $localStorage.token;
}
return config;
},
'responseError': function(response) {
if (response.status === 401) {
//$rootScope.$broadcast('unauthorized');
// WWW-Authenticate: Bearer error="invalid_token"
var authResult = response.headers('WWW-Authenticate');
if (authResult.indexOf("invalid_token")>-1) {
$localStorage.token = null;
$timeout(function(){
;
});
}
}
return response;
}
};
I want to get the WWW-Authenticate header from the response.
I can confirm the header is in the response of the web service call by looking at the network tab in Chrome developers tools. If I set a break point in the response handler function and then run console.log(response.headers()) in the console I get:
Object {}
undefined
How do I get to the response headers?
The responseError function receives rejection instead of response.
Therefore if you want to access response headers, what you need is like below.
'responseError': function(rejection) {
if (rejection.status === 401) {
console.log(rejection.config.headers);
}
}
I hope this would help you. :)
Although I know this is not answer and should post as comment, I post it here to use screen capture image.
I tried to get a response header with my test enviroment like below.
nodejs server
res.setHeader('WWW-Authenticate', 'invalid_token');
res.status(401).send();
angularjs
'responseError': function(rejection) {
if (rejection.status === 401) {
console.log(rejection.headers('WWW-Authenticate'));
}
}
Chrome dev tool screen capture
As you can see, I could get the response header correctly.
Therefore I think that there seems to be some problem in your server code where you set a response header.
Would you like to show us your chrome dev tool screen capture and your server code where you set the response header?

IE striping headers from HTTP POST request to S3

I'm doing straight-to-S3 multipart file upload via AJAX. Everything works fine under all browsers but IE.
S3 requires an Authorization HTTP header in each POST request which contains the signature of the file slice being uploaded.
It appears IE strips out this header from the request, yielding a 403 response.
What's more funny is that IE does not strip another custom S3 header: x-amz-date.
Any idea how I can force the 'Authorization' header in?
As requested, here is my code :
initiateUpload: function() {
var response = this.sign({method:'POST', path: this.key + '?uploads'});
this.request({
method: 'POST',
url: response.url,
headers: {
'x-amz-date': response.date,
'Authorization': response.signature
},
onLoad: this.uploadParts.bind(this)
});
},
request: function(params){
var xhr = new XMLHttpRequest();
if (params.onLoad) xhr.addEventListener("load", params.onLoad, false);
if (params.onUploadStart) xhr.upload.onloadstart = params.onUploadStart;
if (params.onUploadProgress) xhr.upload.onprogress = params.onUploadProgress;
xhr.open(params.method, params.url, true);
for (h in params.headers)
xhr.setRequestHeader(h, params.headers[h]);
xhr.send(params.body);
},

ajax from Chrome-Extension processed, but receive responseText="" and status=0

I am writing a google-chrome extension, that needs to make ajax requests to a server, send some data, and receive some data back. My server is Tomcat 6.0, running on localhost.
I am able to receive all the data on the server side, do all the processing I need, and send a response back to the extension,
but the status i get in the callback is 0, and responseText="".
my guess is that the problem lies either in the server - returning a response to a request originating from chrome-extension://... url, or in the extension - receiving a response from localhost:8080.
I've set the necessary permissions of course, and I tried setting content-type of the response to "text/xml", "text/html" and "text/plain" - it makes no difference.
I've tried using ajax both with XMLHttpRequest and JQuery - same problem with both.
I've found these issues, but they don't seem to solve my problem:
1. http://www.plee.me/blog/2009/08/ajax-with-chrome-empty-responsetext/
2. http://bugs.jquery.com/ticket/7653
here's my code:
bg.js (background page)
function saveText(data) {
var requrl = serverUrl + addTextUrl;
var params = json2urlParams(data);
jQuery.ajax({
type : "POST",
url : requrl,
data : params,
success : function (data, textStatus, XMLHttpRequest) {
console.log("Data Saved: " + msg);
}
});
// var xhr = new XMLHttpRequest();
// xhr.open("POST", requrl, true);
// xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// xhr.onreadystatechange = function (progress) {
// if (xhr.readyState == 4) {
// console.log("Data Saved: " + this.response);
// }
// };
// xhr.send(params);
}
addContentServlet.java: (server side)
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
ErrorCodes error = addContent(request, response);
response.setContentType("text/plain");
//response.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
//response.setIntHeader("errorCode", error.ordinal());
response.getWriter().write(error.toString());
response.setIntHeader("errorcode", error.ordinal());
if(error == ErrorCodes.SUCCESS){
response.setStatus(error.toHttpErrorCode());
response.flushBuffer();
}
else{
response.sendError(error.toHttpErrorCode(), error.toString());
}
}
EDIT:
I've noticed in the chrome console of the background page that for every ajax that returns to the extension i get a
XMLHttpRequest cannot load
http:// localhost:8080/stp_poc/MyServlet.
Origin
chrome-extension://fmmolofppekcdickmdcjflhkbmpdomba
is not allowed by
Access-Control-Allow-Origin.
I tried loosing bg.js and puting all the code in the main page instead - to no avail.
how come XMLHttpRequest agrees to send the request, but not receive it back??
Maybe a server-configuration problem? I'm a newb, so maybe i missed something basic, like a header in the response
EDIT
I've finally pinned the problem:
I shouldn't have included the port number in my permission. Here's the wrong permission I wrote:
"permissions" : [
"http://localhost:8080/"
]
And here's the correct form:
"permissions" : [
"http://localhost/"
]
everything seems to works fine now.
The problem was that I shouldn't have included the port number in my permission.
Here's the wrong permission I wrote:
"permissions" : [
"http://localhost:8080/"
]
And here's the correct form:
"permissions" : [
"http://localhost/"
]

Resources