Issue downloading Twilio Recording in Twilio Rooms - node.js

I have some code to download a recording from Twilio
getRecordingMedia: function (recordingId) {
var client = new Twilio(config.twillio.apiKey, config.twillio.apiSecret, { accountSid: config.twillio.accountId });
var uri = `https://video.twilio.com/v1/Recordings/${recordingId}/Media`;
var response = client.request({ method: "POST", uri: uri });
var mediaLocation = JSON.parse(response.body).location;
request.get(mediaLocation, (err, res, media) => {
return media;
});
}
I get the following error:
SyntaxError: Unexpected token u in JSON at position 0
I looked at the response object and its actually a promise. So, it seems like the documentation is incorrect in the sense that it doesn't handle the promise "then()"
I went ahead and changed the code to use the promise
var response = client.request({ method: "POST", uri: uri }).then((object) => {console.log(object);});
And I actually have an error logged
{ statusCode: 405,
body: '{"code": 20004, "message": "Method not allowed", "more_info": "https://www.twilio.com/docs/errors/20004", "status": 405}' }
I looked at the documentation on the referred link, but it didn't help me much.
Additionally If I open the url https://video.twilio.com/v1/Recordings/${recordingId}/Media in my browser and enter the credentials I get the recording.
So, need help in figuring out if the documentation is incorrect (as to the promise - https://www.twilio.com/docs/api/video/recordings-resource#code-retrieve-a-recording) and why Im getting the error with code 20004.
Thanks

The explaination in the error link says it all. You are using the wrong request method.
The documentation says:
HTTP GET to /Media subresource
HTTP POST
Not supported.
Your code says:
var response = client.request({ method: "POST", uri: uri });
So of course it works in your browser, as browsers make GET requests...

Related

TypeError: Failed to fetch from http site

Here is my nodejs code that works perfectly with https site.
app.use(cors({ origin: '*' }));
app.use(express.json())
app.use("/user", userRouter);
app.use("/mention", mentionRouter);
app.use("/request", requestRouter);
But the problem is if I send the request from any HTTP site, I get an error saying TypeError: Failed to fetch and get no response. Here is my frontend code.
const response = await fetch(WEB_URL + "mention", {
method: "POST",
body: JSON.stringify({
to: users,
text,
link: window.location.toString(),
}),
headers: {
"x-access-token": accessToken,
"Content-Type": "application/json",
},
});
I tried answers from this Getting "TypeError: failed to fetch" when the request hasn't actually failed but not working.
Sorry to be one of those people, but your variables are not defined in your snippet so I can't really see what you have defined. Example:
const response = await fetch(WEB_URL + "mention",
Nobody knows what WEB_URL means and it can be apart of the problem.
Also, window.location can be used like http://example.com/, but it is an object so it could print "[object Object]". Instead, try using window.location.href. Your problem most likely is that the Fetch JS API is not available with HTTP sites for security reasons. There's not much more to the problem.

Axios GET request sends empty req.body to server

I'm trying to make a GET request in my React app but Axios seems to send an empty request body for some reason. I know there's (most likely) nothing wrong in the backend as I'm able to make the requests perfectly fine with Insomnia. I've tried the following till now and none of the seem to work:
const response = await axios.get(URL, { email })
const response = await axios({
method: "get",
url: URL,
data: { email }
})
I'm using the express.json() middleware in the backend.
From the RFC 7231
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
So do not rely on body data for GET request and use appropriate HTTP method like POST, PUT etc.
Moreover, if you want to send Query params with your GET request, both code snippets you shared above will not work. Instead do it like below.
// using get method
const response = await axios.get(URL, {
params: {
ID: 12345
}
});
// using Axios API
const response = await axios({
method: "get",
url: URL,
params: {
ID: 12345
}
});

Why am I getting 404 ("Resource media not found") on the media upload from the docs?

The docs for uploading rich media to LinkedIn (https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/rich-media-shares#upload-rich-media) say to make a POST to https://api.linkedin.com/media/upload with form data. As far as I can tell I am doing that correctly using request-promise on my Node server, but I am still getting a 404.
Initially I had a problem with my file, but now I think I am properly creating a Buffer. Even if I'm not, that was preventing me from even making the request, and now I am and I don't think that would cause a 404.
I have also tried using 1.0.0 and 2.0.0 versions of the X-Restli-Protocol-Version (LinkedIn API thing).
// See LinkedIn docs on Rich Media shares https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/rich-media-shares
const stream = require('stream');
const rp = require('request-promise')
async function postRichMediaShare(accessToken) {
try {
const file = await rp({
method: 'get',
url: 'https://local-image-bucket.s3.amazonaws.com/Artboard+copy.png'
});
// Buffer magic
const buffer = new Buffer.from(file);
const bufferStream = new stream.PassThrough();
bufferStream.end( buffer );
bufferStream.pipe( process.stdout );
const options = {
method: 'post',
url: 'https://api.linkedin.com/v2/media/upload',
headers: { 'X-Restli-Protocol-Version': '2.0.0',
"Authorization": `Bearer ${accessToken}` },
formData: {
file: {
value: bufferStream,
options: {
filename: 'Artboard+copy.png',
contentType: 'image/png'
}
}
},
};
const response = await rp(options);
console.log("response", response);
return response;
} catch (error) {
throw new Error(error);
}
}
Instead of the response suggested in the docs, I'm getting this error message from LinkedIn:
error: "{"serviceErrorCode":0,"message":"Resource media does not exist","status":404}"
I'm an idiot. 404 should be expected because I'm requesting https://api.linkedin.com/v2/media/upload and the docs say https://api.linkedin.com/media/upload (no v2/). I believe every other call is versioned. Perhaps an empowered LinkedIn employee reading this could make a route for v2/ that does all the same stuff.
Note, there may be other problems with the code above, I am still struggling but now I'm working on things outside the scope of this question about 404.

Post request with Node fails but works with Python

I'm trying to use a sentiment analysis API for some tweets I've streamed. The API in question is this: http://sentiment.vivekn.com/docs/api/. I've done this before in Python before and it worked as expected. I made a post request using the requests library and sent a JSON object with my content. The JSON object looked something like this:
{
"txt": "The content of the tweet."
}
In Python, sending the post request looked something like this:
url = "http://sentiment.vivekn.com/api/text/"
data_dict = {
"txt": "hi"
}
r = requests.post(url,json.loads(json.dumps(data_dict)))
print(r.text)
Now I'll admit I'm new to Javascript and web based programming in general, but I assume the logic should be similar in both languages. I tried using the XMLHttpRequest method but it always returned an internal server error with status code: 500.
The website works, it takes post requests and responds with the analysis, but I can't get it to work with Node. This is what I'm working with in Javascript:
const rp = require('request-promise');
var options = {
method: 'POST',
uri: 'http://sentiment.vivekn.com/api/text/',
body: {
"txt": "This is a very negative sentence, so we should get a negative analysis!"
},
json: true // Automatically stringifies the body to JSON
};
rp(options)
.then(function (parsedBody) {
console.log("Request received");
console.log(parsedBody);
})
.catch(function (err) {
console.log("Something went wrong\n" + err);
});
It always catches an error with status code 500. I've tried several other methods including making the request with XMLHttpRequest. Nothing seems to work. It would be great if someone could point out where I'm going wrong.
This isn't an answer, but I thought it useful to show some code that evokes a different response, which may be a clue that will help debug the problem.
I get the same response with curl:
jim-macbookpro:~/development/node/so$ curl -X POST 'http://sentiment.vivekn.com/api/text/' -H "Content-Type: application/json" -d '{"txt": "hi"}'
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in theapplication.</p>
I changed the example to use 'node-fetch', and I don't get 500, rather I get 405 - METHOD NOT ALLOWED.
My suspicion is that this is a problem with the server being somehow very particular about the format of the request.
I hope this helps.
const fetch = require('node-fetch');
fetch('http://sentiment.vivekn.com/api/text', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
txt:
'This is a very negative sentence, so we should get a negative analysis!'
})
})
.then(function(parsedBody) {
console.log('Request received');
console.log(parsedBody);
})
.catch(function(err) {
console.log('Something went wrong\n' + err);
});

