Error with Fetch request for Google places API [duplicate] - javascript

I really do NOT understand how I'm supposed to make this work:
var requestURL = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw';
console.log(requestURL);
$.getJSON( requestURL, function( data ) {
// data
console.log(data);
});
and my HTML file:
<body>
<script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script src="main.js" charset="utf-8"></script>
</body>
I always get the No 'Access-Control-Allow-Origin' header is present on the requested resource. message... even though if I go to https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw in my browser I get the proper JSON returned.
I am lead to believe that CORS can help me here. I don't understand CORS. Please, can anyone help me in plain simple terms? What should I change to make this work??
Thanks

You are trying to use the Google Places API Web Service on client side whereas it is designed for server side applications. That's probably why appropriate CORS response headers are not set by the server.
As explained in the Notes at the beginning of the Place Details documentation, you should use the Places Library in the Google Maps JavaScript API:
If you're building a client-side application, take a look at the Google Places API for Android, the Google Places API for iOS, and the Places Library in the Google Maps JavaScript API.
Note: you will need to enable the Google Maps JavaScript API in your Google Developer Console first.
Here is a way you can proceed to get place details (based on the example from the documentation):
<head>
<script type="text/javascript">
function logPlaceDetails() {
var service = new google.maps.places.PlacesService(document.getElementById('map'));
service.getDetails({
placeId: 'ChIJN1t_tDeuEmsRUsoyG83frY4'
}, function (place, status) {
console.log('Place details:', place);
});
}
</script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw&libraries=places&callback=logPlaceDetails"></script>
</head>
<body>
<div id="map"></div>
</body>

#rd3n already answered about why to use Google Maps' SDK, but if you really need to use the API instead of SDK on a web app (reuse code, for exemple), you can bypass CORS using proxy parameter from Webpack's DevServer.
const GMAPS_PLACES_AUTOCOMPLETE_URL = (
process.env.NODE_ENV === 'production'
? 'https://maps.googleapis.com/maps/api/place/autocomplete/json'
: 'place-api' // on development, we'll use the Webpack's dev server to redirect the request
const urlParams = new URLSearchParams([
...
])
const response = await fetch(
`${GMAPS_PLACES_AUTOCOMPLETE_URL}?${urlParams}`,
{ method: 'GET' }
)
And on your webpack.config.js...
module.exports = {
devServer: {
proxy: {
'/place-api': {
target: 'https://maps.googleapis.com/maps/api/place/autocomplete/json',
changeOrigin: true,
pathRewrite: { '^/place-api': '' }
}
}
}
}

I know this is an old question, and this might not be a direct answer to this question, but just in case someone could use this trick, I always like to go around this issue using PHP to create my own API, then fetch the newly created API using JavaScript:
1# Create an api.php file:
<?php
$google_URL = 'https://maps.googleapis.com/maps/api/place/details/json';
$api = 'YOUR_GOOGLE_API';
$place = 'PLACE_ID';
$field = [
'user_ratings_total',
'rating'
];
$fields = join(",", $field);
$result_url = $google_URL.'?placeid='.$place.'&fields='.$fields.'&key='.$api;
$result_content = file_get_contents($result_url);
$json_data = json_decode($result_content, true);
if ( isset($json_data) && $json_data['status'] === 'OK' ) {
echo json_encode($json_data['result']);
}else {
echo json_encode($json_data['error_message']);
}
header("content-type: application/json");
2# Create a script.js file:
const url = './api.php';
fetch(url)
.then(res => res.json())
.then(data => console.log(data))
.catch(error => console.log(error))

Using the same url you provided, this is for pure front-end (React), but a less secure solution:
var requestURL = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw';
Cut out the following from url: 'https://maps.googleapis.com/maps/api/place' and create a proxy line in your package.json:
"proxy": "https://maps.googleapis.com/maps/api/place"
Then following google documentations you'll be left with the following code (wherever you're fetching the api):
var axios = require('axios');
var config = {
method: 'get',
url: '/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw', //the rest of your url
secure: false //important
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});

