How to set um a Node.JS proxy on AWS Lambda - javascript

I was trying to make a Polyfill.io server as a microservice on AWS Lambda, it was supposed to run a JavaScript file on a GET request.
When I run the service locally the call goes through but it returns an undefined object instead of JS file.
I'm running it locally using serverless, my code is based on polyfill.io's github repo
I've modified the service/index.js to be like so:
'use strict';
const express = require('express');
const path = require('path');
const Raven = require('raven');
const morgan = require('morgan');
const shrinkRay = require('./shrink-ray');
const app = express().enable("strict routing");
const one_day = 60 * 60 * 24;
const one_week = one_day * 7;
const one_year = one_day * 365;
app.use(shrinkRay({
brotli: {quality: 11}
}));
let ravenClient;
// Log requests
if (process.env.ENABLE_ACCESS_LOG) {
app.use(morgan('method=:method path=":url" request_id=:req[X-Request-ID] status=:status service=:response-time bytes=:res[content-length]'));
}
process.on('uncaughtException', (err) => {
console.log('Caught exception', err);
});
// Set up Sentry (getsentry.com) to collect JS errors.
if (process.env.SENTRY_DSN) {
const about = require(path.join(__dirname, '../about.json'));
ravenClient = new Raven.Client(process.env.SENTRY_DSN, {
release: about.appVersion || process.env.SENTRY_RELEASE || 'unknown'
});
ravenClient.patchGlobal();
app.use(Raven.middleware.express.requestHandler(ravenClient));
}
// Do not send the X-Powered-By header.
app.disable("x-powered-by");
// Default response headers
app.use((req, res, next) => {
// Ensure our site is only served over TLS and reduce the chances of someone performing a MITM attack.
res.set('Strict-Transport-Security', `max-age=${one_year}; includeSubdomains; preload`);
// Enables the cross-site scripting filter built into most modern web browsers.
res.set('X-XSS-Protection', `1; mode=block`);
// Prevents MIME-sniffing a response away from the declared content type.
res.set('X-Content-Type-Options', `nosniff`);
// Sets content-type
res.set('Content-Type', `application/javascript`);
// Prevents clickjacking by prohibiting our site from being included on other domains in an iframe.
res.set('X-Frame-Options', `sameorigin`);
res.set('Cache-Control', 'public, s-maxage=' + one_year + ', max-age=' + one_week + ', stale-while-revalidate=' + one_week + ', stale-if-error=' + one_week);
res.set('Surrogate-Key', process.env.SURROGATE_KEY || 'polyfill-service');
res.set('Timing-Allow-Origin', '*');
return next();
});
/* Routes */
app.use(require('./routes/api.js'));
app.use(require('./routes/meta.js'));
app.use('/test', require('./routes/test.js'));
if (process.env.RUM_MYSQL_DSN) {
app.use(require('./routes/rum.js'));
}
app.use(/^\/v[12]\/assets/, express.static(__dirname + '/../docs/assets'));
if (process.env.SENTRY_DSN) {
app.use(Raven.middleware.express.errorHandler(ravenClient));
}
module.exports.node = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'Go Serverless v1.0! Your function executed successfully!',
input: event,
}),
};
callback(event, app);
};
This is my serverless.yml:
service: serverless-node
provider:
name: aws
region: us-east-1
stage: dev
runtime: nodejs6.10
functions:
node:
handler: service/index.node
events:
- http:
path: node
method: get

I think you need to pass back the response object in the callback in the handler e.g.
callback(null, response);

Related

How Can I Transfer This http Node.Js to run on https?

