Google Sheets API values.append Returning incorrect response - google-sheets-api

Trying to write a Firebase cloud function that appends user information to a spreadsheet. I want the values of the range updated so I can use it if the user changes their mind to update the spreadsheet.
async function writeToSpreadSheet(firstName: string, lastName: string, response: string, spreadSheetId: string, date:string, userEmail:string): Promise<Schema$AppendValuesResponse> {
await sheets.spreadsheets.values.append({
auth: jwtClient,
spreadsheetId: spreadSheetId,
range: 'Sheet1!A1:C3', // update this range of cells
valueInputOption: 'RAW',
requestBody: {"values": [[firstName, lastName,userEmail, response, date]]},
}, (err, res) => {
if(err){
console.log(err);
return;
}
console.log(res);
return;
});
}
For some reason I am getting a huge response like:
{ status: 200,
statusText: 'OK',
headers:
{ 'content-type': 'application/json; charset=UTF-8',
vary: 'Origin, X-Origin, Referer',
...
}
Instead of a nice:
{
"spreadsheetId": "{spreadsheetId}",
"tableRange": "Sheet1!A1:C18",
}

You want to retrieve the properties of only spreadsheetId and tableRange as the response.
You are using googleapis of Node.js.
If my understanding is correct, how about this modification?
Modified script:
await sheets.spreadsheets.values.append({
auth: jwtClient,
spreadsheetId: spreadSheetId,
range: 'Sheet1!A1:C3', // update this range of cells
valueInputOption: 'RAW',
requestBody: {"values": [[firstName, lastName,userEmail, response, date]]},
fields: "spreadsheetId,tableRange", // Added
}, (err, res) => {
if(err){
console.log(err);
return;
}
console.log(res.data); // Modified
return;
});
References:
spreadsheets.values.append
About response from API using googleapis
If I misunderstood your question, I apologize.

Related

KeystoneJS login via GraphQL mutation

I am trying to login to a Keystone 5 GraphQL API. I have setup the app so that I can login via the Admin Console, but I want to login from a Svelte application.
I keep finding references to the code below (I am new to GraphQL) but don't know how to use it.
mutation signin($identity: String, $secret: String) {
authenticate: authenticateUserWithPassword(email: $identity, password: $secret) {
item {
id
}
}
}
If I post that query "as is" I get an authentication error, so I must be hitting the correct endpoint.
If I change the code to include my username and password
mutation signin("myusername", "mypassword") {
authenticate: authenticateUserWithPassword(email: $identity, password: $secret) {
item {
id
}
}
}
I get a bad request error.
Can anyone tell me how I send username/password credentials correctly in order to log in.
The full code I am sending is this
import { onMount } from 'svelte';
let users = [];
onMount(() => {
fetch("http://localhost:4000/admin/api", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query: `mutation signin($identity: String, $secret: String) {
authenticate: authenticateUserWithPassword(email: $identity, password: $secret) {
item {
id
}
}
}`
})
}).then(res => res.json())
.then(data => {
console.log(data)
})
})
Here is the response I get
{"errors":[{"message":"[passwordAuth:failure] Authentication failed","locations":[{"line":2,"column":3}],"path":["authenticate"],"extensions":{"code":"INTERNAL_SERVER_ERROR","exception":{"stacktrace":["Error: [passwordAuth:failure] Authentication failed"," at ListAuthProvider._authenticateMutation (/Users/simon/development/projects/keystone/meetings-api/node_modules/#keystonejs/keystone/lib/providers/listAuth.js:250:13)"]}},"uid":"ckwqtreql0016z9sl2s81af6w","name":"GraphQLError"}],"data":{"authenticate":null},"extensions":{"tracing":{"version":1,"startTime":"2021-12-03T20:13:44.762Z","endTime":"2021-12-03T20:13:44.926Z","duration":164684813,"execution":{"resolvers":[{"path":["authenticate"],"parentType":"Mutation","fieldName":"authenticateUserWithPassword","returnType":"authenticateUserOutput","startOffset":2469132,"duration":159500839}]}}}}
I found the answer eventually.
You have to provide an extra object in your body called variables
variables: {
var1: "value1",
var2: "value2"
}
Those variables will then replace the placehodlers in the query like $var1 or $var2
Here is the full fetch code that works.
fetch("http://localhost:4000/admin/api", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query: `mutation signin($identity: String, $secret: String) {
authenticate: authenticateUserWithPassword(email: $identity, password: $secret) {
item {
id
}
}
}`,
variables: {
identity: "myusername",
secret: "mypassword"
}
})
}).then(res => res.json())
.then(data => {
console.log(data)
})
It's a shame that KeystoneJS don't provide any full code examples in their documentation. It would have saved me hours of searching.
As you say #PrestonDocks, if your query defines variables, you need to supply the variable values in a separate top level object. For the benefit of others I'll link to the GraphQL docs on this.
The alternative is to not use variables and to in-line your values in the query itself, like this:
mutation signin {
authenticate: authenticateUserWithPassword(
email: "me#example.com",
password: "Reindeer Flotilla"
) {
item {
id
}
}
}
But variables usually end up being neater.