Related

Axios get call in Vue3 not working, although curl and javascript work as expected

I'm trying to make an API call from my Vue3 app. The prepared API has an endpoint like http://localhost:8888/api/dtconfigsearch, where one needs to pass a json payload like { "Modelname": "MyFancyModel"} to get the full dataset with the given modelname. Pure get functions without a payload / a body do work from my Vue3 project to the golang backend, but I'm having problems with passing a payload to the backend.
Test with curl -> ok
$ curl -XGET localhost:8888/api/dtconfigsearch -d '{"Modelname" : "MyFancyModel" }'
{"ID":4,"Modelname":"MyFancyModel","ModelId":"96ee6e80-8d4a-b59a-3524-ced3187ce7144000","OutputTopic":"json/fancyoutput"}
$
This is the expected output.
Test with javascript ok
Source file index.js:
const axios = require('axios');
function makeGetRequest() {
axios.get(
'http://localhost:8888/api/dtconfigsearch',
{
data: { Modelname : "MyFancyModel" },
headers: {
'Content-type' : 'application/json'
}
}
)
.then(resp => {
console.log(resp.data)
})
.catch(err => {
console.log(err)
})
}
makeGetRequest()
Output
$ node index.js
{
ID: 4,
Modelname: 'MyFancyModel',
ModelId: '96ee6e80-8d4a-b59a-3524-ced3187ce7144000',
OutputTopic: 'json/fancyoutput'
}
$
Here, I also get the desired output.
Test within Vue fails :-(
Source in the Vue one file component:
onSelection(event) {
let searchPattern = { Modelname : event.target.value }
console.log(event.target.value)
console.log("searchPattern = " + searchPattern)
axios.get("http://localhost:8888/api/dtconfigsearch",
{
data : { Modelname : "Windshield"},
headers: {
'Content-type' : 'application/json',
'Access-Control-Allow-Origin': '*'
}
})
.then(response => {
console.log(response.data)
})
.catch(err => {
console.log(err)
alert("Model with name " + event.target.value + " not found in database")
})
},
Output in browser:
In the image you can see in the terminal log on the right side that the backend is not receiving the body of the API call. However, in the browser information of the call there is content in the config.data part of the object tree, which is the payload / the body. The only thing that bothers me that it is not a json object, but stringified json, although it was entered as json object. According to the documentation, the parameter name (data) in the call should be correct to hold the body content of the api call.
I've tried different header information, looked if it could be a CORS issue, what it isn't to my opinion, exchanged key data with body, used axios instead of axios.get and adapted parameter, all without success. The version of the axios library is 0.27, identical for Vue and vanilla javascript. After checking successfully in javascript, I was sure that it would work the same way in Vue, but it didn't.
Now I'm lost and have no further ideas how to make it work. Maybe someone of you had similar issues and could give me a hint? I'd be very grateful for some tipps!!

How to embed Apache Superset (v1.5) Dashboard in Wordpress?

I'm trying to embed an Apache 1.5 dashboard in a Wordpress site. So far I've succeeded in doing the following:
Upgrade to Apache Superset 1.5 and enable the embedded dashboard functionality
Configure dashboard to be embedded
Implemented backend code to obtain JWT token
What I'm struggling with now is to implement the "#superset-ui/embedded-sdk" functionality in my Wordpress site (using TwentyTwentyOne standard template). I'm trying to follow the instructions listed here: https://fossies.org/dox/apache-superset-1.5.0-source/md_superset_embedded_sdk_README.html
The CDN approach looks the easiest, but I'm getting the error ReferenceError: Buffer is not defined. And if I add the following code:
<script src="https://unpkg.com/buffer"></script>
Then I get the error ReferenceError: require is not defined. I'm not sure how I can resolve this error. Is the CDN approach a dead end, or is there a way I can make this work?
With the "Using npm" approach I'm struggling even more. I'm able to install the npm packages on bitnami linux, but then I don't know how to make use of them in the site. I wasn't able to make it work to add '#superset-ui/embedded-sdk' using wp_enqueue_script(). Also I tried the following code in wordpress:
<script type="module">
import {embedDashboard} from 'http://[MY_IP_ADDRESS]/wp-content/themes/twentytwentyone/node_modules/#superset-ui/embedded-sdk/lib/index.js';
</script>
However then I get the following error:
Uncaught SyntaxError: The requested module 'http://[MY_IP_ADDRESS]/wp-content/themes/twentytwentyone/node_modules/#superset-ui/embedded-sdk/lib/index.js' does not provide an export named 'embedDashboard'
I don't quite understand this error as embedDashboard does appear to be defined in the js file. I also tried using the embedded-sdk/bundle/index.js file with the same result.
I've spent many hours on this and I'm not sure what approach I should take. Can anyone point me in the right direction? Or even better: have a solution to a similar problem with sample code I can look at? If I need to provide more details on what I've tried or what errors I'm seeing let me know.
This is how I did it.
I wrote my backend in Flask.
My Superset Version is 2.0
backend.py
from flask import Flask, render_template, jsonify
import requests
import json
import os
app = Flask(__name__)
#app.route('/')
def hello():
return render_template('index.html')
#app.route("/guest-token", methods=["GET"])
def guest_token():
url = "http://<IP>:<PORT>/api/v1/security/login"
payload = json.dumps({ "password": "<>", "provider": "db", "refresh": "true", "username": "<>" })
headers = { 'Content-Type': 'application/json', 'Accept': 'application/json' }
responsel = requests.request("POST", url, headers=headers, data=payload)
print(responsel.text)
superset_access_token = json.loads(responsel.text)['access_token']
payload = json.dumps ({
"user": {
"username": "kashew",
"first name":"Kashish",
"lastname":"Bakshi"
},
"resources": [{
"type": "dashboard",
"id": "8f96cc84-7e9e-4f5c-ba92-3a1f0825fe3d"
}],
"rls": []
})
bearer_token = "Bearer " + superset_access_token
print(bearer_token)
response2 = requests.post(
"http://<IP>:<PORT>/api/v1/security/guest_token",
data = payload,
headers = { "Authorization": bearer_token, 'Accept': 'application/json', 'Content-Type': 'application/json' })
print(response2.json())
return jsonify(response2.json()['token'])
if __name__ == "__main__":
app.run(debug=True)
Explanation:
The Major part of understanding is the Guest_Token Function.
Here two POST Requests are at play.
The first Request gets the access token from Superset.
The Second request uses the Access Token we got as Bearer and is a POST Call to get the Guest_Token from Superset.
Payload for Guest_Token:
{
"user": {
"username": "kashew",
"first name":"Kashish",
"lastname":"Bakshi"
},
"resources": [{
"type": "dashboard",
"id": "8f96cc84-7e9e-4f5c-ba92-3a1f0825fe3d"
}],
"rls": []
}
Explanation:
The Payload is a JSON with 3 Key-Value Pair.
user (Here, I created a Dummy User{ This can be replaced with your App Auth Logic})
resources (Refer this)
rls (I kept it empty but more can be found here)
I ran my backend on Localhost:5000.
For Frontend, I created a directory "templates" and put my index.html file inside it.
index.html
<html>
<head>
<script src="https://unpkg.com/#superset-ui/embedded-sdk"></script>
<style>
iframe {
width: 100%;
height: 50%;
border: none;
pretext {
margin-right: 10%;
margin-left: 10%;
font-family: Tahoma;
</style>
</head>
<body>
<div class="pretext">
<h2> Covid Statistics </h2>
<p> Dive into Covid data
<p id="dashboard-container"></p>
<script>
async function fetchGuestTokenFromBackend() {
let response = await fetch('http://127.0.0.1:5000/guest-token');
let data = await response.json()
return data
}
const myDashboard = supersetEmbeddedSdk.embedDashboard({
id: "8f96cc84-7e9e-4f5c-ba92-3a1f0825fe3d",
supersetDomain: "http://<IP>:<PORT>",
mountPoint: document.getElementById("dashboard-container"),
fetchGuestToken: () => fetchGuestTokenFromBackend(),
dashboardUiConfig: {
hideTitle: true,
hideChartControls: true
},
});
</script>
</div>
</body>
</html>
Explanation:
It calls my guest-token method which returns a Guest-Token to my frontend. The Frontend then makes a request to Superset Embed Dashboard URL with the guest-token which in turn embeds and renders the chart in an Iframe on my website.
Hello, I hope this example of using 'superset embedded-sdk' will help you:
<!DOCTYPE html>
<head>
...
<script src="https://unpkg.com/#superset-ui/embedded-sdk"></script>
</head>
<body>
<p id="dashboard" width="700" height="700"></p>
<script>
async function getToken() {
const res = await fetch('http://localhost:3000/token');
const data = await res.json()
console.log(data['value']);
return data['value'];
}
supersetEmbeddedSdk.embedDashboard({
id: "7b5ee110-435b-4ad1-a257-97ea340bf82d",
supersetDomain: "http://localhost:8088",
mountPoint: document.getElementById("dashboard"),
fetchGuestToken: () => getToken(),
dashboardUiConfig: {
hideTitle: true,
filters: {
expanded: true
}
}
});
</script>
</body>
</html>

CORS No 'Access-Control-Allow-Origin' error in React app w/ Facebook

I'm a junior developer that's fairly new to using Facebook for Developers. I'm hitting a wall with the ReactJs application I'm building and could use your help!
My boss has requested a Grid representation of the Page Plugin, not the actual Plugin itself. For this project, he's requested I make and use a test 'Page' I've found that DevExtreme's Data Grid seems to be the best option in terms of the desired visual, and I'm trying to call my Facebook Page using the Graph API documentation. I know it's hitting at least the area I want it to with my console.log because it's returning the error message.
Here are the errors my browser is returning:
Access to fetch at 'https://www.facebook.com/Feeds-Tester-170107151801959/' from origin 'https://localhost:3000' 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.
GET https://www.facebook.com/Feeds-Tester-170107151801959/ net::ERR_FAILED
The link you'll see referenced in my URL variable has been triple checked to be the correct link. Since I'm using NodeJS, I tried installing the CORS npm package but I'm not 100% sure where to put it to use it, I'm wondering if that's the cause of the issue?
Here's my full code snippet (I'm using VS Code, if that helps):
/*global FB*/
import React from 'react';
import { DataGrid, Editing, Scrolling, Lookup, Summary, TotalItem } from 'devextreme-react/data-grid';
import { Button } from 'devextreme-react/button';
import { SelectBox } from 'devextreme-react/select-box';
import CustomStore from 'devextreme/data/custom_store';
import { formatDate } from 'devextreme/localization';
import 'whatwg-fetch';
const URL = 'https://www.facebook.com/Feeds-Tester-170107151801959/';
const REFRESH_MODES = ['full', 'reshape', 'repaint'];
class Grid extends React.Component {
constructor(props) {
super(props);
this.state = {
fbData: null,
ordersData: new CustomStore({
key: 'OrderID',
load: () => this.sendRequest(`${URL}`, 'GET'),
}),
requests: [],
refreshMode: 'reshape'
};
this.clearRequests = this.clearRequests.bind(this);
this.handleRefreshModeChange = this.handleRefreshModeChange.bind(this);
var body = 'Reading JS SDK documentation';
FB.api('/me/feed', 'post', { message: body }, function(response) {
if (!response || response.error) {
console.log('Error occured');
} else {
console.log('Post ID: ' + response.id);
}
})
}
sendRequest(url, method, data) {
method = method || 'GET';
data = data || {};
this.logRequest(method, url, data);
if(method === 'GET') {
return fetch(url, {
method: method,
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Access-Control-Allow-Origin': '*'
}
}).then(result => result.json().then(json => {
if(result.ok) return json.data;
throw json.Message;
}));
}
const params = Object.keys(data).map((key) => {
return `${encodeURIComponent(key) }=${ encodeURIComponent(data[key])}`;
}).join('&');
return fetch(url, {
method: method,
body: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
credentials: 'include'
}).then(result => {
if(result.ok) {
return result.text().then(text => text && JSON.parse(text));
} else {
return result.json().then(json => {
throw json.Message;
});
}
});
}
logRequest(method, url, data) {
const args = Object.keys(data || {}).map(function(key) {
return `${key }=${ data[key]}`;
}).join(' ');
const time = formatDate(new Date(), 'HH:mm:ss');
const request = [time, method, url.slice(URL.length), args].join(' ');
this.setState((state) => {
return { requests: [request].concat(state.requests) };
});
}
clearRequests() {
this.setState({ requests: [] });
}
handleRefreshModeChange(e) {
this.setState({ refreshMode: e.value });
}
render() {
const { refreshMode, ordersData } = this.state;
return (
<React.Fragment>
<DataGrid
id="grid"
showBorders={true}
dataSource={ordersData}
repaintChangesOnly={true}
>
<Editing
refreshMode={refreshMode}
mode="cell"
allowAdding={true}
allowDeleting={true}
allowUpdating={true}
/>
<Scrolling
mode="virtual"
/>
<Lookup dataSource={ordersData} valueExpr="Value" displayExpr="Text" />
<Summary>
{/* <TotalItem column="CustomerID" summaryType="count" />
<TotalItem column="Freight" summaryType="sum" valueFormat="#0.00" /> */}
</Summary>
</DataGrid>
<div className="options">
<div className="caption">Options</div>
<div className="option">
<span>Refresh Mode: </span>
<SelectBox
value={refreshMode}
items={REFRESH_MODES}
onValueChanged={this.handleRefreshModeChange}
/>
</div>
<div id="requests">
<div>
<div className="caption">Network Requests</div>
<Button id="clear" text="Clear" onClick={this.clearRequests} />
</div>
<ul>
{this.state.requests.map((request, index) => <li key={index}>{request}</li>)}
</ul>
</div>
</div>
</React.Fragment>
);
}
}
export default Grid;
This is the link to the docs for the module I'm trying to reference
I'm trying to not bite off more than I can chew and just start with retrieving the data before I even think about manipulating it or sending any in return. Any insight or guidance you can provide would be greatly appreciated. Thank you!! :)
Do not use fetch with the Facebook URL, it won't let it happen on the browser, instead, use the Facebook API for everything you need to do with it
For example, instead of fetching the page, use the api with the page
FB.api('/Feeds-Tester-170107151801959', function(response) {
// ...
});
If you need to fetch the page, then you have to do it outside the browser environment or use a proxy like cors anywhere, but you can avoid that by using the Facebook API
I was also getting these error. I found that the pageId, I was using was wrong🤦‍♀️. These errors come only when your pageId is wrong or the domain is not whitelisted properly(I even tried with a ngrok url and it worked😵).
So the steps which I followed were:
In buisness.facebook.com go to inbox from sidebar and select chat plugin. [https://i.stack.imgur.com/rDk5d.png]
Click on setup to add your domain. [https://i.stack.imgur.com/exOi2.png]
Pick a setup method(standard for react/nextjs) and setup chat plugin(add language, domain, copy code and paste it). [https://i.stack.imgur.com/hDArZ.png]
You can add multiple domains. [https://i.stack.imgur.com/zGdgx.png]
You will get pageId already embedded. [https://i.stack.imgur.com/iRT13.png]
Use this code and paste it in _document.js file in nextjs. and after deploying it will work perfectly. For any confusion please let me know. Thanks, Happy Coding ☺

How to pass JWT-TOKEN to localStorage using JavaScript (script for html)?

I am writing a Rest MVC application for an online coffee and tea store. The following technologies are used: Spring-Boot, Hibernate, PostgreSQL, Gradle, Thymeleaf, HTML, CSS. I have the whole backend ready, it remains to make a frontend. At the moment I'm making an authorization page. The page itself is ready with HTML and CSS, now you need to make the authorization logic itself. To do this, I need to write a script in javascript so that my jwt token is stored in localStorage. The point is that I don't know how to implement this, how to pass my token through the header using javascripte in localStorage.
Important: javascript must be clean, without using frameworks (angular, node ...). How should I do it?
P.S. Again, the whole backand is ready. Rest-authorization method works (that is, I enter my login and password - I get a jwt token).
Java - authorization method
public ResponseEntity<Map<String, String>> authorization(#RequestBody AuthenticationRequestDTO requestDto) {
try {
String login = requestDto.getLogin();
authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(login, requestDto.getPassword()));
User user = userRepository.getByLogin(login);
if (user == null) {
throw new AuthenticationServiceException("ddwd");
}
String token = jwtTokenProvider.createToken(login, user.getRole());
Map<String, String> response = new HashMap<>();
response.put("login", login);
response.put("token", token);
return ResponseEntity.ok(response);
} catch (AuthenticationServiceException e) {
log.error("Error: ", e);
throw new AuthenticationServiceException("Invalid login");
}
}
You can add the JWT token in localstorage and retrieve/read and pass the value with your API calls. below is the example for setting and reading value from localstorage.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
function createLocalstorageItem(txtJwtTokenValue) {
sessionStorage.setItem("jwtToken", txtJwtTokenValue);
}
function readValue() {
var jwtToken = sessionStorage.getItem("jwtToken");
console.log("jwtToken : "+jwtToken );
return jwtToken ;
}
function getDataFromAPiByPassingJwtTokenInHeader(){
var jwtToken=readValue();
$.ajax({
url: 'https://url.com',
type: 'post',
data: {},
headers: {
Bearer Token: "Bearer "+jwtToken, //key word **Bearer** should pass before the token string
},
dataType: 'json',
success: function (data) {
console.info(data);
}
});
}
</script>
please try this way.

workbox 3 - ignore URL params on run-time caching

I want to cache assets from a secure CDN that uses policy token as URL params.
for example: www.cdn.com/image.png?Policy=AAAAA&Key-Pair-Id=BBBBB
and if I re-visit the site, I want to get the asset from the cache even if I have a different policy token and Key-Pair-Id.
for example: www.cdn.com/image.png?Policy=CCCCC&Key-Pair-Id=DDDDD
If I use this code in the service worker:
workbox.routing.registerRoute(
/^(http(s)?:)?\/\/www\.cdn\.com.*/,
workbox.strategies.staleWhileRevalidate()
);
It doesn't find the response in the cache and goes to the network.
I want it to match by the URL without the URL params (even if Policy=CCCCC&Key-Pair-Id=DDDDD is not actually a valid policy). just look if www.cdn.com/image.png exists and retrieve it.
I found a solution for this by using a custom handler:
workbox.routing.registerRoute(
/^(http(s)?:)?\/\/www\.cdn\.com.*/,
({url, event}) => {
return caches.open(`${prefix}-${runtime}-${suffix}`).then((cache) => {
const customRequest = `${url.origin}${url.pathname}`;
return cache.match(customRequest).then((cacheRes) => {
if (cacheRes) {
return cacheRes;
}
return fetch(event.request).then((fetchRes) => {
cache.put(customRequest, fetchRes.clone());
return fetchRes;
});
});
});
}
);

Categories

Resources