Can't connect to twilsoc - reactjs

I am getting this bizarre twilsoc error when trying to connect to twilio through node and react. I cannot figure out how to fix this. This seems to be happening on the server side of my application. I have generated the token based on the instructions on the website.
index.js:1437 Error: Can't connect to twilsock
at Upstream.send (upstream.js:245)
at TwilsockClient.post (client.js:280)
at network.js:176
at Retrier.<anonymous> (network.js:114)
at Retrier.emit (events.js:136)
at Retrier.attempt (retrier.js:56)
at retrier.js:111
Here is on the front end
componentDidMount() {
fetch("http://localhost:3001/chat/token", {
headers: { 'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': "*",
'Access-Control-Allow-Headers': "*"
},
method: 'POST',
body: `identity=${encodeURIComponent(this.props.username)}`
})
.then(res => res.json())
.then(data => Chat.create(data.token))
.then(this.setupChatClient)
.catch(this.handleError);
}
here is the server
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(pino);
app.use(cors());
const sendTokenResponse = (token, res) => {
res.set('Content-Type', 'application/json');
res.send(
JSON.stringify({
token: token.toJwt()
})
);
};
app.get('/api/greeting', (req, res) => {
const name = req.query.name || 'World';
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ greeting: `Hello ${name}!` }));
});
app.get('/chat/token', (req, res) => {
const identity = req.query.identity;
const token = chatToken(identity, config);
sendTokenResponse(token, res);
});
app.post('/chat/token', (req, res) => {
console.log('this is firing on the backend')
const identity = req.query.identity;
const token = new AccessToken('AC821b3924fcf9577a0eb017c4b21b----', "SK8c95cf6ba0e4a0ec5499d12ae4d----", "o4x7JC9xTEAsZC06SVsnfb2xZU9n----");
const chatGrant = new ChatGrant({
serviceSid:"ISdd3f2b55594f45038ac88d84b78e----" ,
});
token.addGrant(chatGrant);
token.identity = identity;
sendTokenResponse(token, res);
});
app.get('/video/token', (req, res) => {
const identity = req.query.identity;
const room = req.query.room;
const token = videoToken(identity, room, config);
sendTokenResponse(token, res);
});
app.post('/video/token', (req, res) => {
const identity = req.body.identity;
const room = req.body.room;
const token = videoToken(identity, room, config);
sendTokenResponse(token, res);
});
app.listen(3001, () =>
console.log('Express server is running on localhost:3001')
);

the latest versions of express are not using bodyparser.json any more, it's now a part of express, try using:
express(express.json())
instead of
express(bodyParser.json())

Twilio developer evangelist here.
This actually looks like my code 😄. This is good news, because it's from my post on how to proxy to an Express server with React so you can avoid CORS issues. If you are using my repo then you should be able to start both the server and the front end applications by running:
npm run dev
Then you don't need to fetch from an absolute URL, instead you can just use:
fetch("/chat/token", {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
body: `identity=${encodeURIComponent(this.props.username)}`
});
And the webpack dev server will proxy the request through to the Express application.
Let me know if that helps at all.
Quick note on CORS
I noticed you're trying to pass the headers 'Access-Control-Allow-Origin': "*", 'Access-Control-Allow-Headers': "*" from your fetch request. However they are not request headers, but response headers. If you do need CORS headers then you need your Express server to return them as part of the response.
But as I said, the way I set up the code for this post should mean that you don't need CORS at all. So you shouldn't have to worry about this for now.

If you're using express, the easiest way to achieve this is using the cors module.
First, install it using the next code:
npm install cors
Next, put the cors middleware in the express app:
app.use(cors())
If you want to learn more, read the cors module docs https://www.npmjs.com/package/cors

