Im trying to replicate a facebook messenger bot but keep getting request is not defined.
Same code as facebook:
function callSendAPI(messageData) {
request({
uri: 'https://graph.facebook.com/v2.6/me/messages',
qs: { access_token: PAGE_ACCESS_TOKEN },
method: 'POST',
json: messageData
}, function (error, response, body) {
if (!error && response.statusCode == 200) {
var recipientId = body.recipient_id;
var messageId = body.message_id;
console.log("Successfully sent generic message with id %s to recipient %s",
messageId, recipientId);
} else {
console.error("Unable to send message.");
console.error(response);
console.error(error);
}
});
}
My node server.js looks like this:
const express = require('express');
const bodyParser = require('body-parser');
//const request = express.request;
const PAGE_ACCESS_TOKEN = 'abc';
let app = express();
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
[...]
function sendTextMessage(recipientId, messageText) {
var messageData = {
recipient: {
id: recipientId
},
message: {
text: messageText
}
};
callSendAPI(messageData);
}
function callSendAPI(messageData) {..}
[...]
Am I missing something with express? Thanks
This example is making use of third-party Request module.
You could also use the native request like so: require('http').request(), if you want to, but I would say, that the request module is very common, and a good tool to use.
Your request, which is commented out, points to express.request. If used like request() will throw an error, since it's not a function. So, you should really use the Request module, or adjust the code to use native http.request.
Update 2020
The request module is deprecated now, so if you are reading this answer, use the native module or find a popular third-party library like Axios or others.
You have not installed request module.
First install it npm install --save request and then include it var request = require('request');
I got the same error but in a different context than yours; when I tried importing
import { Request } from 'express'
export class UserRequest extends Request {
user: UserEntity;
}
the problem was caused because of using class instead of interface
Related
I am having an API Service build on node js running on port 3001 and a web UI using REACT & running on port 3000. I have to POST details from Web page to the API in JSON Format. I am able to hit the API, however I could not get the JSON on the API. Its being received as {}. However the API is working fine from postman.
Could some one please share light on where i am missing.
Source code of API
const util = require('util')
const request = require("request");
const express = require('express')
const app = express();
const port = 3001
app.use(express.json());
app.use(express.urlencoded( {extended: false}));
const bodyParser = require('body-parser');
const { json } = require('express/lib/response');
app.post('/PostPatronDetailsone',(req,res) => {
async function run() {
try {
console.log('Request received from REACT ONE');
// parse application/json
app.use(bodyParser.json())
console.log(req.body);
// Respond back
res.send('Transaction Sent');
} finally {
// Ensures that the client will close when you finish/error
}
}
run().catch(console.dir);
});
app.listen(port, () => console.log('Server is listening at port ' + port));
Code Snippet of Web making the HTTP POST
import React from 'react';
class Signup extends React.Component {
constructor(props) {
super(props);
this.state = {
postId: null
};
}
async componentDidMount() {
// Simple POST request with a JSON body using fetch
let payload = {'first_name': 'TEST' };
var data = new FormData();
data.append( "json", JSON.stringify( payload ) );
const requestOptions = {
method: 'POST',
mode: 'no-cors',
headers: { 'Content-Type': 'application/json','Accept':'application/json' },
body: data,
redirect: 'follow'
};
var response = await fetch('http://localhost:3001/PostPatronDetailsone', requestOptions);
var data1 = await response.json();
var data2 = data1.text();
alert(data2);
//this.setState({ postId: data1.insertedid });
}
render() {
const { postId } = this.state;
return (
<div className="card text-center m-3">
<h5 className="card-header">Simple POST Request</h5>
</div>
);
}
}
export default Signup;
Console Output of API Service
Server is listening at port 3001
Request received from REACT ONE
{}
Request received from REACT ONE
{}
It is because you send formData, instead stringify the object and send it to body like this:
async componentDidMount() {
// Simple POST request with a JSON body using fetch
let payload = {first_name: 'TEST' };
const requestOptions = {
method: 'POST',
mode: 'no-cors',
headers: { 'Content-Type': 'application/json','Accept':'application/json' },
body: JSON.stringify(payload ),
redirect: 'follow'
};
var response = await fetch('http://localhost:3001/PostPatronDetailsone', requestOptions);
var data1 = await response.json();
var data2 = data1.text();
alert(data2);
//this.setState({ postId: data1.insertedid });
}
Please change the code as follows:
let payload = {'first_name': 'TEST' };
fetch('http://localhost:3001/PostPatronDetailsone',{
body:JSON.stringify(payload),
method:'post',
mode: 'no-cors',
headers: {
"Content-Type": "application/json"
},
}).then((res)=>res.json()).then((data)=>console.log(data));
And from controller in backend remove that line as you are already using express.json() which is equivalent to that line:
app.use(bodyParser.json()) // remove it
You have 3 key problems here:
You are posting a FormData object (which gets converted to a multipart/form-data encoding) and not JSON
You are setting no-cors mode which causes the browser to silently discard any instructions to do anything that would require CORS permission (such as setting the application/json content-type or reading the response)
There won't be a text() method on anything parsed from JSON
const data = {'first_name': 'TEST' };
const payload = JSON.stringify(data)
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json','Accept':'application/json' },
body: payload,
redirect: 'follow'
};
const response = await fetch('http://localhost:3001/PostPatronDetailsone', requestOptions);
const parsed_json = await response.json();
console.log(parsed_json);
You will also need to change the server-side code to grant permission to the JavaScript to read the response and send the JSON formatted request. Use the cors module for that.
app.use(cors());
Also note that body parsing middleware needs to be set up when the application starts and not in the middle of a route. The body-parser module has been obsoleted as Express has its features built-in now.
The following is good:
app.use(express.json());
The following is bad:
const bodyParser = require('body-parser');
and
app.use(bodyParser.json())
Your route code doesn't need to be any more complex than:
app.post('/PostPatronDetailsone', async (req,res) => {
console.log('Request received from REACT ONE');
console.log(req.body);
res.json('Transaction Sent');
});
Note that since you are trying to parse the response as JSON in the client side code, I've had to change send to json so that the server outputs JSON instead of plain text.
So I have a simple Heroku app that just signs people up to my Mailchimp contacts list. I have it working locally, but when deploying the app I get CORS errors.
I've tried adding withCredentials: true to my axios request and adding cors origin in my Express app, but it still doesn't work.
I have been going through all kinds of articles on cors issues trying to get this to work and understand why this is happening.
I've replaced some of the sensitive information with dummy text, but this is essentially how the request is being made and what the server is doing with the information.
React Code:
const submitForm = async (values) => {
const { email } = values;
try {
const payload = {
email_address: email
};
await axios.post("https://some-url.herokuapp.com", payload, { withCredentials: true });
handleMessage("Thank you for signing up.");
} catch (error) {
console.log(error.message);
handleMessage(error.message);
}
}
Express Code:
const cors = require('cors');
app.use(cors({
origin: `https://www.mycustomdomain.com/`,
credentials: true
}));
app.post('/', jsonParser, (req, res, next) => {
const { email_address } = req.body
if (!email_address) {
return res.status(400).json({
error: `Missing email in request body`
})
}
const data = {
members: [
{
email_address,
status: 'subscribed'
}
]
}
const payload = JSON.stringify(data);
const options = {
url: `https://mailchim-api.com`,
method: 'POST',
headers: {
Authorization: `auth authCode`
},
body: payload
}
request(options, (err, response, body) => {
if (err) {
res.status(500).json(err)
} else {
if (response.statusCode === 200) {
res.status(200).json(body)
}
}
})
})
My initial problem was that I didn't manually enter the env variables used in the Express app into Heroku.
I had to run heroku config:set APIKEY=SOME-PASSWORD in order to get all of my env variables to be used on Heroku.
https://devcenter.heroku.com/articles/config-vars
Because I didn't do this originally, I made the mistake of replacing all of my env variables with the actual strings which brought about the CORS issue. Mailchimp also deactivated my API key since the key was being published online. So it was actually a layered issue, not exactly a CORS issue, to begin with.
I would like to send an API request to https://api-test.onlineszamla.nav.gov.hu/invoiceService/queryTaxpayer and they expect an XML, as a sample provided below. What is the appropriate syntax in Node.js that processes this request? Unfortuantely I couldn't find this out from the API documentation.
EDIT: part of the XML contents will be from user data, part of it from input fields.
<?xml version="1.0" encoding="UTF-8"?><QueryTaxpayerRequest xmlns="http://schemas.nav.gov.hu/OSA/1.0/api">
<header>
<requestId></requestId>
<timestamp></timestamp>
<requestVersion></requestVersion>
<headerVersion></headerVersion>
</header>
<user>
<login></login>
<passwordHash></passwordHash>
<taxNumber></taxNumber>
<requestSignature></requestSignature>
</user>
<software>
<softwareId></softwareId>
</software>
<taxNumber></taxNumber>
</QueryTaxpayerRequest>
Use XML parser and then Set the response type as XML like below :
var xml = require('xml');
response.set('Content-Type', 'text/xml');
response.send(xml(YOUR_XML_OBJECT));
in the above I have used XML as the parser, you should be able to use any other available packages.
You can use a library like xmlbuilder to make creating xml string easier.
var builder = require('xmlbuilder');
var obj = {
root: {
xmlbuilder: {
repo: {
'#type': 'git', // attributes start with #
'#text': 'git://github.com/oozcitak/xmlbuilder-js.git' // text node
}
}
}
};
var xml = builder.create(obj).end({ pretty: true});
console.log(xml);
And then you can use any library to make the request and use the xml string above in the body.
This works for me awesome.
var Request = require("request");
const express = require("express");
const app = express();
app.use(express.urlencoded({extended: true}));
app.use(express.text())
app.post("/api/getXML", (req, res) => {
Request.post({
"headers": { "content-type": "text/plain; charset=utf-8"},
"url": "<url which return xml response>",
"body": req.body
}, (error, response, body) => {
if(error) {
console.error(error);
res.send(error)
}
console.log("XML body :",body);
res.send(body);
});
});
The idea got from the link https://www.thepolyglotdeveloper.com/2017/10/consume-remote-api-data-nodejs-application/
Hello I ve been trying to implement OneSignal API on my dashboard and I wonder if it is possible to make a API external call inside express server.
Here is an example:
var sendNotification = function(data) {
var headers = {
"Content-Type": "application/json; charset=utf-8",
"Authorization": "Basic NGEwMGZmMjItY2NkNy0xMWUzLTk5ZDUtMDAwYzI5NDBlNjJj"
};
var options = {
host: "onesignal.com",
port: 443,
path: "/api/v1/notifications",
method: "POST",
headers: headers
};
var https = require('https');
var req = https.request(options, function(res) {
res.on('data', function(data) {
console.log("Response:");
console.log(JSON.parse(data));
});
});
req.on('error', function(e) {
console.log("ERROR:");
console.log(e);
});
req.write(JSON.stringify(data));
req.end();
};
Here it is the app route
app.post('/path', function(req, res){
var message = {
app_id: "5eb5a37e-b458-11e3-ac11-000c2940e62c",
contents: {"en": "English Message"},
included_segments: ["All"]
};
sendNotification(message);
});
Thank you!
I wonder if it is possible to make a API external call inside express
server.
Sure, you can contact any external server from a node.js app with http.request() like you are showing or one of the higher level modules built on top of that like the request module.
Here's a simple example from the request module home page:
const request = require('request');
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // Show the HTML for the Google homepage.
}
});
Or, using promises:
const rp = require('request-promise');
rp('http://www.google.com').then(body => {
console.log(body);
}).catch(err => {
console.log(err);
});
EDIT Jan, 2020 - request() module in maintenance mode
FYI, the request module and its derivatives like request-promise are now in maintenance mode and will not be actively developed to add new features. You can read more about the reasoning here. There is a list of alternatives in this table with some discussion of each one. I have been using got() myself and it's built from the beginning to use promises and is simple to use.
you can use Axios client as Axios is a Promise based HTTP client for the browser as well as node.js.
Using Promises is a great advantage when dealing with code that requires a more complicated chain of events. Writing asynchronous code can get confusing, and Promises are one of several solutions to this problem.
First install Axios in your application using npm install axios --save
and then you can use this code
const axios = require('axios');
axios.get('api-url')
.then(response => {
console.log(response.data.status);
// console.log(response.data);
res.send(response.data.status);
})
.catch(error => {
console.log(error);
});
Kindly try out this solution. i used it and it worked for me.
var Request = require("request");
Request.get("http://httpbin.org/ip", (error, response, body) => {
if(error) {
return console.dir(error);
}
console.dir(JSON.parse(body));
});
You can use request-promise-native that uses native ES6 promises.
Install the request-promise-native package
npm install --save request
npm install --save request-promise-native
Use it as follows :
const request = require('request-promise-native');
const options = {
method: 'GET',
uri: 'https://www.google.com'
}
request(options).then(response => {
console.log(response);
}, error => {
console.log(error);
});
2022 update
Built in fetch api is available in NodeJS 18+. Third party npm modules are no longer needed.
(async () => {
const res = await fetch('https://dummyjson.com/products/1')
if (res.ok) {
const data = await res.json()
console.log(data)
}
})()
More details in the official blog
I am using npm request module (https://www.npmjs.com/package/request) to post binary content to a servlet. The binary content is received as part of http request, using the npm request module it is then posted to the J2ee server.
Along with the post, I need to pass some custom headers. I am using the below code to do that
var req = require('request');
function upload(request, response) {
var options = {
headers: {
'customheader1': 'val1',
'customheader2': 'val2'
}
};
var target = req.post('http://'+host+':'+port+'/myapp/Upload', options);
request.pipe(target);
target.on('finish', function() {
console.log('Uploaded with headers');
})
}
However, the headers are going as blank to the server. What would be the right way to pass headers using request.post?
As per request Docs (http://github.com/request/request)
var req = require('request');
function upload(request, response) {
var options = {
url: 'http://'+host+':'+port+'/myapp/Upload',
headers: {
'customheader1': 'val1',
'customheader2': 'val2'
}
};
var target = req.post( options, function(err,data){
console.log('uploaded with headers')
})
request.pipe(target);
}