Recently i created a node js and webrtc project that use http. But I notified that webrtc only works with https. So how can i transfer this http based node js file to https based one? Please help me.
Really i have no idea how to do this. So please help me to make it. What is need is to run this file over https. Not in http. As you can see, the below code use just http. As the webrtc need to run over https, i just need to make this file to run over https too
var hat = require('hat')
var http = require('http')
var nodeStatic = require('node-static')
var ws = require('ws')
var PORT = process.argv[2] || 4000
var httpServer = http.createServer()
var staticServer = new nodeStatic.Server('./public')
var wsServer = new ws.Server({ server: httpServer })
var peers = {}
var waitingId = null
var count = 0
httpServer.on('request', function (req, res) {
req.addListener('end', function () {
staticServer.serve(req, res)
}).resume()
})
wsServer.on('connection', onconnection)
function onconnection (peer) {
var send = peer.send
peer.send = function () {
try {
send.apply(peer, arguments)
} catch (err) {}
}
peer.id = hat()
peers[peer.id] = peer
peer.on('close', onclose.bind(peer))
peer.on('error', onclose.bind(peer))
peer.on('message', onmessage.bind(peer))
count += 1
broadcast(JSON.stringify({ type: 'count', data: count }))
}
function onclose () {
peers[this.id] = null
if (this.id === waitingId) {
waitingId = null
}
if (this.peerId) {
var peer = peers[this.peerId]
peer.peerId = null
peer.send(JSON.stringify({ type: 'end' }), onsend)
}
count -= 1
broadcast(JSON.stringify({ type: 'count', data: count }))
}
function onmessage (data) {
console.log('[' + this.id + ' receive] ' + data + '\n')
try {
var message = JSON.parse(data)
} catch (err) {
console.error('Discarding non-JSON message: ' + err)
return
}
if (message.type === 'peer') {
if (waitingId && waitingId !== this.id) {
var peer = peers[waitingId]
this.peerId = peer.id
peer.peerId = this.id
this.send(JSON.stringify({
type: 'peer',
data: {
initiator: true
}
}), onsend)
peer.send(JSON.stringify({
type: 'peer'
}), onsend)
waitingId = null
} else {
waitingId = this.id
}
} else if (message.type === 'signal') {
if (!this.peerId) return console.error('unexpected `signal` message')
var peer = peers[this.peerId]
peer.send(JSON.stringify({ type: 'signal', data: message.data }))
} else if (message.type === 'end') {
if (!this.peerId) return console.error('unexpected `end` message')
var peer = peers[this.peerId]
peer.peerId = null
this.peerId = null
peer.send(JSON.stringify({ type: 'end' }), onsend)
} else {
console.error('unknown message `type` ' + message.type)
}
}
function onsend (err) {
if (err) console.error(err.stack || err.message || err)
}
function broadcast (message) {
for (var id in peers) {
var peer = peers[id]
if (peer) {
peer.send(message)
}
}
}
httpServer.listen(PORT, function () {
console.log('Listening on port ' + PORT)
})
HTTPS requires a security certificate which matches the domain name. Both domain name and certificate for production usage can be purchased online and will have an expiration date and will need renewals.
The certificate comprises of two files cert.pem and key.pem.
For local development a self-signed untrusted certificate can be generated for localhost domain (via openssl command-line tool).
openssl req -x509 -nodes -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -subj '/CN=localhost'
The original code can be updated from 'http' to 'https' and those two files need to be loaded and passed as options to https.createServer()
I also had to update the call to 'node-static' as it was not serving local files.
var hat = require('hat')
var https = require('https') // updated
const fs = require('fs');
var nodeStatic = require('node-static')
var ws = require('ws')
var PORT = process.argv[2] || 4000
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
var httpServer = https.createServer(options) // updated
var staticServer = new nodeStatic.Server('./public')
var wsServer = new ws.Server({ server: httpServer })
var peers = {}
var waitingId = null
var count = 0
httpServer.on('request', function (req, res) { // updated
staticServer.serve(req, res)
})
// the rest of the original code
// httpServer variable is now an HTTPS server instance
httpServer.listen(PORT, function () {
console.log('Listening on port ' + PORT)
})
Starting the server and visiting https://localhost:4000 will be prompted with untrusted certificate warning which you have to acknowledge.
Register a site domain for under $15.00/year (for .com) including whois protection.
Create a free Cloudflare account and setup your new Domain Name, configure the DNS to proxy and handle your IPs you plan to host with under such domain.
Generate through cloudflare SSL Key, and utilize the certs in your projects. As long as the DNS routes to say your home IP or server IP it'll maintain that HTTPS.
For testing purposes you can use fake key/cert but this will always show insecure until you follow the above steps.
In NodeJS to engage the HTTPS:
const HTTPS = require('https');
const FILESYSTEM = require('fs');
// CREATE HTTP APP HERE THEN CREATE HTTPS SERVER FOR THE APP
HTTPS.createServer({ key: FILESYSTEM.readFileSync(__dirname + '/certs/key.pem'), cert: FILESYSTEM.readFileSync(__dirname + '/certs/cert.pem') }, app).listen(443);

