Google fit aggregate rest api call issue parse error javascript - javascript

I am calling the google fit rest api as following
const requestBody ={
"aggregateBy": [{
"dataTypeName": "com.google.step_count.delta",
"dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps"
}],
"bucketByTime": { "durationMillis": 86400000 },
"startTimeMillis": 1561228200000,
"endTimeMillis": 1561652514300
}
const userAction = async () => {
const response = await fetch('https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate', {
method: 'POST',
body: requestBody,
headers: {
'Content-Type': 'application/json',
'Content-Length': '302',
'Authorization': 'Bearer ' + authcode,
}
});
const jsonResponse = await response.json();
console.log(jsonResponse);
}
userAction();
I am getting response as
{
"error": {
"errors": [{
"domain": "global",
"reason": "parseError",
"message": "Parse Error"
}],
"code": 400,
"message": "Parse Error"
}
}
Not sure where the parsing error is happening. Any help pointing to where it occours will be much appreciated.
Note - auth token is taken correctly, so it probably cant be the issue.
Also I am running on local host.

Got it to work by the following code(I have hardcoded static params). Add api key and client ID and run it would work.
This link helped - https://developers.google.com/fit/rest/v1/reference/users/dataset/aggregate.
<script>
function authenticate() {
return gapi.auth2.getAuthInstance()
.signIn({scope: "https://www.googleapis.com/auth/fitness.activity.read"})
.then(function() { console.log("Sign-in successful"); },
function(err) { console.error("Error signing in", err); });
}
function loadClient() {
gapi.client.setApiKey("YOUR APP ID");
return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/fitness/v1/rest")
.then(function() { console.log("GAPI client loaded for API"); },
function(err) { console.error("Error loading GAPI client for API", err); });
}
// Make sure the client is loaded and sign-in is complete before calling this method.
function execute() {
return gapi.client.fitness.users.dataset.aggregate({
"userId": "me",
"resource": {
"aggregateBy": [
{
"dataTypeName": "com.google.step_count.delta",
"dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps"
}
],
"endTimeMillis": 1561652514300,// Any time in milliseconds
"startTimeMillis": 1561228200000,// Any time in milliseconds
"bucketByTime": {
"durationMillis": 86400000// Any duration in milliseconds
}
}
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error", err); });
}
gapi.load("client:auth2", function() {
gapi.auth2.init({client_id: "YOUR CLIENT ID"});
});
</script>
<button onclick="authenticate().then(loadClient)">authorize and load</button>
<button onclick="execute()">execute</button>

Related

Amadeus flight booking working but Hotel Booking API doesn't

So I first integrated Amadeus for flight booking and everything went well but problem arrived when I started integrating hotel booking. If I use nodejs library of Amadeus, I get a response that my access token is invalid. This is my code of nestjs service and response.
async hotelSearch(data) {
try {
var amadeus = new Amadeus({
clientId: process.env.API_KEY,
clientSecret: process.env.API_SECRET
});
return await amadeus.shopping.hotelOffers.get(data)
} catch (error) {
return error;
}
}
And this is the response.result -
"result": {
"errors": [
{
"code": 38190,
"title": "Invalid access token",
"detail": "The access token provided in the Authorization header is invalid",
"status": 401
}
]
},
"parsed": true
},
"description": [
{
"code": 38190,
"title": "Invalid access token",
"detail": "The access token provided in the Authorization header is invalid",
"status": 401
}
],
"code": "AuthenticationError"
}
How can I get Invalid Access Token error when I am using the library for it?? Anyway, after facing this issue I decided to use axios instead but still got no success.
async getToken(): Promise<{access_token: string}> {
try {
const data = qs.stringify({
client_id: process.env.API_KEY,
client_secret: process.env.API_SECRET,
grant_type: 'client_credentials'
});
const config:AxiosRequestConfig = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://test.api.amadeus.com/v1/security/oauth2/token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
};
return await axios(config)
.then((response) => {
return((response.data));
})
.catch((error) => {
console.log(error);
});
} catch (error) {
return error;
}
}
async hotelSearch(data) {
try {
const tokenData=await this.getToken()
const refreshToken='Bearer '+ ( tokenData).access_token
console.log('token', refreshToken)
const config:AxiosRequestConfig = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://test.api.amadeus.com/v1/reference-data/locations/hotels/by-city',
data: data,
headers: {'Authorization':refreshToken},
};
return await axios(config).then((response) => {
return(JSON.stringify(response.data));
})
.catch((error) => {
return(error);
});
// var amadeus = new Amadeus({
// clientId: process.env.API_KEY,
// clientSecret: process.env.API_SECRET
// });
// return await amadeus.shopping.hotelOffers.get(data)
} catch (error) {
return error;
}
}
And this is the response I got this time.
{
"message": "Request failed with status code 400",
"name": "Error",
"stack": "Error: Request failed with status code 400\n at createError (E:\\travel-portal\\travel-portal\\node_modules\\axios\\lib\\core\\createError.js:16:15)\n at settle (E:\\travel-portal\\travel-portal\\node_modules\\axios\\lib\\core\\settle.js:17:12)\n at IncomingMessage.handleStreamEnd (E:\\travel-portal\\travel-portal\\node_modules\\axios\\lib\\adapters\\http.js:322:11)\n at IncomingMessage.emit (node:events:525:35)\n at endReadableNT (node:internal/streams/readable:1359:12)\n at processTicksAndRejections (node:internal/process/task_queues:82:21)",
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": null,
"headers": {
"Accept": "application/json, text/plain, */*",
"Authorization": "Bearer CMHEjXBrpzE7YxF9O7GKygCtzCxO",
"Content-Type": "application/json",
"User-Agent": "axios/0.26.1",
"Content-Length": 117
},
"method": "get",
"url": "https://test.api.amadeus.com/v1/reference-data/locations/hotels/by-city",
"data": "{\"cityCode\":\"DEL\",\"radius\":\"5\",\"radiusUnit\":\"KM\",\"checkInDate\":\"2023-03-10\",\"checkOutDate\":\"2023-03-11\",\"adults\":\"2\"}"
},
"status": 400
}
I have cross-checked the payload. The bearer token is all good when I console it and even I checked the request with fiddler and there too header and data are getting passed. Any help to get this work through either of the method is really appreciated.
The amadeus.shopping.hotelOffers.get() endpoint has been decommissioned so you won't be able to use it. Install the latest version of the Node library and use the new Hotel Search endpoint as below:
var Amadeus = require(amadeus);
var amadeus = new Amadeus({
clientId: 'YOUR_API_KEY',
clientSecret: 'YOUR_API_SECRET'
});
// Get list of available offers in specific hotels by hotel ids
amadeus.shopping.hotelOffersSearch.get({
hotelIds: 'RTPAR001',
adults: '2'
}).then(function (response) {
console.log(response);
}).catch(function (response) {
console.error(response);
});
You can also check the migration guide for more details and how to use the new Hotel Search version.

