How to send a webhook using Office Script? - javascript

I need to connect Excel to Zapier through a webhook but can't make it work so far. I manage to send a webhook using this code but don't receive any data in the body.
function sendMessage() {
var request = new XMLHttpRequest();
request.open("POST", "https://hooks.zapier.com/hooks/catch/2251620/bv6gjw6/");
request.setRequestHeader('Content-type', 'application/json');
var content = { "value1": "test data" };
request.send(JSON.stringify(content));
}
sendMessage()
}```
Tried every code snippet out there but couldn't make it work. Pasted JSON data as well.

I've found the culprit - mode: 'no-cors'needs to be added. Here's the end result, you can send webhooks from Excel Script with that:
async function main(workbook: ExcelScript.Workbook) {
async function sendWebhook(data:string) {
let response = await fetch('https://hooks.zapier.com/hooks/catch/2251620/bv6gjw6/', {
method: 'POST',
mode: 'no-cors',
headers: { 'Content-Type': 'application/json' },
body: data,
});
return response;
//const json = await response.json();
//return json;
}
let data = JSON.stringify({ message: 'Hello, Excel!' });
let response= await sendWebhook(data);

Related

ECONNRESET and CGI parser error when trying to upload file using axios post [duplicate]

I have an API endpoint that lets the client post their csv to our server then post it to someone else server. I have done our server part which save uploaded file to our server, but I can't get the other part done. I keep getting error { message: 'File not found', code: 400 } which may mean the file never reach the server. I'm using axios as an agent, does anyone know how to get this done? Thanks.
// file = uploaded file
const form_data = new FormData();
form_data.append("file", fs.createReadStream(file.path));
const request_config = {
method: "post",
url: url,
headers: {
"Authorization": "Bearer " + access_token,
"Content-Type": "multipart/form-data"
},
data: form_data
};
return axios(request_config);
Update
As axios doc states as below and the API I'm trying to call requires a file
// data is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', and 'PATCH'
// When no transformRequest is set, must be of one of the following types:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - Browser only: FormData, File, Blob
// - Node only: Stream, Buffer
Is there any way to make axios send a file as a whole? Thanks.
The 2 oldest answers did not work for me. This, however, did the trick:
const FormData = require('form-data'); // npm install --save form-data
const form = new FormData();
form.append('file', fs.createReadStream(file.path));
const request_config = {
headers: {
'Authorization': `Bearer ${access_token}`,
...form.getHeaders()
}
};
return axios.post(url, form, request_config);
form.getHeaders() returns an Object with the content-type as well as the boundary.
For example:
{ "content-type": "multipart/form-data; boundary=-------------------0123456789" }
I'm thinking the createReadStream is your issue because its async. try this.
Since createReadStream extends the event emitter, we can "listen" for when it finishes/ends.
var newFile = fs.createReadStream(file.path);
// personally I'd function out the inner body here and just call
// to the function and pass in the newFile
newFile.on('end', function() {
const form_data = new FormData();
form_data.append("file", newFile, "filename.ext");
const request_config = {
method: "post",
url: url,
headers: {
"Authorization": "Bearer " + access_token,
"Content-Type": "multipart/form-data"
},
data: form_data
};
return axios(request_config);
});
This is what you really need:
const form_data = new FormData();
form_data.append("file", fs.createReadStream(file.path));
const request_config = {
headers: {
"Authorization": "Bearer " + access_token,
"Content-Type": "multipart/form-data"
},
data: form_data
};
return axios
.post(url, form_data, request_config);
In my case, fs.createReadStream(file.path) did not work.
I had to use buffer instead.
const form = new FormData();
form.append('file', fs.readFileSync(filePath), fileName);
const config = {
headers: {
Authorization: `Bearer ${auth.access_token}`,
...form.getHeaders(),
},
};
axios.post(api, form.getBuffer(), config);
I have made an interceptor you can connect to axios to handle this case in node: axios-form-data. Any feedback would be welcome.
npm i axios-form-data
example:
import axiosFormData from 'axios-form-data';
import axios from 'axios';
// connect axiosFormData interceptor to axios
axios.interceptors.request.use(axiosFormData);
// send request with a file in it, it automatically becomes form-data
const response = await axios.request({
method: 'POST',
url: 'http://httpbin.org/post',
data: {
nonfile: 'Non-file value',
// if there is at least one streamable value, the interceptor wraps the data into FormData
file: createReadStream('somefile'),
},
});
// response should show "files" with file content, "form" with other values
// and multipart/form-data with random boundary as request header
console.log(response.data);
I had a same issue, I had a "pdf-creator-service" for generate PDF document from html.
I use mustache template engine for create HTML document - https://www.npmjs.com/package/mustache
Mustache.render function returns html as a string what do I need to do to pass it to the pdf-generator-service ? So lets see my suggestion bellow
//...
async function getPdfDoc(props: {foo: string, bar: string}): Promise<Buffer> {
const temlateFile = readFileSync(joinPath(process.cwd(), 'file.html'))
mustache.render(temlateFile, props)
const readableStream = this.getReadableStreamFromString(htmlString)
const formData = new FormData() // from 'form-data'
formData.append('file', options.file, { filename: options.fileName })
const formHeaders = formData.getHeaders()
return await axios.send<Buffer>(
{
method: 'POST',
url: 'https://pdf-generator-service-url/pdf',
data: formData,
headers: {
...formHeaders,
},
responseType: 'arraybuffer', // ! important
},
)
}
getReadableStreamFromString(str: string): Readable {
const bufferHtmlString = Buffer.from(str)
const readableStream = new Readable() // from 'stream'
readableStream._read = () => null // workaround error
readableStream.push(bufferHtmlString)
readableStream.push(null) // mark end of stream
return readableStream
}
For anyone who wants to upload files from their local filesystem (actually from anywhere with the right streams architecture) with axios and doesn't want to use any external packages (like form-data).
Just create a readable stream and plug it right into axios request function like so:
await axios.put(
url,
fs.createReadStream(path_to_file)
)
Axios accepts data argument of type Stream in node context.
Works fine for me at least in Node v.16.13.1 and with axios v.0.27.2

Fetch API SyntaxError: Unexpected token { in JSON at position 169681

Im trying to make an HTTP request using fetch, but it's blowing up with the error: "SyntaxError: Unexpected token { in JSON at position 169681". This is my request function:
async getOportunidades() {
try {
const response = await fetch('https://gcsupport.internal.vodafone.com/bpa/webservices/GCCRM.asmx/GetCardsLeadsList',
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify({userId: 29188,tipoAplic:'T'})
});
const data = await response.json();
this.listaOportunidades = data;
return data
} catch(e) {
console.log(e);
}
}
Looking at the response at Chrome developer tools all seems fine:
and after inspecting it seems I am receiving my json data as expected, and the json string is well formed, but for some reason it "breaks" on position 169681.
Is there like a size limit on the response?!
Just for the sake of my sanity I tried to make the same request using Jquery AJAX and everything runs fine!! Thing is, I don't want to use Jquery on my project. Anyone more experienced with Fetch has any idea why this is happening?
*********MY AJAX CALL********
$.ajax({
url:'https://gcsupport.internal.vodafone.com/bpa/webservices/GCCRM.asmx/GetCardsLeadsList',
type: 'POST',
data: {userId: 29188, tipoAplic: 'T'},
success: function(data) {
console.log(data)
},
error: function(xhr, status, error) {
console.log(xhr, status, error)
}
})
******webservice code*******
Sorry if this is a duplicate question but all the issues I could find were related to "Unexpected token < at position 0" which is not my case.
Thanks in advance
Cheers
Your web service is not handling JSON requests correctly. I've created a fetch example below that uses form data that should work. $.ajax interprets the object given as form data which is why it works.
What's happening is that your web service outputs BOTH data generated from JSON body and form data. It needs to be fixed to immediately return after handling JSON body, and not continuing to try to interpret form data (which in the case of a JSON body is blank).
tl;dr Web service is bugged. Does not end writing response after using JSON body data to generate response. So, after .write(responseFromJSONData()) it doesn't return and break, and tries to continue to .write(responseFromFormData([blankFormData])), resulting in two JSON objects being attached to your response.
async getOportunidades() {
try {
const response = await fetch('https://gcsupport.internal.vodafone.com/bpa/webservices/GCCRM.asmx/GetCardsLeadsList',
{
headers: {
'Accept': '*/*',
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
method: 'POST',
body: new URLSearchParams({userId: 29188,tipoAplic:'T'})
});
const data = await response.json();
this.listaOportunidades = data;
return data
} catch(e) {
console.log(e);
}
}
var data = JSON.stringify({"userId":29188,"tipoAplic":"T"});
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function() {
if(this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://gcsupport.internal.vodafone.com/bpa/webservices/GCCRM.asmx/GetCardsLeadsList");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(data);
Try this one.

SyntaxError: Unexpected token r in JSON at position 0 on reactjs login page

I have been trying to make a login page in reactjs but it's throwing me an error in console like
SyntaxError: Unexpected token r in JSON at position 0 but I got 200 status code in network tab and also I'm getting "redirect" in both response and preview tab under the network tab.
I tried the same code(except it was if(response.ok) this time) with another server of my friend and it successfully redirects it to another page
This is the code that I've been trying: is response.data not correct for reactjs?
performLogin = async () => {
var body = {
password: this.state.password,
email: this.state.email
};
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify(body)
};
const url = "/api/authenticate";
try {
const response = await fetch(url, options);
const result = await response.json();
console.log(response); //nothing is showing in console for this statement
if (response.data == "redirect") {
this.props.history.push(`/verifyOtp/${this.state.email}`);
} else {
console.log("login failed");
window.alert("login failed");
}
} catch (error) {
console.error(error);
}
};
edit: I also tried it in postman and it gives "redirect" as response in postman so the api must be working fine
Your problem is in this line
const result = await response.json();
Your response is ok, everything is ok, but when you try to do response.json() and the response from the request isn't a valid json (maybe just a normal text), it will give you that error.
Because response can be a text or a json, you need to do some checking. Where is how to check if response is a json
This is kind of bad because on every request you will need to do this type of checking (transform it to text, try to parse, bla bla...), so What I recommend it you to use something better than fetch.
Axios is very good because it already do that checking.
For your example:
performLogin = async () => {
var body = {
password: this.state.password,
email: this.state.email
};
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify(body)
};
const url = "/api/authenticate";
try {
const response = await fetch(url, options); // Fetch the resource
const text = await response.text(); // Parse it as text
const data = JSON.parse(text); // Try to parse it as json
// Do your JSON handling here
} catch(err) {
// This probably means your response is text, do you text handling here
}
}

I'm trying to send JavaScript data to my NodeJS server

So I'm trying to send geolocation data to NodeJS via a POST request but when I console log the data in my NodeJS code it just shows an empty object.
I tested it already with postman and I can receive the data without a problem. I think the problem resides in the client side of my app
//**This is in the client Side(pure JS);
async function getWeather(position){
let coords ={
lat: position.coords.latitude,
long: position.coords.longitude
}
const options = {
method: "POST",
body: JSON.stringify(coords),
headers: {
"Content-Type": "aplication/json"
}
};
let response = await fetch("http://localhost:3000/weather", options);
let location = await response.json();
}
.
//**This is in the server side
app.post('/weather',(req,res)=>{
let coords = req.body;
console.log(coords); //This shows an empty object
res.sendStatus(200);
});
On your client side you can try this code. You can replace the url with your endpoint and try to fetch the result. As shown below, I'm getting the response back in data after executing the script.
I hope this helps.
(async () => {
const rawResponse = await fetch('https://httpbin.org/post', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({lat: 10, long: 20})
});
const content = await rawResponse.json();
console.log(content);
})();

Add parameters to post request using js on client side

I'm developing a "TODO" app using node.js and mongodb.
I'm trying to post a new task from the client but I didn't success to pass parameters to the server and from there to the database.
Client code:
<script>
function addData(item, url) {
var text = document.getElementById("myTask").value;
return fetch('/todos',{
method: 'post',
body: text
}).then(response => response.json())
.then(data => console.log(data));
}
</script>
Server code:
app.post('/todos',(req,res) =>{
console.log("\n\n req.body is: \n\n",req.body);
var todo = new Todo({
text: req.body.text});
todo.save().then((doc) =>{
res.send(doc);
console.log(JSON.stringify(doc,undefined,2));
},(err) =>{
res.status(400).send(err); //400 = unable to connect
console.log("Unable to save todo.\n\n\n" , err);
});
});
And the problem is that the client doesn't send the body to the server,
and the body is null on the server side:
See the logs here
(as you can see: req.body = {})
In the js code, I tried to pass the body parameter but I guess I did something wrong so I want to know the best way to pass parameters back to the server (not only the body but text, time and etc)
Thank in advance,
Sagiv
I think that you are missing something. Try to use name of param
body: JSON.stringify({data: text})
OR
read here Fetch: POST json data
I used this code:
(async () => {
const rawResponse = await fetch('https://httpbin.org/post', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({a: 1, b: 'Textual content'})
});
const content = await rawResponse.json();
console.log(content);
})();
and now I succeeded to pass data to the request.
Thanks everybody

Categories

Resources