Can I create a locally accessible only server in lambda? - javascript

I upload a zip file, and I have the following two files:
// server.js
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const addRequestId = require('express-request-id')();
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(addRequestId);
app.listen(8000);
exports.app = 'app';
and
// main entry point for the handler
'use strict';
const server = require('./server').app;
exports.handler = function(event, context, callback) {
// Do stuff
}
As you can see, I'd like to create an internal server that I can use inside my lambda. This times out, and I get an error message:
{"errorMessage":"2017-03-09T07:52:01.439Z 45210dff-049d-11e7-84cc-8367ae894495 Task timed out after 3.00 seconds"}
The problem happens right at app.listen(8000) (i.e. if I comment this line out, then the function runs.
Can I now create a server inside my lambda?
EDIT
Please do not comment on how a lambda is intended for a short/one time operation. The question is not about a correct implementation and usage of lambda; I know you are suppose to use API Gateway for routing. Of course this is not the full example. For the sake of this equestion, I need a server to run for the 5s that I need to execute this lambda. Is this not allowed within AWS Lambda?

Related

Run function in index.js from script in public folder

I am trying to run a script in my main index.js file from a script in the public folder. I do not know how to link the two.
I am trying to do this because I need to run file system operations on the server side. I have tried to link the script in the main HTML file, but when I try to run the function, it cannot be found.
my index file:
const express = require('express');
const bodyParser = require('body-parser');
var fs = require("fs");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.get('/', (req, res) => {
res.sendFile('public/index.html');
});
app.listen(3000, () => console.log('server started'));
function test() {
console.log("test");
}
my script in the public folder just has test();
my linking HTML
<script src="script.js"></script>
<script src="../index.js"></script>
I am expecting the test function to run, and log 'test'. It does not, and i get no console logs or errors.
All code is available on repl.it
People say the best feature of Node.JS is the ability to use the same code on the client and the server. However it isn't that simple.
You can't just include code in your HTML outside of the public folder. If you want to call a function on the server side, you will need to do something like this:
app.get('/test', (req, res) => {
test() // will log on the server side
res.send("All ok!");
});
And request that on the client side like so:
fetch('/test').then(res => {
console.log('got result from server!')
})
Essentially, you cannot just call functions on the server side - you have to talk to the server through HTTP. What you can do is create a shared folder with utility functions which you could include on both the client and server, but they couldn't be written with any reference to node modules unless you used a bundler (such as WebPack / RollUp).
you are confused with client side java script and server side node js file.
index.js is server side node js file. It has express link and runs like node index.js now if you want to use a java script function inside node js application you can use this example.
http://techslides.com/client-side-javascript-to-node-js
rest this line cannot be used for a nodejs server side js file.
You cannot run a function in your server script from another script which is running in the browser unless the function is set to be called via an end point. The server script and the browser script are not running in the same system so, they don't share the same execution context to call the functions in each other in a plain fashion.
Here is how you set the server function to be able to call from another system.
app.get('/runtest', (req, res) => {
test();
rest.status(200).send('Ok');
});
Now you can call this from your browser script via ajax.
You can't run a script in public folder in index.js in server-side. Because index.js is a script running in a server. This can't be include script in public folder which runs in the client(web browser). To run script.js in public folder you can create a new file in server with same name scirpt.js.
Script.js
module.exports = function test () {
// do some stuff
};
And import in index.js.
Index.js
const express = require('express');
const bodyParser = require('body-parser');
// import test function from script.js file in here
const test = require('./script.js');
var fs = require("fs");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.get('/', (req, res) => {
res.sendFile('public/index.html');
});
app.listen(3000, () => console.log('server started'));
// using it in here
test();
The const test = require('./script.js'); using to import function test from script.js file and using it in the last line test().

How to properly access the app variable set by express in a node.js app?

I'm building a node.js server and my folder structure looks like this:
server.js
app/routes.js
app/routes/users.js
My problem is that i'm not sure how can i use the app variable inside the users.js file. Do i have to require and setup express again in this file or is there a better/easier way to do it? Here is my sample code(just the bare minimum to understand my problem):
server.js
// Include our packages in our main server file
var express = require('express');
var stormpath = require('express-stormpath');
var app = express();
// Init Stormpath for user management and authentication
app.use(stormpath.init(app));
// Load routes
require('./app/routes')(app);
// Start the server
app.listen(process.env.PORT);
// Stormpath will let you know when it's ready to start authenticating users.
app.on('stormpath.ready', function () {
console.log('Your server is running on port ' + port + '.');
});
app/routes.js
// Import dependencies
const express = require('express');
const stormpath = require('express-stormpath');
// Export the routes for our app to use
module.exports = function(app) {
// Create API group routes
const apiRoutes = express.Router();
// User management: get users, invite users, view user profile
var UsersRoute = require('./routes/users');
apiRoutes.get('/memberinfo', stormpath.loginRequired, UsersRoute.memberInfo);
// Set url for API group routes
app.use('/', apiRoutes);
};
app/routes/users.js
// Protected route test
module.exports.memberInfo = function(req, res){
//how do i access the "app" here?
res.status(200).send({ user: req.user });
}
In your .memberInfo method, you can use req.app to access the app object that is associated with that request.
In cases where you aren't passed a req object that you can use in this way, then you need to initialize the module by calling a method on it and passing it the app object and the module can then store the app object locally so it can use it when desired.

node how can My app find index.js

Folder structure
bin - www.js
lib - jsFiles...
models - jsFiles...
node_modules -Folders and Files
public - index.html
route - jsFiles...
index.js
package.json
I use Express, angular.js. Server starts at www.js and It calls
index.js. After that, When I type merely "localhost:3000" It shows me
public/index.html. I don't have route for '/' but It shows me
'public/index.html'. I can not understand this. Please let me know
about the process.
www.js
var debug = require('debug')('example-server');
var app = require(process.cwd()+'/index');
//listen at 3000 port
app.set('port',process.env.PORT || 3000);
var server = app.listen(app.get('port'),function()
{
debug('Express server listening on port ' + server.address().port);
});
index.js
var favicon = require('serve-favicon');
var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//Connection for DB
require('./lib/connection');
var employees = require('./routes/employees');
var teams = require('./routes/teams');
var app = express();
// Writing at routing table
app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended:true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname,'public')));
app.use(employees);
app.use(teams);
// send 404 to errorhandler
app.use(function(err,req,res,next)
{
var err = new Error('Not Found');
err.status = 404;
console.log(error);
next(error);
});
...
...
module.exports = app;
In express.js the sequence in which you register your middleware makes a huge difference.
When express.js receives a request, it starts from top and executes registered middleware.
Middlewares are registered in express app using app.use(middleware_goes_here) this type of middleware gets executed no matter what the request url is on the other hand you can also register a middleware like app.use('/url/path',middleware_goes_here) in this case we are registering this middleware to '/url/path' so this middleware will only get executed when you visit '/url/path' (and non of the previous matching middleware serves the request without calling next() )
This app.use(express.static(path.join(__dirname,'public'))); line of code does the magic.
You can go here (express.static ref) to know more about static content serving and routing.
Basically what happens is, we are configuring express.static middleware to serve static content "as is" from "public" folder. So when you make any request and it matches a static content in public folder, then it will serve it otherwise express.static will call next middleware in sequence.
So in your case, the first middleware that actually server input request is express.static without any route filters, so it servers index.html even without a specifically defined route. If your public folder had file at public/javascript/jquery.js then following url will map to it http://localhost:3000/javascript/jquery.js
NOTE: You do not have to specify "public" in the url, the way in which express.static is registered, it will server contents FROM "public" folder.
................
UPDATE: How does default work in express.static?
By default, app.use(express.static(path.join(__dirname,'public'))); this will take index.html as default document. If you want to set index2.html as your default document, you can do that by doing something like this app.use(express.static(path.join(__dirname,'public'),{index: 'index2.html'}));
Hope it helps.
Put a relative path to folder(one up in hierarchy).
var app = require('../index');

