Sending post does not work on server - javascript

I am attempting to get the silly name maker to work using a webhook hosted on my server. Using PTs-V2 I am able to see the JSON post from Dialogflow.
...{"color":"red","number":6}...
Using Hurl.it I am able to successfully send the post to my server and get the correct response.
{
"speech": "Alright, your silly name is red 6! I hope you like it. See you next time."...
But when I try to use my own server for Dialogflow it does not work. Not sure if there is something I'm missing.
Webhook on server
'use strict';
const https = require('https');
const fs = require('fs');
var privatekey = fs.readFileSync('...');
var certificate = fs.readFileSync('...');
var credentials = {key: privatekey, cert: certificate};
process.env.DEBUG = 'actions-on-google:*';
var DialogflowApp = require('actions-on-google').DialogflowApp;
const express = require('express');
const bodyParser = require('body-parser');
let app = express();
app.use(bodyParser.json({type: 'application/json'}));
var httpsServer = https.createServer(credentials, app);
httpsServer.listen(443);
const NAME_ACTION = 'make_name';
const COLOR_ARGUMENT = 'color';
const NUMBER_ARGUMENT = 'number';
app.get('/', function(req, resp) {
resp.send("Hello!");
console.log('app.get');
});
app.post('/', function (request, response){
console.log('app.post');
const app = new DialogflowApp({request: request, response: response});
console.log('Request headers: ' + JSON.stringify(request.headers));
console.log('Request body: ' + JSON.stringify(request.body));
// Make a silly name
function makeName (app) {
let number = app.getArgument(NUMBER_ARGUMENT);
let color = app.getArgument(COLOR_ARGUMENT);
app.tell('Alright, your silly name is ' +
color + ' ' + number +
'! I hope you like it. See you next time.');
}
let actionMap = new Map();
actionMap.set(NAME_ACTION, makeName);
app.handleRequest(actionMap);
});
Thanks for any help.
Edit:
Response from Dialogflow when I am running Apache server for website on port
"status": {
"code": 206,
"errorType": "partial_content",
"errorDetails": "Webhook call failed. Error: Failed to parse webhook JSON response: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $.",
"webhookTimedOut": false
},
Response when the JS server is running on the port and not Apache
"status": {
"code": 206,
"errorType": "partial_content",
"errorDetails": "Webhook call failed. Error: Webhook response was empty.",
"webhookTimedOut": false
},
Dialogflow Setup (screenshots)
Fulfillment
Intent that calls webhook
Result when Apache webserver is running
Result when JS webhook is running
My JS server never receives a post.

Related

Getting nodeJS web server to send form data to my email

I am trying to get the data my nodeJS server is receiving from a form on the front end to send that data to my email. I have tried to use nodemailer and haven't succeeded much. Can someone tell me perhaps what I am doing wrong with the following code?
const express = require("express");
const app = express();
const nodemailer = require("nodemailer");
var smtpTransport = require("nodemailer-smtp-transport");
const PORT = process.env.PORT || 4000;
app.use(express.static(__dirname + "/front-end"));
app.get("/", (req, resp) => {
resp.sendFile(__dirname + "/front-end/index.html");
});
app.use(express.json());
app.use(express.urlencoded());
app.post("/formData", (req, resp) => {
const data = req.body;
var transport = nodemailer.createTransport(
smtpTransport({
service: "Gmail",
auth: {
user: "user#gmail.com",
pass: "123456",
},
})
);
transport.sendMail(
{
//email options
from: "Sender Name <email#gmail.com>",
to: "Receiver Name <receiver#email.com>", // receiver
subject: "Emailing with nodemailer", // subject
html: data, // body (var data which we've declared)
},
function (error, response) {
//callback
if (error) {
console.log(error);
} else {
console.log("Message sent:");
resp.send("success!");
}
transport.close();
}
);
});
app.listen(PORT, () => {
console.log(`server running on port ${PORT}`);
});
Your code, at a glance, looks fine to me. I think the problem is (since you’re not stating you have set that up), that you want to send email with GMail. If you want to send email from your own app or web service via Gmail, you should set up a project in the Google Cloud Platform. Read more here.
Alternatively, you could use a service like Postmark, which you can configure to send emails via a domain that you own. There’s a free trial. Mailgun is a similar service. (I’m not affiliated to either).

Express POST request body is undefined

I've been working on troubleshooting a very simple application and cannot assess why the request body of POST is undefined. I have used express.json() and body-parser and changed the Content-Type of the request to different formats and have gotten nothing back.
This is the backend code relevant to the issue
const morgan = require("morgan");
const { response } = require("express");
const { format } = require("morgan");
const express = require("express");
const app = express();
const cors = require("cors");
app.use(express.static("build"));
app.use(cors());
app.use(express.json());
app.use(morgan("combined"));
app.post("/api/phonebook/", (req, res) => {
const body = req.body;
console.log(req.body);
console.log(body.content);
if (!body.name) {
return res.status(404).json({
error: "no name",
});
}
const personObj = {
name: body.name,
phone: body.phone,
id: generateId(),
};
phonebook = phonebook.concat(personObj);
response.json(personObj);
});
And this is an example POST
POST http://localhost:3000/api/phonebook/
Content-Type: application/json
{
"name": "Bob",
"phone": 123-456
}
The server is up and running and doing GET and DELETE requests both work.
POST http://localhost:3000/api/phonebook/
Content-Type: application/json
{
"name": "Bob",
"phone": 123-456
}
On request parameter body, 123-456 Isn't number so it should have " " to be "123-456". Because 123-456 type is null so the parameter is undefined. Parsing stiringified number into integer is needed on the server.
Updated
Response parameters in callback func should be used properly. response.json on end of callback function should be edited to res.json as the callback function defined (res, req).

Posting data from swift to node.js

I know this has been gone over before but I've spent hours on this and can't seem to figure out how to post data to a node.js server... I've started the project using cloud9 and node.js so I know I have a good install and that I'm starting with a working site.
In swift I'm sending a post request like
func post (){
let url = URL(string: "https://the-game-stevens-apps.c9users.io/index.html/")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Accept")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postString = "name=henry&message=HelloWorld"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(responseString)")
}
task.resume()
}
Then in my server.js file I have
var router = express();
router.use(express.urlencoded());
router.post('/index.html', function(req, res) {
var obj = {name:req.body.name,text:req.body.message};
});
I have plenty of experience with javascript but I'm a noob when it comes to node.js and have just been poking around with it, any help is really appreciated
The only part I can correct in your node.js code is
To get router you need to call express.Router();
const express = require('express');
const router = express.Router();
router.use((req,res,next) => {
console.log("/" + req.method, "host"+ req.host, "Params" + req.params);
next();
});
router.post('/index.html', (req, res) => {
const obj = {name:req.body.name,text:req.body.message};
//insert obj into database
});