Post call from Nodejs

I am trying to get an authentication token from an API.
the request is supposed to look like
POST /oauth2/token HTTP/1.1
Host: mysageone.ca.sageone.com
client_id=4b64axxxxxxxxxx00710&
client_secret=iNumzTxxxxxxxxxxhVHstrqWesH8tm9&
code=12a0f9c12cxxxxxxxxxxxxxxx92a48cc1f237ead&
grant_type=authorization_code&
redirect_uri=https://myapp.com/auth/callback
My current code keeps giving me status 400. I have tried to modify the headers but it doesn't work. i have also tried to make the required parameters part of the path using ?.
const http = require('http');
var options = {
hostname: 'app.sageone.com',
path: '/oauth2/token',
method: 'POST',
headers: {
"client_id":"xxxxx",
"client_secret":"xxxxx",
"code":"xxxxxx",
"grant_type":"authorization_code",
"redirect_uri":"https://some link"
}
};
console.log('in users file point 2');
var req1 = http.request(options, (res1) => {
console.log('statusCode:', res1.statusCode);
console.log('headers:', res1.headers);
console.log('message',res1.statusMessage);
res1.on('data', (d) => {
res.json(d);
});
});
req1.on('error', (e) => {
console.error('error starts here',e);
});
req1.end();
});
Looks to me like your problem is not with Node.js, but with your use of Sage One's api. This is the relevant documentation that might solve your problem.
From a quick glance it looks like you want to send a GET not a POST, and you should send those parameters in the URL. Here is the example URL they give:
https://www.sageone.com/oauth2/auth?response_type=code&client_id=4b64axxxxxxxxxx00710&redirect_uri=https://myapp.com/auth/callback


&scope=full_access
I've never used Sage One before, but that would match my experience with other OAuth APIs.

Resources