Get images from google drive API

I am using node.js to try and get the images out of my google drive. I’ve finished the the getting started and tried to use download to put it in a file. My code is showing that I successfully downloaded it but I can’t see the image the file. I’m fairly new to API’s. I just want to get my image and be able to render it to my page to be viewed. Any help would be very appreciated.
const express = require("express");
const path = require ("path");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
// Google getting started section
const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/drive.metadata.readonly'];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = 'token.json';
// Load client secrets from a local file.
fs.readFile('credentials.json', (err, content) => {
if (err) return console.log('Error loading client secret file:', err);
// Authorize a client with credentials, then call the Google Drive API.
authorize(JSON.parse(content), listFiles,downloadFile);
});
/**
* Create an OAuth2 client with the given credentials, and then execute the
* given callback function.
* #param {Object} credentials The authorization client credentials.
* #param {function} callback The callback to call with the authorized client.
*/
function authorize(credentials, callback) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getAccessToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
/**
* Get and store new token after prompting for user authorization, and then
* execute the given callback with the authorized OAuth2 client.
* #param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
* #param {getEventsCallback} callback The callback for the authorized client.
*/
function getAccessToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('Authorize this app by visiting this url:', authUrl);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error('Error retrieving access token', err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
/**
* Lists the names and IDs of up to 10 files.
* #param {google.auth.OAuth2} auth An authorized OAuth2 client.
*/
function listFiles(auth) {
const drive = google.drive({version: 'v3', auth});
drive.files.list({
pageSize: 10,
fields: 'nextPageToken, files(id, name)',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const files = res.data.files;
if (files.length) {
console.log('Files:');
files.map((file) => {
downloadFile(auth);
});
} else {
console.log('No files found.');
}
});
}
// download to local file
function downloadFile(auth) {const drive = google.drive({version: "v3",
auth});
var fileId = "######";
var dest = fs.createWriteStream("public/images/photo.jpg");
drive.files.get({fileId: fileId, alt: "media"}, {responseType: "stream"},
function(err, res){
res.data
.on("end", () => {
})
.on("error", err => {
console.log("Error", err);
})
.pipe(dest);
// I am geeting success but I cant find the Image
console.log("success");
});
}
Not sure if this will solve the issue, but my guess is that the problem is the path where to write the file to. The code itself seems to come straight from the API docs, and seems to be correct.
Based on the official documentation, relative paths start with a slash (/).
So try changing this:
var dest = fs.createWriteStream("public/images/photo.jpg");
With this:
var dest = fs.createWriteStream("/public/images/photo.jpg");
Reference:
Node.js: File System > File paths

On windows platform PM2 not supporting Node.js for "Graceful Shutdown"

I have tried this way -
const server = app.listen(port, () => console.log('Project running on port ' + port));
process.on('SIGINT', () => {
console.info('SIGINT signal received.')
// Stops the server from accepting new connections and finishes existing connections.
server.close(function(err) {
// if error, log and exit with error (1 code)
if (err) {
console.error(err)
process.exit(1)
}
// close your database connection and exit with success (0 code)
// for example with mongoose
mongoose.connection.close(function () {
console.log('Mongoose connection disconnected')
process.exit(0)
})
})
})
And 2nd This way too -
const server = app.listen(port, () => console.log('Project running on port ' + port));
process.on('message', function(msg) {
console.info('shutdown signal received.',msg)
if (msg == 'shutdown') {
console.log('Closing all connections...');
setTimeout(function() {
console.log('Finished closing connections');
process.exit(0);
}, 1500);
}
});
But Neither is helping.
What I understand from reading all the related open alike issue is PM2 rather sending 'SIGINT' signal to node, it killing it by themself.
Instead of using pm2 we can self make a bash script that will restart our node project if shut with some error.
#echo off
setlocal enableextensions enabledelayedexpansion
set /a "x = 0"
:more_to_process
if %x% leq 10 (
echo %x%
node E:\Max\Projects\dummy\API\server.js
set /a "x = x + 1"
goto :more_to_process
)
endlocal
pause
Above script retry 10 times to restart the API. One can change the retry time.
Now for making the log files and handling the errors, we can do
const server = app.listen(port, () => console.log('Dummy-App API running on port ' + port));
var fs = require('fs');
var util = require('util');
var path = __dirname + `/mylogfiles/debug(${getDate()}).log`, printNextLine = false
if(fs.existsSync(path)){
printNextLine = true
}
var log_file = fs.createWriteStream(path, {flags : 'a'});
/* 'a' : open the file for writing, positioning the stream at the end of the file. The file is created if not existing
'a+' : open the file for reading and writing, positioning the stream at the end of the file. The file is created if not existing
'r+' : open the file for reading and writing
'w+' : open the file for reading and writing, positioning the stream at the beginning of the file. The file is created if not existing
(you can find more flags at https://nodejs.org/api/fs.html#fs_file_system_flags)
*/
if(printNextLine == true){
let prnt = '***************************************************************************************************************'
log_file.write('\n' + '\n' + prnt + '\n');
}
var log_stdout = process.stdout;
console.log = function(d) { //
log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
log_stdout.write( util.format(d) + '\n');
};
console.error = function(d) { //
log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
log_stdout.write( util.format(d) + '\n');
};
process.on('uncaughtException', function (err) {
console.error(err)
// console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
// console.error(err.stack)
process.exit(1)
})
function getDate(addDay){
let mydate = new Date()
var month = mydate.getMonth() + 1; // month (in integer 0-11)
var year = mydate.getFullYear(); // year
var date = mydate.getDate()
let h = mydate.getHours()
let m = mydate.getMinutes()
let s = mydate.getSeconds()
// let desiredDate = `${year}.${month}.${date} H-${h} M-${m} S-${s}`
let desiredDate = `${year}.${month}.${date}`
return desiredDate
}
Please create a folder named 'mylogfiles' parallel to server.js/index.js file.
Now, what is remaining to "Graceful Shutdown":-
process.on('SIGINT', () => {
console.info('SIGINT signal received.')
// Stops the server from accepting new connections and finishes existing connections.
server.close(function(err) {
// if error, log and exit with error (1 code)
if (err) {
console.error(err)
process.exit(1)
}
// close your database connection and exit with success (0 code)
// for example with mongoose
mongoose.connection.close(function () {
console.log('Mongoose connection disconnected')
process.exit(0)
})
})
})
About code process.on('SIGINT', .. will help if we run/start Node.js API with command
node server.js or the file index.js whatever is have named it.
That's why we built our Bash script that will take 'node' as a command to start the project-API.
One can put that bash script anywhere on the system/server unless and until path given on bash script for starting the API main file is correct.
Finally, the main server.js/index.js file may look like -
const express = require('express');
const bodyParser = require('body-parser'); // call body-parser here to parse body request from frontend
var fileUpload = require('express-fileupload'); // call express-fileupload here to accept file in the form of multipart data from frontend
// create express app
const app = express();
// parse requests of content-type - application/json
app.use(bodyParser.json({limit:'50mb'})); // here we try to set body request can accept requested data from frontend upto 50Mb
// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true,limit:'50mb' })); // here we try to set body request can accept requested data from frontend as urlencoded and upto 50Mb
app.use(fileUpload()); // here enable app to use fileupload
// Configuring the database
const dbConfig = require('./config/database.config.js');
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const options = {
auth: {
user: "*********ww",
password: "******dd"
},
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
autoIndex: true, // Don't build indexes
reconnectTries: Number.MAX_VALUE, // Never stop trying to reconnect
reconnectInterval: 500, // Reconnect every 500ms
poolSize: 10, // Maintain up to 10 socket connections
// If not connected, return errors immediately rather than waiting for reconnect
bufferMaxEntries: 0,
connectTimeoutMS: 10000, // Give up initial connection after 10 seconds
socketTimeoutMS: 45000, // Close sockets after 45 seconds of inactivity
family: 4, // Use IPv4, skip trying IPv6
serverSelectionTimeoutMS: 5000, // Timeout after 5s instead of 30s
useUnifiedTopology: true
};
mongoose.connect(dbConfig.url, options).then(
() => {
console.log("Successfully connected to the database");
},
err => {
/** handle initial connection error */
console.log('Could not connect to the database. Exiting now...', err);
process.exit();
}
);
var port = process.env.PORT || 23804; // set our port and port must be enable on server
var router = express.Router(); // call Router methode to enable api can accept multiple routes
app.all('/*', function(req, res,next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-Content-Type-Options, X-XSS-Protection, Content-Type, Accept, Key, Authorization");
res.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, PATCH");
next()
});
// define a simple route
app.get('/', (req, res) => {
res.json({"message": "Welcome to Dummy application. Sign Up and Login Quicky. Organize and keep track of all forms."});
});
// Require routes
require('./app/routes/controlFile.routes.js')(app);
const server = app.listen(port, () => console.log('Dummy-App API running on port ' + port));
var fs = require('fs');
var util = require('util');
var path = __dirname + `/mylogfiles/debug(${getDate()}).log`, printNextLine = false
if(fs.existsSync(path)){
printNextLine = true
}
var log_file = fs.createWriteStream(path, {flags : 'a'});
/* 'a' : open the file for writing, positioning the stream at the end of the file. The file is created if not existing
'a+' : open the file for reading and writing, positioning the stream at the end of the file. The file is created if not existing
'r+' : open the file for reading and writing
'w+' : open the file for reading and writing, positioning the stream at the beginning of the file. The file is created if not existing
(you can find more flags at https://nodejs.org/api/fs.html#fs_file_system_flags)
*/
if(printNextLine == true){
let prnt = '***************************************************************************************************************'
log_file.write('\n' + '\n' + prnt + '\n');
}
var log_stdout = process.stdout;
console.log = function(d) { //
log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
log_stdout.write( util.format(d) + '\n');
};
console.error = function(d) { //
log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
log_stdout.write( util.format(d) + '\n');
};
process.on('uncaughtException', function (err) {
console.error(err)
// console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
// console.error(err.stack)
process.exit(1)
})
process.on('SIGINT', () => {
console.info('SIGINT signal received.')
// Stops the server from accepting new connections and finishes existing connections.
server.close(function(err) {
// if error, log and exit with error (1 code)
if (err) {
console.error(err)
process.exit(1)
}
// close your database connection and exit with success (0 code)
// for example with mongoose
mongoose.connection.close(function () {
console.log('Mongoose connection disconnected')
process.exit(0)
})
})
})
function getDate(addDay){
let mydate = new Date()
var month = mydate.getMonth() + 1; // month (in integer 0-11)
var year = mydate.getFullYear(); // year
var date = mydate.getDate()
let h = mydate.getHours()
let m = mydate.getMinutes()
let s = mydate.getSeconds()
// let desiredDate = `${year}.${month}.${date} H-${h} M-${m} S-${s}`
let desiredDate = `${year}.${month}.${date}`
return desiredDate
}

IBM Watson WebSocket Connection failure. HTTP authentication failed; no valid credentials avaliable

I am working on a speech-to-text web app using the IBM Watson Speech to text API. The API is fetched on the click of a button. But whenever I click the button. I get the above-mentioned error. I Have stored my API key and URL in a .env file.
I tried a lot but keep on getting this error. Please Help me out as I am new to all this.
I got server.js from the Watson Github Repo
Server.js
'use strict';
/* eslint-env node, es6 */
const env = require('dotenv');
env.config();
const express = require('express');
const app = express();
const AuthorizationV1 = require('watson-developer-cloud/authorization/v1');
const SpeechToTextV1 = require('watson-developer-cloud/speech-to-text/v1');
const TextToSpeechV1 = require('watson-developer-cloud/text-to-speech/v1');
const vcapServices = require('vcap_services');
const cors = require('cors');
// allows environment properties to be set in a file named .env
// on bluemix, enable rate-limiting and force https
if (process.env.VCAP_SERVICES) {
// enable rate-limiting
const RateLimit = require('express-rate-limit');
app.enable('trust proxy'); // required to work properly behind Bluemix's reverse proxy
const limiter = new RateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
delayMs: 0 // disable delaying - full speed until the max limit is reached
});
// apply to /api/*
app.use('/api/', limiter);
// force https - microphone access requires https in Chrome and possibly other browsers
// (*.mybluemix.net domains all have built-in https support)
const secure = require('express-secure-only');
app.use(secure());
}
app.use(express.static(__dirname + '/static'));
app.use(cors())
// token endpoints
// **Warning**: these endpoints should probably be guarded with additional authentication & authorization for production use
// speech to text token endpoint
var sttAuthService = new AuthorizationV1(
Object.assign(
{
iam_apikey: process.env.SPEECH_TO_TEXT_IAM_APIKEY, // if using an RC service
url: process.env.SPEECH_TO_TEXT_URL ? process.env.SPEECH_TO_TEXT_URL : SpeechToTextV1.URL
},
vcapServices.getCredentials('speech_to_text') // pulls credentials from environment in bluemix, otherwise returns {}
)
);
app.use('/api/speech-to-text/token', function(req, res) {
sttAuthService.getToken(function(err, token) {
if (err) {
console.log('Error retrieving token: ', err);
res.status(500).send('Error retrieving token');
return;
}
res.send(token);
});
});
const port = process.env.PORT || process.env.VCAP_APP_PORT || 3002;
app.listen(port, function() {
console.log('Example IBM Watson Speech JS SDK client app & token server live at http://localhost:%s/', port);
});
// Chrome requires https to access the user's microphone unless it's a localhost url so
// this sets up a basic server on port 3001 using an included self-signed certificate
// note: this is not suitable for production use
// however bluemix automatically adds https support at https://<myapp>.mybluemix.net
if (!process.env.VCAP_SERVICES) {
const fs = require('fs');
const https = require('https');
const HTTPS_PORT = 3001;
const options = {
key: fs.readFileSync(__dirname + '/keys/localhost.pem'),
cert: fs.readFileSync(__dirname + '/keys/localhost.cert')
};
https.createServer(options, app).listen(HTTPS_PORT, function() {
console.log('Secure server live at https://localhost:%s/', HTTPS_PORT);
});
}
App.js
import React, {Component} from 'react';
import 'tachyons';
//import WatsonSpeech from 'ibm-watson';
var recognizeMic = require('watson-speech/speech-to-text/recognize-microphone');
class App extends Component {
onListenClick = () => {
fetch('http://localhost:3002/api/speech-to-text/token')
.then(function(response) {
return response.text();
}).then(function (token) {
var stream = recognizeMic({
token: token, // use `access_token` as the parameter name if using an RC service
objectMode: true, // send objects instead of text
extractResults: true, // convert {results: [{alternatives:[...]}], result_index: 0} to {alternatives: [...], index: 0}
format: false // optional - performs basic formatting on the results such as capitals an periods
});
stream.on('data', function(data) {
console.log('error 1')
console.log(data);
});
stream.on('error', function(err) {
console.log('error 2')
console.log(err);
});
//document.querySelector('#stop').onclick = stream.stop.bind(stream);
}).catch(function(error) {
console.log('error 3')
console.log(error);
});
}
render() {
return(
<div>
<h2 className="tc"> Hello, and welcome to Watson Speech to text api</h2>
<button onClick={this.onListenClick}>Listen to Microphone</button>
</div>
);
}
}
export default App
Since the only code you show is fetching an authorisation token then I guess that that is what is throwing the authentication failure. I am not sure how old the code you are using is, but the mechanism you are using was used when the STT service credentials are userid / password. The mechanism became unreliable when IAM keys started to be used.
Your sample is still using watson-developer-cloud, but that has been superseded by ibm-watson. As migrating the code to ibm-watson will take a lot of rework, you can continue to use watson-developer-cloud.
If do you stick with watson-developer-cloud and you want to get hold of a token, with an IAM Key then use:
AuthIAMV1 = require('ibm-cloud-sdk-core/iam-token-manager/v1'),
...
tokenService = new AuthIAMV1.IamTokenManagerV1({iamApikey : apikey});
...
tokenService.getToken((err, res) => {
if (err) {
...
} else {
token = res;
...
}
});