If none of these solutions work (they didn't for me), here's something that might be helpful which made the error go away for me: https://stackoverflow.com/a/56671780/404541

I had this problem because I mispelled the SIDs I was using when getting the token through the rest API. I made sure the SIDs were correct and the error went away.

Related

ReactJS http-proxy-middleware request header not set properly

TL;DR: How to actually change a request header in http-proxy-middleware?
To get around some CORS errors I set up a local proxy using the http-proxy-middleware module. In addition to setting the mode of my request to "no-cors" I need to change an additional header: "Content-Type". However, this seems to be not working. In fact, I cannot even change the response headers on a redirected (through my proxy) request. For local requests (fetching pages etc) I am able to change the response headers but even then I am unable to change the request headers.
This is my setupProxy.js:
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use((req, res, next) => {
req.header("Content-Type", "application/json");
res.header("Access-Control-Allow-Origin", "*");
next();
});
function onProxyReq(proxyReq, req, res) {
console.log("test 1");
proxyReq.setHeader("Content-Type", "application/json");
req.header("Content-Type", "application/json");
}
app.use(
"/api",
createProxyMiddleware({
target: "https://my-domain.com/",
changeOrigin: true,
onProxyReg: { onProxyReq },
// secure: true,
// on: {
// proxyReq: requestInterceptor(async (buffer, proxyReq, req, res) => {
// console.log("test 2");
// }),
// },
logger: console,
})
);
};
And this is the code that sends the request:
try {
let requestOptions: RequestInit = {
method: "POST",
mode: "no-cors",
headers: {
accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
email: { username },
password: { password },
}),
};
fetch("https://localhost:3000/api/path/to/login/api", requestOptions)
.then(async function (response) {
console.log(response);
if (!response.ok) {
setError("Error code: " + response.status.toString());
}
return response.json();
})
.then(function (response) {
console.log(response);
});
} catch (e) {
console.log(e);
}
I'm getting an error back from the API itself (the CORS avoidance is working):
Content type 'text/plain;charset=UTF-8' not supported
And indeed, when I use the Chrome inspector to look at the request, the request header is set to "text/plain;charset=UTF-8". I tried setting the response header content type to "text/plain" but even that remains untouched. But how can this be after routing the request through my proxy?
EDIT:
Ok so I found out part of the problem. Setting the mode to "no-cors" in my fetch request alters the headers. But this still doesn't explain why my proxy can't edit the request headers. When I remove the "no-cors" mode but copy the headers it produced, the server is giving me error 400 (bad request). This means it is not receiving the same request as before, but this baffles me since I copied all the headers manually.
EDIT2:
Actually, I found out that when I remove mode: "no-cors" and set the "Sec-Fetch-Mode" header to "no-cors" manually, it is still set to "cors" in the actual request!
EDIT3:
I tried sending my request through ReqBin and it works there :)! So at least we know my request is correct.
I found out that changing the "content-type" header in cors mode is simply not allowed. The solution is to first send a preflight request with the options. When this has been accepted, you can send the actual request.
You can send the request through ReqBin, it will take the necessary steps to complete the request succesfully. It will even generate code to reproduce the request for you.
var url = "https://thedomain.com/path/to/api";
var xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
console.log(xhr.status);
console.log(xhr.responseText);
}
};
var data_ = '{"email": "*************", "password": "******"}';
xhr.send(data_);
And this works! :)

Problem with CORS on React and PUT Ajax PUT request

I have an issue with my app. I use Express/node for the API and try to access it with React which works fine with Axios.
now I tried a DevExpress grid component to display data. fetching data is working fine but if I want to edit and save I get always a CORS error.
My settings on express:
app.use(
cors({
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
})
);
The API looks like this:
router.put('/dataToEdit', auth, (req, res) => {
MasterData.updateData(req, res);
});
If I want to call and bind to the grid:
const dataSource = createStore({
key: 'helperboxTypeId',
loadUrl: `${url}/getAlldataToEdit`,
insertUrl: `${url}/dataToEdit`,
updateUrl: `${url}/dataToEdit`,
deleteUrl: `${url}/dataToEdit`,
onBeforeSend: (method, ajaxOptions) => {
ajaxOptions.headers = {
'Content-Type': 'application/json',
'x-auth-token': localStorage.token,
};
ajaxOptions.crossDomain = true;
},
});
I tried it I think with every possible constellation of settings and I'm searching for about 1 day in several forums before I asked this :)
maybe somebody is using the same component and can help somehow.
the error is:
Access to XMLHttpRequest at 'http://localhost:5000/api/masterData/dataToEdit' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Another solution could be that I use Axios there but was not able to integrate it.
Many thanks in advance!
You should allow Access-Control-Allow-Origin as following:
app.all('/*', function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
Finally i found it thanks for the eye opener comments :)
the problem was that i missed at the top of the backend server.js a line i added weeks ago...
app.get('/', (req, res) => res.send(text.SERVER_API_RUNNING));
and seems if i add the cors setting then it works only for a part of my API's.