Generating a random string in browser

I need to generate a random, two-word identifier field for each Mongo doc I'm inserting via Node.
I found random-words, an NPM module. It's great, except that I can only generate the random string server-side. When I try to use it in the client code, the function randomWords() comes back as undefined.
Here's my relevant server code (I took out the error handlers for the sake of brevity):
var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
// random words
var randomWords = require('random-words');
// Database
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:27017/test');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// Make the db accessible to our router
app.use(function(req,res,next){
req.db = db;
next();
});
app.use('/', routes);
app.use('/users', users);
module.exports = app;
And here's my server stuff (my global js file, not the route - though it doesn't work in either):
// DOM Ready =============================================================
$(document).ready(function() {
var ident = randomWords(2);
// Add User button click
$('#button').on('click', addUser); //addUser is a function in this doc
});
Any idea what I'm doing wrong here? I'm exporting the module and I'm able to access other stuff from the server-side code (like the database), I just don't know where I'm messing it up.
I solved this using vmkcom's suggestion above. I'm posting for others who might benefit from it because I had a really hard time diagnosing this problem and figuring out how to solve it. NOTE: This is a hacky fix that I suspect isn't recommended (but it works in this instance because, as vmkcom pointed out, the index.js file is pretty simple), so if you have a more elegant solution, please feel free to respond below.
Node modules, as helpfully pointed out above, are not automatically accessible to your browser. However you can make them so with Browserify, which is, in theory, great. But, when I ran Browserify, it didn't work and when I got it to run it only caused more errors.
What I did instead was take the index.js file from the random-words github (located here), renamed it random.js, and included it in my public /javascripts folder. I then linked to it in my layout.jade template file like this:
body
block content
script(src='http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js')
script(src='/javascripts/global.js')
script(src='/javascripts/random.js')
It isn't ideal, but it does work. As I said this is quick and dirty at its quickest and dirtiest, so if you have a better way, please share.
if you are using it in server side for env file you can do it like:
export const randomString = (length: number) => {
if (process.env.SECRET_KEY === undefined)
process.env.SECRET_KEY = [...Array(length)]
.map(() => (~~(Math.random() * 36)).toString(36))
.join("");
return process.env.SECRET_KEY;
};
Just copy code of random-words module index.js into your client code and rewrite module.exports = words as window._words = words
Or use some module system at client code as require.js

