Amadeus Point of Interest Search INVALID_DATA_RECEIVED - amadeus

Using the Amadeus Node SDK, Amadeus Points of Interest API only works for some geographical coordinates.
I am currently looking at some Points of Interest in France and everything north of Paris does not seem to work, and Amadeus responds with the error INVALID DATA RECEIVED.
Example of coordinates that work (Orleans, France):
Latitude: 47.90082
Longitude: 1.90283
Example of coordinates that don't work (Rouen, France):
Latitude: 49.443231
Longitude: 1.0999
Example error response:
{"response":{"contentType":"application/vnd.amadeus+json","statusCode":400,"request":{"host":"api.amadeus.com","port":443,"ssl":true,"scheme":"https","verb":"GET","path":"/v1/reference-data/locations/pois","params":{"latitude":49.443231,"longitude":1.0999,"radius":20},"queryPath":"/v1/reference-data/locations/pois?latitude=49.443231&longitude=1.0999&radius=20","bearerToken":"TOKEN","clientVersion":"4.0.0","languageVersion":"12.2.0","appId":null,"appVersion":null,"headers":{"User-Agent":"amadeus-node/4.0.0 node/12.2.0","Accept":"application/json, application/vnd.amadeus+json","Authorization":"Bearer TOKEN","Content-Type":"application/vnd.amadeus+json"}},"body":"{"errors":[{"status":400,"code":4926,"title":"INVALID DATA RECEIVED","detail":"","source":{"parameters":["longitude"]}}]}","result":{"errors":[{"status":400,"code":4926,"title":"INVALID DATA RECEIVED","detail":"","source":{"parameters":["longitude"]}}]},"parsed":true},"description":[{"status":400,"code":4926,"title":"INVALID DATA RECEIVED","detail":"","source":{"parameters":["longitude"]}}],"code":"ClientError"}"}
var Amadeus = require('amadeus');
var amadeus = new Amadeus({
clientId: 'PRODUCTION_ID',
clientSecret: 'PRODUCTION_SECRET',
hostname: 'production'
});
exports.autocompleteCreate = async (req, res) => {
console.log(req.body);
// I'm getting lat/lng from a POST request
var latitude = parseFloat(JSON.stringify(req.body.latitude).toString().substring(0,9));
var longitude = parseFloat(JSON.stringify(req.body.longitude).toString().substring(0,6));
amadeus.referenceData.locations.pointsOfInterest.get({
latitude: latitude,
longitude: longitude,
radius: 20
}).then(
function(response) {
console.log(response)
})
}

The issue was linked to the computation of the radius (for specific places). It has been fixed and delivered. You shouldn't face the problem anymore.

Related

CORS header ‘Access-Control-Allow-Origin’ missing on response in addon but not on request

I am creating a Firefox extension which posts some data to a database.
I made all parts in a modular fashion and am now combining everything piece by piece.
As such I know that my code to POST data to the database works.
Now here is the part that stumps me :
When I then add this code to my firefox extension
I get the following error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3003/timed_shot_create. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 400.
Now ofcourse CORS was nothing new and to be expected when dealing with Cross Origin Resource Sharing, it is even in the name.
But the reason why I am here is because this pertains only to the response of the POST request. The request itself is fine and allowed with the following piece of config in the server:
app.use(
cors({
//todo change to proper origin when live
origin: "moz-extension://d07f1e99-96a0-4934-8ff4-1ce222c06d0d",
method: ["GET", "POST"],
})
);
Which was later changed to:
app.use(
cors({
origin: "*",
method: ["GET", "POST"],
})
);
And then simplified even more to:
app.use(cors())
This is in Nodejs btw using cors middleware.
But none of this seems to work when it is used inside a firefox extension, as a local client page works as intended but as soon as I add this to a firefox extension I get a CORS error specifically pertaining to the reponse message.
The client side post (in the background script of the extension) is:
async function postTimedShot(post_options) {
const response = await fetch(post_endpoint, post_options);
//console.log(response);
const json_response = await response.json();
console.log(json_response);
}
let post_options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(response_data),
};
postTimedShot(post_options);
And the api looks like this:
app.post("/timed_shot_create", (req, res) => {
console.log("Received POST request");
const data = req.body;
console.log(data);
const timeStamp = data.time_stamp;
//TODO add screenshot and Description text maybe??
//const lastName = data.last_name
const queryString =
"INSERT INTO " + timed_shots_database + " (time_stamp) VALUES (?)";
getConnection().query(queryString, [timeStamp], (err, results, fields) => {
if (err) {
console.log("Failed to insert new user: " + err);
res.sendStatus(500);
return;
}
//Todo change this message when adding more data in body
//res.header("Access-Control-Allow-Origin", "moz-extension://d07f1e99-96a0-4934-8ff4-1ce222c06d0d");
res.json({
status: "Success!!!",
time_stamp: timeStamp,
});
console.log("Inserted a new user with id: ", results.insertId);
});
});
Furthermore, this extension is only for personal use and will work with a local server under my complete control so complications due to security or cloud usage that people want to mention are appreciated but not necessary (I think, I am a bit of novice).
I will be happy to clarify anything that is unclear, or change this post if necessary, but I think it is a unique question as far as I could see on SO. Additionally if I need to provide more of the codebase I will.
I will also update this post if I find out more about this problem.
Thank you for reading :3.
After reading about this post https://stackoverflow.com/a/53025865/5055963
on SO I found out that it had to do with the permissions in the manifest of the extension.
Adding this line: "://.localhost/*".
Solved the issue for me.