How to send an SMS using Twilio through frontend with react?

I've read the Twilio documentation and I can't find a way to send a simple SMS from the frontend using JavaScript/React.
The Twilio documentation just shows how to do that using Node.js(server side).
Actually, I found the documentation a bit awkward because they don't explain the how to do that using the most common programme language on the web.
I'm using postman and it works fine, but on my react code doesn't.
The code below was exported from Postman:
var settings = {
"async": true,
"crossDomain": true,
"url": "https://api.twilio.com/2010-04-01/Accounts/AC62761f2bae5c5659cc5eb65d42e5d57e/Messages.json",
"method": "POST",
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic hashedAuthToken",
"Cache-Control": "no-cache",
"Postman-Token": "0s41f5ac-2630-40c4-8041-1e5ee513f20d"
},
"data": {
"To": "+353838173123",
"From": "+18634000432",
"MessagingServiceSid": "MG3d622e63a343e11a2032b1414560f227",
"Body": "Test, hi"
}
}
$.ajax(settings).done(function (response) {
console.log(response);
});
PS: The tokens above was modified. It won't work if you are not using your own credential.
Twilio developer evangelist here.
There is a huge problem with what you are trying to attempt here.
Putting your Twilio credentials into the front end (or into a Stack Overflow question/answer) leaves them open to anyone to read your source code and steal them. A malicious attacker can take those credentials and abuse your account with them.
I recommend you refresh your Auth Token in your Twilio console now. You should consider them compromised.
What you should do is build an SMS sending service on your own server side and then call that service from your React front end. There is a blog post on sending SMS with Twilio on React that is worth reading and I will try to put something together to show it too.
Update:
I wrote a blog post explaining how to send an SMS with React and Twilio. The important thing is that you should perform the API call in your server (in the blog post, it's an Node.js/Express server but you can use whatever server-side tech you want). Then you send the message from your React application to the server using fetch (or axios or XMLHttpRequest if you want).
You can use the method below to do that easily.
sendSMSTwilio(message) {
const url = Config.sms.url;
const accountSid = Config.sms.accoundId;
const authToken = Config.sms.authToken;
const auth = 'Basic ' + new Buffer(Config.sms.accountSid + ':' + Config.sms.authToken).toString('base64');
const details = {
To: message.to,
From: message.from,
MessagingServiceSid: Config.sms.serviceSid,
Body: message.text
};
const formBody = [];
for (var property in details) {
const encodedKey = encodeURIComponent(property);
const encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + '=' + encodedValue);
}
const body = formBody.join('&');
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
Authorization: auth
},
body
};
return new Promise((resolve, reject) => {
return fetch(url, options)
.then((response) => {
return resolve(response);
})
.then((responseJson) => {
return resolve(responseJson);
})
.catch((error) => {
return reject(error);
});
});
}
You can call and receive the promise response like that:
this.sendSMSTwilio()
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log('Error SMS sender', err);
});

Nodejs sending external API POST request