Nodejs, expressjs - how to serve delayed response

I am building a webservice, for which i am using nodejs, phantomjs and expressjs. I am learning all the three.
I want to serve a delayed response to the clients after processing their query. Like for example,
I am processing certain inputs from my client, then, i want to process the data at the backend which will take approx 10 sec on an avg. Then i wanted to serve this page to the client.
Is it possible in node to send multiple responses to the same request or delayed responses so that the template will automatically update the contents.
Or , should i use the same method , like store the json in a file in the server , then serve the page with ajax which will query the page.
please help me. here is the code which i wrote ,
app-server.js(the main file):
// import express module
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
// define all required template files to be served and also define the template engine
app.engine('.html', require('ejs').__express);
app.set('views', __dirname + '/views');
app.set('view engine', 'html');
// Useful modules
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// import the routes
require('./router')(app);
app.listen(8080);
router.js:
var crypto = require('crypto');
var express = require('express');
module.exports = function (app) {
// define the static routes.
app.use('/static', express.static('./static'));
app.use('/media', express.static('./media'));
//defining the controller.
var parserlib = require('./controller.js')
// Define the home root path
app.get('/', function (req, res) {
// shows the home search page.
res.render('index', {content:'template success'});
});
app.get('/search', function(req, res){
res.redirect('/');
});
app.post('/search', parserlib.parserlib);
}
controller.js:
var crypto = require('crypto');
var path = require('path')
var childProcess = require('child_process')
exports.parserlib= function(req, res){
var output = '';
var url = req.body.search_url;
var childArgs = [
path.join(__dirname, 'external-script.js'),
url,
]
// execute the script in a separate thread.
childProcess.execFile(binPath, childArgs, function(err, stdout, stderr) {
// handle results
console.log(stdout);
output = stdout;
//console.log(err);
//res.send(output);
});
//res.send(output);
};
so , what i want to see is, first send a response to client stating that its loading, then i want to update the with processed data. In other languages its not possible to send multiple responses. Not sure about nodejs.
Also, do i have to store the json output from the processed lib to a file and then use ajax to query ? or is it possible to directly update the json object to the client ?
Thanks
This is just not how HTTP works. The clients won't expect it. This has nothing to do with Node or any other framework. The way to do what you're attempting is to actually send a response that the thing is loading, and then have some other mechanism for reporting state.
As an example, you might design a RESTful API. In that RESTful API you might define a endpoint for creating new things:
POST /api/things
The client would post data to that to create a new thing. The response should be something that provides a location of the newly created resource, for example an HTTP 301 to /api/things/1.
If the user goes to /api/things/1 and the thing isn't done getting made yet, then you can either do a temporary redirect (303) to /api/things/1/status which provides some helpful status information, or just issue a 404.
If you actually want to send back server-side pushes of status information, then you should be looking at WebSockets or a pure Socket API of some kind, neither of which is provided by Express, but both of which are available in Node (checkout the socket.io library and the net core library)

Categories

Resources