Successful Login to API; Unsuccessful at accessing any data due to being unauthorized

I am attempting to come up with a live leaderboard for my local club using the PDGA's (Professional Disc Golf Association) API. I am writing a Google Apps Script intending to auto populate a Google Sheet with a Club Ranking that can be refreshed as needed.
Right now, all I am trying to do is make pull of data to ensure I am able to begin using the API, but I can't seem to do even that.
For reference, here are the only two resources I have to work with regarding this specific API:
PDGA REST API Authentication
PDGA REST API Services
I have got the original login to work using this code:
function apiLogin() {
var LoginUrl = 'https://api.pdga.com/services/json/user/login';
var LoginDetails = {
'username' : Username,
'password' : Password
};
var LoginRequest = {
'method' : 'post',
'Content-Type' : 'application/json',
'payload' : LoginDetails
};
var LoginResponse = UrlFetchApp.fetch(LoginUrl, LoginRequest);
var json = LoginResponse.getContentText();
var LoginData = JSON.parse(json);
Logger.log(LoginData);
var SessionID = LoginData['sessid'];
var SessionName = LoginData['session_name'];
var Tok = LoginData['token'];
var playerFetchPar = {
'method' : 'get',
'Cookie' : SessionID + '=' + SessionName
};
var PlayerResponse = UrlFetchApp.fetch('https://api.pdga.com/services/json/players?pdga_number=1',playerFetchPar); //ERROR
Logger.log(PlayerResponse);
};
It's the last part when I am trying to call on data from a player that I get the following error message:
Exception: Request failed for https://api.pdga.com returned code 403. Truncated server response: ["Access denied for user anonymous"] (use muteHttpExceptions option to examine full response)
I am guessing that my screw up is in my interpretion of the parameter Cookie from that second link. In the initial response to make sure I was logging in properly, I received a session_name and sessid but I can't seem to figure out what is expected from Cookie. I am sorry if the answer is obvious, but any help would be greatly appreciated!
The documentation says
Cookie: session_name=sessid
You've used
Cookie: sessid=session_name
Reverse it:
'Cookie' : `${SessionName}=${SessionID}`
And you need to send it as a header:
const playerFetchPar = {
method : 'get',
headers: {'Cookie' : `${SessionName}=${SessionID}`}
};

Recreate a post request in postman

I have the following javascript code, to produce a post request.
var postUrl = "http://localhost:3100/radiance";
xhttp.open("POST", postUrl, true);
xhttp.setRequestHeader('Content-type', 'application/json');
let radFile = {"radfile":"long string"}
let solarJson = {"key1":"value1","key2":"value2"}
let latitude = 45
let longitude = 24
msgJson=JSON.stringify({'radFile':radFile,'speedSolar':solarJson,'latitude':latitude,'longitude':longitude})
xhttp.send(msgJson);
The post request works absolutely fine with my express app code below.
var express = require('express');
// require our dependencies
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var app = express();
var port = process.env.PORT || 3100;
var corsOptions = {
credentials: false
};
// use body parser
app.use(bodyParser.urlencoded({extended: true, limit: 1024 * 1024 * 10000, parameterLimit: 1000000*1000}));
app.use(bodyParser.json({type: 'application/json', extended: false, limit: 1024 * 1024 * 10000, parameterLimit: 1000000*1000}));
// route our app
var router = require('./app/routes');
app.use('/', router);
var server
// start the server
server = app.listen(port, function() {
console.log('app started ' +port );
});
However I am struggling to replicate the post request above in post man for testing (purposes).
I believe that the following post request should do the trick but when my app recieves this post request the body of the request is always empty. Why? It seems that the body parser isnt doing it's job.
What I am doing wrong in my post request in postman, how can I replicate my javascript post request exactly?
You are doing two different types of request here. Your website code is sending a JSON string with the contents of the 'files' embedded into it:
let radFile = {"radfile":"long string"}
let solarJson = {"key1":"value1","key2":"value2"}
let latitude = 45
let longitude = 24
msgJson=JSON.stringify({'radFile':radFile,'speedSolar':solarJson,'latitude':latitude,'longitude':longitude})
gives you a body of
{'radFile': {"radfile": "long string"}, 'speedSolar': {"key1":"value1", "key2":"value2"}, 'latitude': 45, 'longitude': 24}
However, when you are using Postman as you are, you are submitting 2 different pieces, a file (or 2) and the form values - you can use the postman echo site to see what you are actually submitting, in case you have questions in the future:
If you really want to replicate your original version, you can do this - a raw body of type json, and fill in the details:

getaddrinfo ENOTFOUND API Google Cloud