Loopback IO OAuth not working

I am trying to get a https loopback server up and running protected by OAuth. I am using the loopback gateway sample project as a reference. But for some reason I can't get the OAuth piece to work. What I mean is, even after adding in the OAuth bits and pieces, the APIs don't seem to be protected. I get a response back even if there is no token in my request. This is what my server.js looks like
var loopback = require('loopback');
var boot = require('loopback-boot');
var https = require('https');
var path = require('path');
var httpsRedirect = require('./middleware/https-redirect');
var site = require('./site');
var sslConfig = require('./ssl-config');
var options = {
key: sslConfig.privateKey,
cert: sslConfig.certificate
};
var app = module.exports = loopback();
// Set up the /favicon.ico
app.middleware('initial', loopback.favicon());
// request pre-processing middleware
app.middleware('initial', loopback.compress());
app.middleware('session', loopback.session({ saveUninitialized: true,
resave: true, secret: 'keyboard cat' }));
// -- Add your pre-processing middleware here --
// boot scripts mount components like REST API
boot(app, __dirname);
// Redirect http requests to https
var httpsPort = app.get('https-port');
app.middleware('routes', httpsRedirect({httpsPort: httpsPort}));
var oauth2 = require('loopback-component-oauth2')(
app, {
// Data source for oAuth2 metadata persistence
dataSource: app.dataSources.pg,
loginPage: '/login', // The login page url
loginPath: '/login' // The login processing url
});
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// Set up login/logout forms
app.get('/login', site.loginForm);
app.get('/logout', site.logout);
app.get('/account', site.account);
app.get('/callback', site.callbackPage);
var auth = oauth2.authenticate({session: false, scope: 'demo'});
app.use(['/protected', '/api', '/me', '/_internal'], auth);
app.get('/me', function(req, res) {
// req.authInfo is set using the `info` argument supplied by
// `BearerStrategy`. It is typically used to indicate scope of the token,
// and used in access control checks. For illustrative purposes, this
// example simply returns the scope in the response.
res.json({ 'user_id': req.user.id, name: req.user.username,
accessToken: req.authInfo.accessToken });
});
signupTestUserAndApp();
//var rateLimiting = require('./middleware/rate-limiting');
//app.middleware('routes:after', rateLimiting({limit: 100, interval: 60000}));
//var proxy = require('./middleware/proxy');
//var proxyOptions = require('./middleware/proxy/config.json');
//app.middleware('routes:after', proxy(proxyOptions));
app.middleware('files',
loopback.static(path.join(__dirname, '../client/public')));
app.middleware('files', '/admin',
loopback.static(path.join(__dirname, '../client/admin')));
// Requests that get this far won't be handled
// by any middleware. Convert them into a 404 error
// that will be handled later down the chain.
app.middleware('final', loopback.urlNotFound());
// The ultimate error handler.
app.middleware('final', loopback.errorHandler());
app.start = function(httpOnly) {
if(httpOnly === undefined) {
httpOnly = process.env.HTTP;
}
server = https.createServer(options, app);
server.listen(app.get('port'), function() {
var baseUrl = (httpOnly? 'http://' : 'https://') + app.get('host') + ':' + app.get('port');
app.emit('started', baseUrl);
console.log('LoopBack server listening # %s%s', baseUrl, '/');
});
return server;};
// start the server if `$ node server.js`
if (require.main === module) {
app.start();
}
function signupTestUserAndApp() {
// Create a dummy user and client app
app.models.User.create({username: 'bob',
password: 'secret',
email: 'foo#bar.com'}, function(err, user) {
if (!err) {
console.log('User registered: username=%s password=%s',
user.username, 'secret');
}
// Hack to set the app id to a fixed value so that we don't have to change
// the client settings
app.models.Application.beforeSave = function(next) {
this.id = 123;
this.restApiKey = 'secret';
next();
};
app.models.Application.register(
user.username,
'demo-app',
{
publicKey: sslConfig.certificate
},
function(err, demo) {
if (err) {
console.error(err);
} else {
console.log('Client application registered: id=%s key=%s',
demo.id, demo.restApiKey);
}
}
);
});
}
I don't get any errors when the server starts up. Thoughts?
Got it figured. More information here https://github.com/strongloop/loopback-gateway/issues/17, but basically I had my rest-api middleware not configured right.

Categories

Resources