Browsers needs a HTTP response, but server is not allowing multiple responses

This is my handler that sends out a PUT request to my server:
export function insertRandomQuestionsHandler(roomId, questions) {
return (dispatch) => {
dispatch(questionOverviewHandler(questions));
let result = questions.reduce((r, e) => (r.push(...e), r), []);
const url = . `http://localhost:3000/quizzer/room/${roomId}/selectedQuestions`;
const response = fetch(url, {
method: "PUT",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
questions: result,
})
});
if (response.error) {
throw new Error(`HTTP PUT request went wrong: got .
"${response.statusText}" for "${url}"`)
}
dispatch(insertRandomQuestions(result))
}
}
On the server it goes through this request:
quizzer.put('/room/:roomId/selectedQuestions', async function (req, res) {
for (let i = 0; i < req.body.questions.length; i++) {
await Room.findOneAndUpdate({roomId: req.params.roomId}, {
"$push": {
"questions": [{
"_id": req.body.questions[i]._id,
"question": req.body.questions[i].question,
"answer": req.body.questions[i].answer,
"category": req.body.questions[i].category,
"isShown": false,
}]
}
},(err, data) => {
if (err) {
return res.status(500).send(err);
}
return res.status(200).json(data);
});
}
});
For some reason the browser needs a response else the request will be stuck at being pending and eventually return ERR_EMPTY_RESPONSE:
But when I return a response (data) as shown above (the http request is 200)
Then my server crashes:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent
So... I need that response to be sent, but it can't be sent twice..
Any ideas?

Add youtube comments with youtube API and node.js

