alexa-js / alexa-app-server Goto Github PK
View Code? Open in Web Editor NEWAn Alexa app server for alexa-app.
License: MIT License
An Alexa app server for alexa-app.
License: MIT License
Hi there! This is awesome stuff. I was hoping to incorporate some of this into something I'm working on, but I noticed there wasn't a license. I was wondering if you wouldn't mind adding one to the project so that I could do that and contribute any improvements back upstream.
The same is true for @matt-kruse/alexa-app, but I figured I'd only bug you once. ;)
Thanks!
Hi,
I just updated to the latest version, and now I have verify: true
and debug: false
in my code. I tested it out in production, and it doesn't work.
I get the following
{ status: "failure", reason: "missing certificate url" }
I have a feeling that it has to do with debug: false
. I think turning off the debugger page deactivates the url's ability to be active.
Is anyone else seeing this too? Thanks!
Hi,
Would you please add a 'listen' IP configuration option to AlexaAppServer.start()? For example, in index.js, line 218, add a config.listen variable...
self.express.listen(config.port, config.listen);
This way, users can control the listen IP address for the service. For now we are 'hacking' it by modifying this line to:
self.express.listen(config.port, '149.2.28.245');
Thanks!
When attempting to add intents and utterances to the Amazon app portal for the example app guessing game, an error message is displayed:
Error: There was a problem with your request: 'guess' is an intent name as well as a slot name. Slot names and intent names must not overlap._
question:
I've put together an alexa-app-server, with https support as described in the README, but no amount of fooling with the settings on developer.amazon.com seems to get it to work. I just get "The SSL handshake failed". I also tried following the Amazon directions for generating a certificate, and put it in the same place in the alexa-app-server and get the same response.
Any ideas or suggestions? I know it's not directly related to the app-server, but I'm hoping someone might have some experience they can lend.
Amazon certification rules dictate that the end point must verify that the request has come from Alexa. However, when verification is ON, this breaks the local testing tool.
The testing tool probably needs to be automatically disabled when config.verify is on. In fact, the testing tool should probably be disabled in any production environment.
Hey guys, just wanted to let you know I built a similar app server for the Amazon SDK for Node.js inspired by this project:
The merge that was done under commit 4be7899 seems to have introduced a call to app.customSlotTypes()
. However, this seems to have caused a regression. When I now start my (alexa-app-server
and alexa-app
-based skill), I get an error like this:
TypeError: app.customSlotTypes is not a function
at Object.handle (/Users/xyz/Documents/Projects/xyz123/myprojects/Alexa/node_modules/alexa-app-server/index.js:131:81)
It's not clear to me what should be implementing the customSlotTypes()
method, but I don't see it elsewhere in the whole source code tree for alexa-app-server
or alexa-app
.
I see this problem with alexa-app-server
2.3.0. If I regress to 2.2.4, it goes away. I am using alexa-app
2.3.4.
Hi,
every i time i start my server i get the following error:
{"status":"failure","reason":"missing certificate url"}
I tried it with a self signed certificat and altough with an existing wildcard certificat from my domain.
Whats wrong there ?
I've tried altough the old version 2.3.1 (as mentioned in another issue) , but i get the same error.
Here are my settings:
var AlexaAppServer = require("alexa-app-server");
AlexaAppServer.start({
server_root: __dirname,
port: 83,
debug:false,
verify:true,
log : true,
// Use preRequest to load user data on each request and add it to the request json.
// In reality, this data would come from a db or files, etc.
preRequest: function(json, req, res) {
console.log("preRequest fired");
json.userDetails = { "name": "Bob Smith" };
},
// Add a dummy attribute to the response
postRequest: function(json, req, res) {
console.log("JKO");
json.dummy = "text";
},
httpsEnabled: true,
// The https port the server will bind to. Required for httpsEnabled support.
// Default is undefined.
httpsPort: 8181,
// The private key filename. This file must reside in the sslcert folder under the
// root of the project. Default is undefined.
privateKey: 'key.key',
// The certificate filename. This file must reside in the sslcert folder under the root of the
// project. Default is undefined.
certificate: 'crt.crt',
bundle: 'ca.crt'
});
Undo #46, see #56 (comment).
When I tried to test the node alexa-sdk
(https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs) locally, I got a response from alexa-app-server
of...
App [app-name] is not an instance of alexa-app
which means that any user using alexa-sdk
instead of alexa-app
(https://github.com/matt-kruse/alexa-app) cannot proceed with local testing. Is there support for this and I simply haven't configured alex-sdk
or my app correctly, or does the support for alexa-sdk
not exist? If the latter, ought there be support for alexa-sdk
?
Is it possible to update the README with some documentation on how to connect your echo to it? Even if it's just a link to relevant docs, it'd be super helpful :)
What is really needed for this library (and possible other alexa-js libraries) is a feature-based testing system, that focuses more on what features are being tested and how well will they work against various scenarios. For example, if I have two alexa-app-servers, one on an AWS Lambda instance and one on an express instance, I should have some reassurance that both instances will work identically feature-wise. This would also ideally help us isolate any bugs so that if a certain group of tests of one feature fail, the feature itself would be deemed buggy.
From #72
See http://stackoverflow.com/a/18283508 for more info.
I'm getting this in the console:
Error loading app [/Users/tlovett1/projects/alexa-app-server/examples/apps/airportinfo/index.js]: SyntaxError: Invalid or unexpected token
How can I find the line number?
Ok, so I have alexa-app-server server.js like so:
var AlexaAppServer = require('alexa-app-server');
var instance = AlexaAppServer.start({
server_root: __dirname, // Path to root
public_html: "public_html", // Static content
app_dir: "apps", // Location of alexa-app modules
app_root: "/alexa/", // Service root
port: 8080, // Port to use
httpsPort: 8081,
httpsEnabled: true,
privateKey: 'private-key.pem',
certificate: 'cert.cer',
debug: true,
verify: false
});
And then in ./apps/hello_world/index.js
, I have:
var alexa = require('alexa-app');
// Allow this module to be reloaded by hotswap when changed
module.change_code = 1;
// Define an alexa-app
var app = new alexa.app('hello_world');
app.launch(function(req, res) {
res.say("Hello World!!");
});
app.intent('NameIntent', {
"slots": { "NAME": "LITERAL", "AGE": "NUMBER" },
"utterances": ["{My name is|my name's} {matt|bob|bill|jake|nancy|mary|jane|NAME} and I am {1-100|AGE}{ years old|}"]
}, function(req, res) {
res.say('Your name is ' + req.slot('NAME') + ' and you are ' + req.slot('AGE') + ' years old');
});
app.intent('AgeIntent', {
"slots": { "AGE": "NUMBER" },
"utterances": ["My age is {1-100|AGE}"]
}, function(req, res) {
res.say('Your age is ' + req.slot('AGE'));
});
module.exports = app;
But when I start the server I get this stack trace complaining about express.post:
serving static content from: /home/ec2-user/Tinkering/xAlexa/public_html
loading server-side modules from: /home/ec2-user/Tinkering/xAlexa/server
loaded /home/ec2-user/Tinkering/xAlexa/server/login.js
loading apps from: /home/ec2-user/Tinkering/xAlexa/apps
/home/ec2-user/Tinkering/xAlexa/apps/hello_world/node_modules/alexa-app/index.js:491
express.post(endpoint, function(req, res) {
^
TypeError: undefined is not a function
at Object.express (/home/ec2-user/Tinkering/xAlexa/apps/hello_world/node_modules/alexa-app/index.js:491:13)
at /home/ec2-user/Tinkering/xAlexa/node_modules/alexa-app-server/index.js:122:11
at Array.forEach (native)
at Object.self.load_apps (/home/ec2-user/Tinkering/xAlexa/node_modules/alexa-app-server/index.js:82:30)
at Object.self.start (/home/ec2-user/Tinkering/xAlexa/node_modules/alexa-app-server/index.js:188:12)
at Function.appServer.start (/home/ec2-user/Tinkering/xAlexa/node_modules/alexa-app-server/index.js:295:21)
at Object.<anonymous> (/home/ec2-user/Tinkering/xAlexa/server.js:3:31)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3
I tried installing express then updating ./apps/hello_world/index.js
to be:
var express = require( 'express' );
var alexa = require('alexa-app');
var express_app = express();
// Allow this module to be reloaded by hotswap when changed
module.change_code = 1;
// Define an alexa-app
var app = new alexa.app('hello_world');
app.launch(function(req, res) {
res.say("Hello World!!");
});
app.intent('NameIntent', {
"slots": { "NAME": "LITERAL", "AGE": "NUMBER" },
"utterances": ["{My name is|my name's} {matt|bob|bill|jake|nancy|mary|jane|NAME} and I am {1-100|AGE}{ years old|}"]
}, function(req, res) {
res.say('Your name is ' + req.slot('NAME') + ' and you are ' + req.slot('AGE') + ' years old');
});
app.intent('AgeIntent', {
"slots": { "AGE": "NUMBER" },
"utterances": ["My age is {1-100|AGE}"]
}, function(req, res) {
res.say('Your age is ' + req.slot('AGE'));
});
app.express({ expressApp: express_app });
module.exports = app;
And this starts the server, but the app does not load:
serving static content from: /home/ec2-user/Tinkering/xAlexa/public_html
loading server-side modules from: /home/ec2-user/Tinkering/xAlexa/server
loaded /home/ec2-user/Tinkering/xAlexa/server/login.js
loading apps from: /home/ec2-user/Tinkering/xAlexa/apps
error loading app [/home/ec2-user/Tinkering/xAlexa/apps/hello_world/index.js]: TypeError: undefined is not a function
enabling https
listening on https port 8081
listening on http port 8080
Any ideas?
It seems like the server always binds to both, or just HTTP.
Hello,
Alexa would not connect to the server with the SSL cert that I had without also including the ca bundle (spent several hours of it working on my local machine and not on Alexa dev network to figure this one out)
I have forked and have added the code here and have made the ca cert optional as to keep the original functionality and to allow the inclusion of the cert if available.
Start returns a single instance, but that one may not be started since there're 2 instances, one for HTTP and one for HTTPS. In the case both are enabled it's even less clear what happens there.
It seems that LaunchRequest always sets session.new true, and all other requests always set session.new false. This doesn't seem to be the way that real AVS works, though. I'm not real sure how possible it would be to change this, given that I haven't looked into how the tester works at all, but figure it's worth noting, and if someone does have the time and inclination to dig into it, it'd be real helpful for some people. :-)
That said, as soon as I get some time (if ever), I'm going to look into it as well as other things.
The current tests are not organized properly. If anyone is willing to re-write the tests, please send a PR.
The request templates don't have the locale attribute need for i18n
When you checkCert: true
the following test hangs.
/*jshint expr: true*/
"use strict";
var chai = require("chai");
var chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
var sinonChai = require("sinon-chai");
chai.use(sinonChai);
var chaiString = require('chai-string');
chai.use(chaiString);
var expect = chai.expect;
chai.config.includeStack = true;
var mockHelper = require("./helpers/mock_helper");
var sinon = require("sinon");
var express = require('express');
var request = require("supertest-as-promised");
var bodyParser = require('body-parser');
var path = require('path');
describe("Alexa", function() {
var Alexa = require("../index");
var mockRequest = mockHelper.load("intent_request_airport_info.json");
describe("app", function() {
var app;
var testServer;
var testApp;
beforeEach(function() {
app = express();
app.use(bodyParser.json());
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
testApp = new Alexa.app("testApp");
testServer = app.listen(3000);
});
afterEach(function() {
testServer.close();
});
context("#express with checkCert=true", function() {
beforeEach(function() {
testApp.express({
expressApp: app,
router: express.Router(),
checkCert: true,
debug: false
});
});
it("checks cert header", function() {
return request(testServer)
.post('/testApp')
.set('signaturecertchainurl', 'dummy')
.set('signature', 'dummy')
.send(mockRequest)
.expect(401).then(function(res) {
expect(res.body.status).to.equal("failure");
expect(res.body.reason).to.equal("signature is not base64 encoded");
});
});
});
});
});
bodyParser.urlencoded
doesn't necessary work for all the user server modules.
In my project, for example ( https://gyazo.com/bc5b88a444b8ff334b78a5771b3d80c0 ) there are many express routes added which don't use urlencoded forms, so blanket-applying bodyParser.urlencoded to every request causes problems.
See #18 (comment).
I originally logged this against alexa-app (here)and was told to try moving it here.
Trying to use a custom slot type, which basically looks like this in my intent:
{
"slots":{"COMMAND":"COMMAND_SLOT"},
"utterances":[ "send {the|} {command|} {commands|COMMAND}" ]
}
(where commands is an app.dictionary)
I've also tried:
{
"slots":{"COMMAND":"COMMAND_SLOT"},
"utterances":[ "send {the|} {command|} {-|COMMAND}" ]
}
In both cases, the Utterances properly appear in the Alexa Tester (using alexa-app-server 2.3.1), but the Custom Slot Type section of the tester is always empty. I was under the impression the custom slot type info should appear there to facilitate copy/pasting into the interaction model.
I started on alexa-app 2.3.4 and upgraded to 2.4.0 ... same problem.
Thanks!
I have subfolders in some of my apps. Hotswap will reload for index.js but not for my other js files in the subfolders. How can I get hotswap to listen to all files in my app's hierarchy?
There should be a way to disable HTTP just like there's a way to enable HTTPs.
From #64
One (simple) formatting suggestion is to remove trailing slashes from the normalizedRoot in self.loadapps(). The comments have an example where the server root ends with a slash and if included, the message says, "loaded app [hello_world] at endpoint: /alexa//hello_world."
I am learning the Alexa ecosystem and in running the persistence tutorial, the execution failed due to userId being null. It appears the alexa-app is pulling the userId from the context property, but the request template does not have said property. I modified my copy of test.ejs and it now works. Is there another configuration parameter that I should have set so that his would happen "automagically"?
I put garbage instead of port numbers in the tests that call isPortTaken
and they still pass. Something looks not right, this should return a promise and reject it?
It is a rather off-topic question, but is it possible to deploy an Express server on Lambda that forwards the requests from Alexa to my webserver? Basically I just would like to use Lambda as a proxy between my computer (that has an alexa-app-server running but without HTTPS) and Amazon Voice Service.
Currently, the only tested node versions are v6 and v7 (according to travis-ci). It's not very easy to add other versions without some errors encountered, mainly with danger-js (see #48 for attempts by me to solve this issue).
If future releases of alexa-app-server are to intentionally drop support for older versions of node, it's best to add a section in the README stating which versions are supported.
I noticed that this portion of the code could be replaced with some from the alexa-verifier-middleware module.
// starts at line 73 in index.js
if (config.verify) {
// could be replaced with something like: self.express.use(endpoint, avm());
self.express.use(endpoint, function(req, res, next) {
req.verified = false;
if (!req.headers.signaturecertchainurl) {
return next();
}
var cert_url = req.headers.signaturecertchainurl;
var signature = req.headers.signature;
var requestBody = req.rawBody;
verifier(cert_url, signature, requestBody, function(er) {
if (er) {
res.status(401).json({ status: 'failure', reason: er });
} else {
req.verified = true;
next();
}
});
});
}
Thoughts?
I used the example code here:
var AlexaAppServer = require("alexa-app-server");
var server = new AlexaAppServer( {
port:3000
,verify: true
,public_html: "public"
// Use preRequest to load user data on each request and add it to the request json.
// In reality, this data would come from a db or files, etc.
,preRequest: function(json,req,res) {
//console.log("preRequest fired");
//json.userDetails = { "name":"Bob Smith" };
}
// Add a dummy attribute to the response
,postRequest: function(json,req,res) {
//json.dummy = "text";
}
} );
server.start();
and added the verify flag so that I can pass the skills certification. When I try to make a request through postman it does fail (which is good) but It's not throwing a 500, instead it throws the following error:
ReferenceError: er is not defined
at Object.handle (/my/path/node_modules/alexa-app-server/index.js:97:57)
at next_layer (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/route.js:103:13)
at Route.dispatch (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/route.js:107:5)
at /my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:195:24
at Function.proto.process_params (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:251:12)
at next (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:189:19)
at Layer.handle (/my/path/node_modules/alexa-app-server/index.js:79:15)
at trim_prefix (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:226:17)
at /my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:198:9
at Function.proto.process_params (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:251:12)
at next (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:189:19)
at next (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:166:38)
at Layer.staticMiddleware [as handle] (/my/path/node_modules/alexa-app-server/node_modules/serve-static/index.js:55:61)
at trim_prefix (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:226:17)
at /my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:198:9
at Function.proto.process_params (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:251:12)
at next (/my/path/node_modules/alexa-app-server/node_modules/express/lib/router/index.js:189:19)
at IncomingMessage.<anonymous> (/my/path/node_modules/alexa-app-server/index.js:184:5)
at emitNone (events.js:86:13)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
I have a script in the server
directory that requires POST method, and it hangs now that I've updated alexa-app-server. I was able to get around this by wrapping the raw body function with:
if (config.verify) {
...raw body parser for request verification...
}
It seems like req.on('data', function(data) {
does not get called if the POST method is used.
Considering how many changes we've all contributed to this library, wouldn't it make sense to bump the version to 2.4.0 from 2.3.1, instead of 2.3.2?
req.slot('abc', null)
If abc
isn't passed with intent request, it'll report error like
missing intent in request: abc [TypeError: Cannot read property 'value' of undefined]
IMO, passing default value means it can be empty and consumer of this method will handle it. In this case we shouldn't log as error. At most, we can set as warning.
I can send a PR if you agree.
Is it possible to play an online audio stream/file with this server on Alexa? I haven't found anything in the examples or package to use it with. It would be nice to have an example or a small documentation for stuff like this.
My PHPStorm gave me res.play();
but that didn't really work out either.
Hello,
I really like the alexa-app and alexa-app-server environment and tools. They enable me to create Alexa-Skills easily. But what I am not sure of (didn't find something on the Internet so far or must have missed it) how I can test the Skill-Intents with eg. Mocha and Chai? It easy to open the Skill in the Browser, see the response and everything there, but it is not scalable. Is it?
Or how can I test multiple slot-values (eg wrong, valid or empty) against multiple Intents?
I am thinking about something like this example: Alexa Skill Test Framework from BrianMacIntosh. Or how do you test your skills within this setup? Am I looking in the wrong direction?
Thank you for your help guys.
I am filing this here but also cross-filed against the alexa-app. Please feel free to close out one of them.
@matt-kruse There seems to be a bug in the server generation of utterance permutations. For example the following:
"utterances": ['{to|} set temperature to {64-80|number}']
generates utterances as follows:
setTempsIntent to set temperature to {sixty four|number}
setTempsIntent set temperature to {sixty five|number}
setTempsIntent to set temperature to {sixty six|number}
setTempsIntent set temperature to {sixty seven|number}
...
but what I believe should be generated is:
setTempsIntent to set temperature to {sixty four|number}
setTempsIntent set temperature to {sixty four|number}
setTempsIntent to set temperature to {sixty five|number}
setTempsIntent set temperature to {sixty five|number}
setTempsIntent to set temperature to {sixty six|number}
setTempsIntent set temperature to {sixty six|number}
setTempsIntent to set temperature to {sixty seven|number}
setTempsIntent set temperature to {sixty seven|number}
...
Can you please add an example skill with a http request?
I want to query an API but i think my way is not so perfect.
`var alexa = require('alexa-app');
var async = require('async');
var request = require('request');
// Allow this module to be reloaded by hotswap when changed
module.change_code = 1;
// Define an alexa-app
var app = new alexa.app('hello_world');
async.parallel([
function(callback) {
var options = {
url: 'https://xxxxxxxxxx.de/ddd',
timeout: 3000
}
request(options, function(err, response, body) {
// JSON body
if(err) { console.log(err); callback(true); return; }
obj = JSON.parse(body);
callback(false, obj);
});
}],
function(err, results) {
app.launch(function(req, res) {
sayToday(results[0], req, res);
});
app.intent('DayIntent', {
"slots": { "DAY": "DAY_OF_WEEK"},
"utterances": ["xxxxx"]
}, function(req, res) {
if(err) {
res.say("sdfsdfsdfsdf");
return;
}
//parse JSON
});
}
);`
I have added the application id to the project.json file. I verified that app.id is getting set by adding a console.log into node_modules/alexa-app-server/index.js(line 112).
But when I bring up the POST testing page the application id is not being replaced in the template. I'm don't do much browser javascript programming, and can't figure out why.
Is this a bug, or did I miss a configuration step somewhere?
Is there an easy way to convert one of the Alexa Skills Kit examples from here, so it can run within the alexa-app-server container, or could someone provide me some guidance on how to go about doing that?
Is there any way to check which language my request is in so i can forward it to my intent?
When I set the flag for verify to be true it works when I try to check my endpoint from a non-echo device. It properly returns a 401 error message:
{
"status": "failure",
"reason": "The signaturecertchainurl HTTP request header is invalid!"
}
However, when I try to test the app from the Amazon Alexa dev website or any echo devices, it throws an error that the requested skill has taken too long to respond.
Switching the flag back to false or removing completely and it goes back to working from echo devices but obviously it is going to fail certification.
For security.
Would it be possible to add a license declaration, similar to alexa-app?
Maybe I missed it, but this seems to be missing from this library?
See this page for the requirements:
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service#Verifying%20that%20the%20Request%20was%20Sent%20by%20Alexa
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.