Access post body without bodyparser

I am trying to send a bas64 encoded image to my express server and parse it there to save it to disk. Id like to implement this with a simple http post request but couldn't get it to work. My first implementation utilized a websocket server and worked well:
Client:
const object = JSON.stringify({
action: "add_image",
data: dataUrl,
})
ws.send(object)
Server:
ws.on("message", (message) => {
const req = JSON.parse(message);
fs.writeFile(
"path/to/file.png",
data.split(";base64,").pop(),
{ encoding: "base64" },
(err) => err && console.log(err)
)
}
This is my trying to get the same result with an http request.
Client:
const object = JSON.stringify({
action: "add_image",
data: dataUrl,
})
fetch("http://localhost:3001/add_image", {
method: "POST",
headers: new Headers({
Origin: window.origin,
Accept: "image/png",
"Content-Type": "image/png",
}),
mode: "cors",
body: object,
})
Server:
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.post("/add_image", function (req, res) {
console.log(req.body);
});
Unfortunately, req.body always logs an empty object.
I am not quite sure what I am lacking. Any help would be greatly appreciated.
I found the answer in this article. I needed to combine all individual chunks of the request and then use the data once the process is complete.
app.post("/add_image", function (req, res) {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
console.log(JSON.parse(body));
res.end('ok');
});
});

Axios formData with image is sending empty array

I have a put method to my profile route in the backend, I need a token authentication so in order to be authorized I have to pass the token through a header, I get an error because for some reason it's sending an empty formData when I log the request in my backend.
I tested the backend with postman and everything works as intended so it's not a backend issue, it's totally something wrong in the request I'm doing from the frontend, but I don't know how to handle this, any clue?
profile_update() {
let params = {
email: this.profile.email,
password: this.profile.password,
coin: this.profile.coin,
phone_country: this.profile.phone_country,
phone_area: this.profile.area_code,
phone_number: this.profile.number,
first_name: this.profile.first_name,
last_name: this.profile.last_name,
date_of_birth: this.profile.date_of_birth,
gender: this.profile.gender,
city_id: this.profile.city,
wants_to_change_password: this.profile.wants_to_change_password,
state_id: this.profile.state,
city_id: this.profile.city
}
let headers = {
'Authorization': 'Bearer' + this.token
}
let formData = new FormData();
formData.append('profile-picture', this.profile.profile_picture)
formData.append('data', params)
formData.append('headers', headers)
formData.append('_method', 'PUT')
axios.put(`http://127.0.0.1:8000/api/profile`, formData, headers).then(res => {
console.log(res)
}).catch(e => {
console.log(e)
})
}
Try this way
axios.put(`http://127.0.0.1:8000/api/profile`, {'profile-picture':this.profile.profile_picture}, {
headers: {
Authorization: 'Bearer ' + this.token,
'content-type': 'multipart/form-data'
}
}).then(res => {
console.log(res)
}).catch(e => {
console.log(e)
})
Hope this may solve your problem. For more info read docs

How to change status code of headers of response in serverless framwork?

I want to response personal defined statuscode and some headers.
But I find even I change the status code to 201 the status code is still 200. and my defined header is not in headers.
my handler like:
function createResponse(status, header, body) {
return {
headers: Object.assign(header, {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json;charset=utf-8'
}),
statusCode: status,
body: JSON.stringify(body)
}
}
export const hello = async (event, context, cb) => {
const rep = {
message: 'v1.0',
event: event
};
cb(null, createResponse(201, {}, rep));
return;
};
I use serverless.yml my configuration is:
functions:
first:
handler: handlers/first.hello
events:
- http:
method: ANY
path: first
integration: lambda
How to check to correct code can change status code and response header?
I also find my headers still in response body, How to add my header part in Response headers?
If you think my intergration part have problem, can you give me correct configuration example?
Looks like you have a nested object inside headers.
Reference documentation,
https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
Here is the correct sample code to send the correct response,
exports.handler = function(event, context, callback) {
console.log('Received event:', JSON.stringify(event, null, 2));
var res ={
"statusCode": 200,
"headers": {
"Content-Type": "*/*"
}
};
res.body = "Hello, World !";
callback(null, res);
};
Hope it helps.

Difference between POST and GET (hapijs)

I'm new to the hapijs. Can someone tell me what's the difference between POST and GET in hapijs? For some reason my POST method doesn't work at all so I do is INSERT via GET function.
GET:
server.route({
method: 'GET',
path: '/index/{orderId}',
config: {
handler: test,
validate: {
params: {
orderId: Joi.string()
.required()
.description('Order indentifier')
}
}
}
});
And test function:
function test (request, reply) {
console.log(request.params.orderId);
var params = {orderId: request.params.orderId}
connection.query('INSERT QUERY HERE', function (err, res, fields) {
if (err) throw error;
console.log(res);
reply(res);
});
}