I managed to fetch video data from a channel but when it try to add comments to a video, I fail. So at some point I can read data successfully.
I have read that docummentation: https://developers.google.com/youtube/v3/docs/commentThreads/insert
And I'm not sure if I did the parameters correctly.
Besides Node.js and Express I'm using the request-promise package for promises if that's worth to mention.
const optionsComment = {
method: 'POST',
uri: 'https://www.googleapis.com/youtube/v3/commentThreads',
qs: {
part: 'snippet',
'snippet.channelId': 'a channel id',
'snippet.videoId': 'some video id',
'snippet.topLevelComment.snippet.textOriginal': 'a nice message',
key: "my key"
},
json: true
};
rp(optionsComment)
.then(result=>{
console.log("result of adding comment:", result);
})
.catch(function(err){
console.log("error during add comment");
console.log(err);
});
When I run the code I get this error:
error during add comment
{ StatusCodeError: 401 - {"error":{"errors":[{"domain":"global","reason":"required","message":"Login Required","locationType":"header","location":"Authorization"}],"code":401,"message":"Login Required"}}
at new StatusCodeError
Even if I'm logged in and try to comment my own video I get this error.
Maybe someone can give me a hint.
Thank you!
I'd similar issue as yours, sending the access_token in qs fixed it for me.
'use strict';
let request = require('request');
const sourceId = '< youtube video id>';
const comment_id = 'the comment id';
const comment = 'actual comment';
new Promise((resolve, reject) => {
request({
method: 'POST',
url: 'https://www.googleapis.com/youtube/v3/commentThreads',
headers: {
'User-Agent': 'Request-Promise'
},
body: {
"snippet": {
"videoId": sourceId,
"channelId": comment_id,
"topLevelComment": {
"snippet": {
"textOriginal": comment
}
}
}
},
qs: {
part: 'snippet',
access_token: token
},
json: true
}, function (error, response, body) {
if (error) {
console.log('body', body);
console.log('error in when posting comment ', error.stack);
return reject(error);
}
return resolve(body);
});
});

How to code a "try again" in a Promise?

I will try to describe my problem as the best I can. I have a method who (1)get all Grafana datasources via the API (2)create 2 JSON (3)post them to Grafana API.
The thing is sometimes one of my JSON is not finish when the code make the 3rd step so I got an error and the result is not what I want.
updateDashboard = Meteor.bindEnvironment(function() {
console.log("called updateDashboard()");
new Promise(Meteor.bindEnvironment(function(resolve) {
// get all the datasources of Grafana
HTTP.call("GET", 'http://localhost:3000/api/datasources', {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
},
},
function(error, result) {
if (!error) {
allDataSources = result.data;
resolve(allDataSources);
} else {
console.error(error);
}
});
})).then(function(allDataSources) {
// create the dashboard
return new Promise(function(resolve) {
//ANCHOR
var dataJSON = {
//create the dashboard
"annotations": {
"list": []
},
"description": "Containers metrics",
"editable": true,
"gnetId": null,
"graphTooltip": 1,
"hideControls": false,
"id": null,
"links": [],
"refresh": "1s",
//create the lines
"rows": _.map(allDataSources, function(ds, index) {
return newGraphOverview(ds, index);
}),
//dashboard things
"schemaVersion": 14,
"style": "dark",
"tags": [
"docker"
],
"time": {
"from": "now-15m",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"1s",
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "browser",
"title": "Docker Containers _custom_from_js",
"version": 1
}
dataJSONDetails = newGraphDetails(allDataSources);
resolve(dataJSON);
});
}).then(Meteor.bindEnvironment(function(dataJSON) {
// send the dashboard
HTTP.call("POST", "http://localhost:3000/api/dashboards/db", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
},
data: {
dashboard: dataJSON,
overwrite: true
}
},
function(error, result) {
if (!error) {
console.log("result post " + dataJSON.title + " ----------------------------------")
console.log(result);
} else {
//HERE I WANT TO DO IF ERROR GO TO ANCHOR
console.log("error post " + dataJSON.title + " ----------------------------------")
console.error(error);
}
});
//send the dashboard for details view
HTTP.call("POST", "http://localhost:3000/api/dashboards/db", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
},
data: {
dashboard: dataJSONDetails,
overwrite: true
}
},
function(error, result) {
if (!error) {
console.log("result post " + dataJSONDetails.title + " ----------------------------------")
console.log(result);
} else {
//HERE I WANT TO DO IF ERROR GO TO ANCHOR
console.log("error post " + dataJSONDetails.title + " ----------------------------------")
console.error(error);
}
});
}));
});
I know the code snipped doesn't work but it was easier for me to make it readable.
So someone could help me to make a thing like "if error try to create again" ? I have seen Meteor retries but it don't think it's what I need
You shouldn't use promises or callbacks. Write normal, synchronous-looking code as you've seen in Meteor examples.
var datasources = null;
try {
var request1 = HTTP.call("GET", 'http://localhost:3000/api/datasources', {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': APIKEY,
}
});
// From http://docs.meteor.com/api/http.html#HTTP-call
datasources = request.data;
} catch (e) {
console.error(e);
return;
}
// Do all the other steps you keep wanting to do...
Repeat a similar statement for your other HTTP calls. Generally, you will not be throwing errors unless localhost is unreachable, in which case everything is unreachable. So don't bother with try-catch. Let the exception be thrown and handled by the client (the caller of the method).
You shouldn't generally have to use Meteor.bindEnvironment.

Reactjs isomorphic-fetch PATCH how to have the body error?

So basically I am sending data with a fetch POST or PATCH method and when I have an error I can see in the network -> response this error:
{
"Errors": [
{
"Code": -201,
"Message": "Could not get file from link",
"AssociatedError": "404 Not Found"
}
],
"Result": null
}
Here is my actual code:
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
} else {
var error = new Error(response.statusText);
error.response = response;
throw error;
}
}
export function sendImageUploaded(data, valueMethod, endpoint) {
return dispatch => {
dispatch(requestPosts(data));
return fetch(endpoint, {
method: valueMethod,
headers: new Headers({
Authorization: Isengard.config.token
}),
body: data
})
.then(checkStatus)
.then(reponse => {
dispatch(successSent("The output list has been successfully sent!"));
}).catch(err => {
console.log('request failed', err);
dispatch(failSent("Error on sending request: " + err));
});
};
};
And I am struggling on having this error message.
You already got your response error in "error.response". You only have to resolve that promise.
instead of
.catch(err => {
console.log('request failed', err);
dispatch(failSent("Error on sending request: " + err));
});
use
.catch(err => {
err.response.json().then((json) =>{
let {Errors,Result} = json;
dispatch(failSent(Errors)); // You are sending your array of errors here
});
});

Categories