getting empty body in record action - twilio

My use case:
My case is that i'm making a bot for listening podcast in which user will make call to twilio number and bot will ask what type of podcast would you like to listen then record for 10 seconds
when recording finish, it say user to please wait while we are finding podcast
I want that recording in my webhook so i will figure out caller mood and find appropriate podcast mp3 file from my database and play to caller
Issue I'm Facing:
I'm getting empty body in all of my webhooks
My code:
var express = require("express");
var bodyParser = require("body-parser");
var VoiceResponse = require('twilio').twiml.VoiceResponse;
var app = express();
var port = (process.env.PORT || 4000);
app.use(bodyParser.json())
// helper to append a new "Say" verb with alice voice
function say(text, twimlRef) {
twimlRef.say({ voice: 'alice' }, text);
}
// respond with the current TwiML content
function respond(responseRef, twimlRef) {
responseRef.type('text/xml');
responseRef.send(twimlRef.toString());
}
app.post("/voice", function (request, response, next) {
console.log("request: ", request.body); //body is comming as empty object
var phone = request.body.From;
var input = request.body.RecordingUrl;
var twiml = new VoiceResponse();
console.log("phone, input: ", phone, input);
say('What type of podcast would you like to listen. Press any key to finish.', twiml);
twiml.record({
method: 'POST',
action: '/voice/transcribe',
transcribeCallback: '/voice/transcribe',
maxLength: 10
});
respond(response, twiml);
});
app.post("/voice/transcribe", function (request, response, next) {
console.log("request: ", request.body); //body is comming as empty object
var phone = request.body.From;
var input = request.body.RecordingUrl;
var twiml = new VoiceResponse();
var transcript = request.body.TranscriptionText;
console.log("transcribe text: ", transcript);
//here i will do some magic(Ai) to detect user mood and find an
//appropriate mp3 file from my database and send to twilio
var mp3Url = 'https://api.twilio.com/cowbell.mp3'
say('start playing.', twiml);
twiml.play(mp3Url);
respond(response, twiml);
});
app.listen(port, function () {
console.log('app is running on port', port);
});
API Test with postman:
added url as webhook on twilio:
Heroku Logs:
Twilio developer evangelist here.
You are using body-parser which is good. However, you are using the JSON parser. Twilio makes requests in the format of application/www-x-form-urlencoded so you should change:
app.use(bodyParser.json())
to
app.use(bodyParser.urlencoded({ extended: false }))
Then you should see the parsed body as part of the request.body object.
As an extra note, the transcribeCallback is sent asynchronously to the call. So returning TwiML in response to that request won't affect the call at all. You will need to modify the call in flight, by redirecting it to some new TwiML when you get the result of transcription. An example of updating a call with Node.js is below:
const accountSid = 'your_account_sid';
const authToken = 'your_auth_token';
const client = require('twilio')(accountSid, authToken);
client.calls('CAe1644a7eed5088b159577c5802d8be38')
.update({
url: 'http://demo.twilio.com/docs/voice.xml',
method: 'POST',
})
.then((call) => console.log(call.to));