i am trying to send a POST request from my angularjs controller to the nodejs server which should then send a full POST request to the external API and this way avoid CORS request as well as make it more secure as i'm sending relatively private data in this POST request.
My angularjs controller function for making the post request to the nodejs server looks like this and it works fine:
var noteData = {
"id":accountNumber,
"notes":[
{
"lId":707414,
"oId":1369944,
"nId":4154191,
"price":23.84
}
]
}
var req = {
method: 'POST',
url: '/note',
data: noteData
}
$http(req).then(function(data){
console.log(data);
});
Now the problem lies in my nodejs server where i just can't seem to figure out how to properly send a POST request with custom headers and pass a JSON data variable..
i've trierd using the nodejs https function since the url i need to access is an https one and not http ,i've also tried the request function with no luck.
I know that the url and data i'm sending is correct since when i plug them into Postman it returns what i expect it to return.
Here are my different attempts on nodejs server:
The data from angularjs request is parsed and retrieved correctly using body-parser
Attempt Using Request:
app.post('/buyNote', function (req, res) {
var options = {
url: 'https://api.lendingclub.com/api/investor/v1/accounts/' + accountNumber + '/trades/buy/',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': apiKey
},
data = JSON.stringify(req.body);
};
request(options, function (error, response, body) {
if (!error) {
// Print out the response body
// console.log(body)
console.log(response.statusCode);
res.sendStatus(200);
} else {
console.log(error);
}
})
This returns status code 500 for some reason, it's sending the data wrongly and hence why the server error...
Using https
var options = {
url: 'https://api.lendingclub.com/api/investor/v1/accounts/' + accountNumber + '/trades/buy/',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': apiKey
}
};
var data = JSON.stringify(req.body);
var req = https.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
req.write(data);
req.end();
Https attempt return a 301 status for some reasons...
Using the same data, headers and the url in Postman returns a successful response 200 with the data i need...
I don't understand how i can make a simple http request...
Please note: this is my first project working with nodejs and angular, i would know how to implement something like this in php or java easily, but this is boggling me..
So after a lot of messing around and trying different things i have finally found the solution that performs well and does exactly what i need without over complicating things:
Using the module called request-promise is what did the trick. Here's the code that i used for it:
const request = require('request-promise');
const options = {
method: 'POST',
uri: 'https://requestedAPIsource.com/api',
body: req.body,
json: true,
headers: {
'Content-Type': 'application/json',
'Authorization': 'bwejjr33333333333'
}
}
request(options).then(function (response){
res.status(200).json(response);
})
.catch(function (err) {
console.log(err);
})

OPTIONS method not allowed when asking for OAuth2 token [duplicate]