I'm trying to execute API.AI tutorial for building a weather bot for Google Assistant (the one here: https://dialogflow.com/docs/getting-started/basic-fulfillment-conversation)
I made everything successfully, created the bot within API, created the Fulfillments, installed NodeJS on my pc, connected Google Cloud Platform, etc.
Then I created the index.js file by copying it exactly how it's stated on API.ai tutorial with my API key from World Weather Organisation (see below).
But when I use the bot, it doesn't work. On the Google Cloud Platform the error is always the same:
Error: getaddrinfo ENOTFOUND api.worldweatheronline.com
api.worldweatheronline.com:80
at errnoException (dns.js:28)
at GetAddrInfoReqWrap.onlookup (dns.js:76)
No matter how often I do it I get the same error. So I don't actually reach the API. I tried to see if anything changed from WWO side (URL, etc.) but apparently no. I updated NodeJS and still same issue. I refreshed the Google Cloud platform completely and didn't help.
That one I really can't debug. Could anyone help?
Here's the code from API.ai:
'use strict';
const http = require('http');
const host = 'api.worldweatheronline.com';
const wwoApiKey = '[YOUR_API_KEY]';
exports.weatherWebhook = (req, res) => {
// Get the city and date from the request
let city = req.body.result.parameters['geo-city']; // city is a required param
// Get the date for the weather forecast (if present)
let date = '';
if (req.body.result.parameters['date']) {
date = req.body.result.parameters['date'];
console.log('Date: ' + date);
}
// Call the weather API
callWeatherApi(city, date).then((output) => {
// Return the results of the weather API to Dialogflow
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ 'speech': output, 'displayText': output }));
}).catch((error) => {
// If there is an error let the user know
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ 'speech': error, 'displayText': error }));
});
};
function callWeatherApi (city, date) {
return new Promise((resolve, reject) => {
// Create the path for the HTTP request to get the weather
let path = '/premium/v1/weather.ashx?format=json&num_of_days=1' +
'&q=' + encodeURIComponent(city) + '&key=' + wwoApiKey + '&date=' + date;
console.log('API Request: ' + host + path);
// Make the HTTP request to get the weather
http.get({host: host, path: path}, (res) => {
let body = ''; // var to store the response chunks
res.on('data', (d) => { body += d; }); // store each response chunk
res.on('end', () => {
// After all the data has been received parse the JSON for desired data
let response = JSON.parse(body);
let forecast = response['data']['weather'][0];
let location = response['data']['request'][0];
let conditions = response['data']['current_condition'][0];
let currentConditions = conditions['weatherDesc'][0]['value'];
// Create response
let output = `Current conditions in the ${location['type']}
${location['query']} are ${currentConditions} with a projected high of
${forecast['maxtempC']}°C or ${forecast['maxtempF']}°F and a low of
${forecast['mintempC']}°C or ${forecast['mintempF']}°F on
${forecast['date']}.`;
// Resolve the promise with the output text
console.log(output);
resolve(output);
});
res.on('error', (error) => {
reject(error);
});
});
});
}
Oh boy, in fact the reason was most stupid ever. I didn't enable "billing" on Google Cloud Platform and that's why it blocked everything (even though I'm using a free test of the API). They just wanted my credit card number. It works now
I had the same issue trying to hit my db. Billing wasn't the fix as I had billing enabled already.
For me it was knexfile.js setup for MySql - specifically the connection object. In that object, you should replace the host key with socketPath; and prepend /cloudsql/ to the value. Here's an example:
connection: {
// host: process.env.APP_DB_HOST, // The problem
socketPath: `/cloudsql/${process.env.APP_DB_HOST}`, // The fix
database: process.env.APP_DB_NAME,
user: process.env.APP_DB_USR,
password: process.env.APP_DB_PWD
}
Where process.env.APP_DB_HOST is your Instance connection name.
PS: I imagine that even if you're not using Knex, the host or server parameter of a typical DB connectionstring will have to be called socketPath when connecting to Google Cloud SQL.

Cannot Checkin Through FB.api (javascript)

With the javascript sdk (FB.api), I cannot checkin on behalf of user.
(The user has granted publish_stream permission to my app)
Since facebook's API keeps changing, confused for some time. After searching and reading from internet, I think it's the right way to publish a checkin. Any help is appreciated.
var params = {
method: 'POST',
place: 107297282684980,
message: 'hi',
coordinates: {
'latitude': 22.204284439454,
'longitude': 113.54313260065
}};
FB.api(
'/me/checkins',
params,
function(response) {
if( response )
alert('Checkin Completed!');
});
It was deprecated at July 2013. You should check the changes from the URLs provided at the question comment.
And follow the instructions:
https://developers.facebook.com/docs/opengraph/overview/
https://developers.facebook.com/docs/opengraph/getting-started/
As FB Check-In is deprecated we can achieve the same thing with a post on FB with Location Attached using the following FB Graph Api post.
FB.api('/me/feed', 'post', {
name: 'SomeName',
message: 'SomeMessage',
place: yourLocationID
}, function (response) {});
Note : Where yourLocationID is the ID that you will get by the Graph search using https://graph.facebook.com/search?q=yourPlaceName&type=page&access_token=YOURTOKEN