Node / Express / Request - Attempt to proxy POST request with parameters throws "Write after end"

I'm attempting to proxy all /api/ requests from local node server to a remote server while embedding some authentication parameters to them.
My current approach seems to work fine for GET with query parameters and POST as long as I don't give the "form" parameter to Request library, but as soon as I include it, the server starts throwing Error: write after end.
var express = require("express");
var request = require("request");
var parser = require("body-parser");
var strftime = require("strftime");
var app = express();
var path = require("path");
var port = 80;
var apiUrl = "http://example.com/";
var apiUser = "example";
var apiPass = "example";
app.use(express.static(path.join(__dirname, "/dist")));
app.use(parser.json());
app.use(parser.urlencoded({extended: true}));
app.get("/api/*/", function(req, res) {
console.log((strftime("%H:%M:%S") + " | GET -> " + req.url));
var url = apiUrl + req.url;
req.pipe(request.get(url, {
auth: {
user: apiUser,
pass: apiPass
}
})).pipe(res);
});
app.post("/api/*/", function(req, res) {
console.log((strftime("%H:%M:%S") + " | POST -> " + req.url));
var url = apiUrl + req.url;
req.pipe(request.post(url, {
form: req.body, // <----- RESULTS IN "write after end" error
auth: {
user: apiUser,
pass: apiPass
}
})).pipe(res);
});
app.listen(port);
console.log("Development server started, listening to localhost:" + port);
console.log("Proxying /api/* -> " + apiUrl + "/api/*");
This probably has to do with the body-parser middleware, but I couldn't find any fix for this issue and I don't quite get why the "form: req.body" would break the script. Logging the req.body seems to output the expected parameters.
I also attempted the alternative chaining syntax with .form(req.body), but the result is the same.
This is a couple of months old so the OP has probably moved on but I just ran into this and thought I'd post my solution for future searchers. The problem is that request writer is being ended when the reader ends and therefore the body cannot be written (and throws the 'write after end'). So we need to tell it not to end. When passing a body, you need to add { end : false } to the pipe options. For example:
app.post("/api/*/", function(req, res) {
console.log((strftime("%H:%M:%S") + " | POST -> " + req.url));
var url = apiUrl + req.url;
req.pipe(request.post(url, {
form: req.body,
auth: {
user: apiUser,
pass: apiPass
}
}), { end : false }).pipe(res);
});

Categories

Resources