I have a REST api created with the restify module and I want to allow cross-origin resource sharing. What is the best way to do it?
You have to set the server up to set cross origin headers. Not sure if there is a built in use function or not, so I wrote my own.
server.use(
function crossOrigin(req,res,next){
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
return next();
}
);
I found this from this tutorial. http://backbonetutorials.com/nodejs-restify-mongodb-mongoose/
The latest version of Restify provides a plugin to handle CORS.
So you can now use it like this:
server.use(restify.CORS({
// Defaults to ['*'].
origins: ['https://foo.com', 'http://bar.com', 'http://baz.com:8081'],
// Defaults to false.
credentials: true,
// Sets expose-headers.
headers: ['x-foo']
}));
This works for me:
var restify = require('restify');
var server = restify.createServer();
server.use(restify.CORS());
server.opts(/.*/, function (req,res,next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", req.header("Access-Control-Request-Method"));
res.header("Access-Control-Allow-Headers", req.header("Access-Control-Request-Headers"));
res.send(200);
return next();
});
server.get('/test', function (req,res,next) {
res.send({
status: "ok"
});
return next();
});
server.listen(3000, function () {
console.log('%s listening at %s', server.name, server.url);
});
This is what worked for me:
function unknownMethodHandler(req, res) {
if (req.method.toLowerCase() === 'options') {
console.log('received an options method request');
var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version', 'Origin', 'X-Requested-With']; // added Origin & X-Requested-With
if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
res.header('Access-Control-Allow-Methods', res.methods.join(', '));
res.header('Access-Control-Allow-Origin', req.headers.origin);
return res.send(204);
}
else
return res.send(new restify.MethodNotAllowedError());
}
server.on('MethodNotAllowed', unknownMethodHandler);
I this code was taken from https://github.com/mcavage/node-restify/issues/284
CORS Plugin is deprecated in favor of https://github.com/Tabcorp/restify-cors-middleware. (Source: https://github.com/restify/node-restify/issues/1091.)
Below is a sample code regarding how to use
const corsMiddleware = require('restify-cors-middleware')
const cors = corsMiddleware({
preflightMaxAge: 5, //Optional
origins: ['http://api.myapp.com', 'http://web.myapp.com'],
allowHeaders: ['API-Token'],
exposeHeaders: ['API-Token-Expiry']
})
server.pre(cors.preflight)
server.use(cors.actual)
If anyone comes across this as of Feb 2018 there seems to be a bug that's been introduced, I couldn't get the restify-cors-middleware to work.
I'm using this work around for now:
server.pre((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
next();
});
To enable CORS for basic authentication I did the following. It did not work until the .pre methods were used instead of the .use methods
server.pre(restify.CORS({
origins: ['https://www.allowedip.com'], // defaults to ['*']
credentials: true,
headers: ['X-Requested-With', 'Authorization']
}));
server.pre(restify.fullResponse());
function unknownMethodHandler(req, res) {
if (req.method.toLowerCase() === 'options') {
var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version', 'Origin', 'X-Requested-With', 'Authorization']; // added Origin & X-Requested-With & **Authorization**
if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
res.header('Access-Control-Allow-Methods', res.methods.join(', '));
res.header('Access-Control-Allow-Origin', req.headers.origin);
return res.send(200);
} else {
return res.send(new restify.MethodNotAllowedError());
}
}
server.on('MethodNotAllowed', unknownMethodHandler);
I do it like this on my restify base app:
//setup cors
restify.CORS.ALLOW_HEADERS.push('accept');
restify.CORS.ALLOW_HEADERS.push('sid');
restify.CORS.ALLOW_HEADERS.push('lang');
restify.CORS.ALLOW_HEADERS.push('origin');
restify.CORS.ALLOW_HEADERS.push('withcredentials');
restify.CORS.ALLOW_HEADERS.push('x-requested-with');
server.use(restify.CORS());
you need to use restify.CORS.ALLOW_HEADERS.push method to push the header u want into restify first, then using the CORS middleware to boot the CORS function.
MOST OF THE PREVIOUS ANSWERS ARE FROM 2013 AND USE DEPRECATED EXAMPLES!
The solution (in 2017 at least) is as follows:
npm install restify-cors-middleware
Then in your server javascript file:
var corsMiddleware = require('restify-cors-middleware');
var cors = corsMiddleware({
preflightMaxAge: 5,
origins: ['*']
});
var server = restify.createServer();
server.pre(cors.preflight);
server.use(cors.actual);
And add whatever additional other options work for you. My use case was creating a localhost proxy to get around browser CORS issues during devolopment. FYI I am using restify as my server, but then my POST from the server (and to the server) is with Axios. My preference there.
npm listing for restify-cors-middleware
This sufficed in my case:
var server = restify.createServer();
server.use(restify.fullResponse());
server.get('/foo', respond(req, res, next) {
res.send('bar');
next();
});
It wasn't necessary to server.use(restify.CORS());
Also, it appears server.use() calls must precede server.get() calls in order to work.
This worked for me with restify 7
server.pre((req, res, next) => {
res.header('Access-Control-Allow-Origin', req.header('origin'));
res.header('Access-Control-Allow-Headers', req.header('Access-Control-Request-Headers'));
res.header('Access-Control-Allow-Credentials', 'true');
// other headers go here..
if(req.method === 'OPTIONS') // if is preflight(OPTIONS) then response status 204(NO CONTENT)
return res.send(204);
next();
});
I am using Restify 7.2.3 version and this code worked for me very well.
You need to install the restify-cors-middleware plugin.
const corsMiddleware = require('restify-cors-middleware')
const cors = corsMiddleware({
preflightMaxAge: 5, //Optional
origins: ['http://ronnie.botsnbytes.com', 'http://web.myapp.com'],
allowHeaders: ['API-Token'],
exposeHeaders: ['API-Token-Expiry']
})
server.pre(cors.preflight)
server.use(cors.actual)
const cors = require('cors');
const server = restify.createServer();
server.use(cors());
This worked for me
const restify = require('restify');
const corsMiddleware = require('restify-cors-middleware');
const cors = corsMiddleware({
origins: ['*']
});
const server = restify.createServer();
server.pre(cors.preflight);
server.use(cors.actual);
server.get('/api/products', (request, response) => {
response.json({ message: 'hello REST API' });
});
server.listen(3000, () => console.info(`port 3000`));
... is one brute-force solution, though you should be very careful doing that.

Resources