: Guide Book on Web framework for Node.js
Transcript of : Guide Book on Web framework for Node.js
Express.js
GuideBookonWebframeworkforNode.js
ByRickL.
Copyright©2016RickL.AllRightsReserved
Copyright©2016byRickL.
All rights reserved. No part of this publication may be reproduced, distributed, ortransmitted in any form or by any means, including photocopying, recording, or otherelectronic or mechanical methods, without the prior written permission of the author,except in the case of brief quotations embodied in critical reviews and certain othernoncommercialusespermittedbycopyrightlaw.
TableofContentsIntroduction
Chapter1-OverviewofExpressJS
Chapter2-Session
Chapter3-serve-index
Chapter4-cookie-Sessions
Chapter5-MorganinExpressJS
Chapter6-CORS
Chapter7-Express-Paginate
Chapter8-Multer
Chapter9-Compression
Chapter10-csurf
Chapter11-body-parser
Chapter12-Flash
method-override
Chapter13-serve-favicon
Chapter14-response-time
Chapter15-express-namespace
Chapter16-express-expose
Chapter17-connect-render
Conclusion
Disclaimer
Whileallattemptshavebeenmadetoverifytheinformationprovidedinthisbook,the author does assume any responsibility for errors, omissions, or contraryinterpretations of the subjectmatter containedwithin. The information provided inthisbookisforeducationalandentertainmentpurposesonly.Thereaderisresponsibleforhisorherownactionsandtheauthordoesnotacceptanyresponsibilitiesforanyliabilitiesordamages,realorperceived,resultingfromtheuseofthisinformation.
The trademarks that are used arewithout any consent, and thepublication of thetrademark is without permission or backing by the trademark owner. Alltrademarksandbrandswithinthisbookareforclarifyingpurposesonlyandaretheownedbytheownersthemselves,notaffiliatedwiththisdocument.
Introduction
ExpressJSisoneofthemostusefulandinterestingNodeframeworks.Itisusedforthe
developmentofbothwebandmobileapplications.Thesetypesofapplicationsarethe
mostlywidelyusedinsoftwareenvironments.Thisshowstheneedforyoutoknowhow
thisframeworkcanbeusedfordevelopment.Theframeworkhasnumerousmodules
whichcanbeusedforthepurposeofenhancingthelookandfeelofyourapplications.
Chapter1-OverviewofExpressJS
ExpressJSisaNodeframeworkwhichisveryflexibleandprovidesdeveloperswith
numerousfeaturesforthedevelopmentofwebandmobileapplications.Theframework
canbeusedforthedevelopmentofAPIs.Inthisbook,wewilldiscussthevariousfeatures
ofExpressJS.
Chapter2-Session
ToinstallthisinExpress,justexecutethefollowingcommand:
$npminstallexpress-session
Theabovecommandwillinstallthesessionintoyoursystem.Touseitinyourprogram,
youhavetousethe“require”command.Thisisshownbelow:
varsession=require(‘express-session’)
Thesessionmiddlewarecanbecreatedbyuseofthegiven“options.”Youshouldknow
thatthedataforthesessionshouldnotbesavedinthecookieitself,buthere,onlythe
sessionIDisstored.Thedataforthesessionisstoredontheserversidefortheapp.
However,“MemoryStore,”whichisthedefaultserver-sidesessionstoragewasnot
developedforuseinaproductionenvironment.Inmostcases,itwillleakandnotscale
pastasingleprocess.Itwasdevelopedforthepurposeofdebugging.
“express-session”willacceptthefollowingpropertiesintheobjectforoptions:
Cookie
ThesearethesettingsforthecookieofthesessionID.Considertheexamplegivenbelow:
{path:‘/’,httpOnly:true,secure:false,maxAge:null}.
Genid
ThisisafunctionwhichiscalledforgenerationofanewsessionID.Thefunction
providedshouldreturnastringwhichwillbeusedasthesessionID.“req”isgiventothe
functionasthefirstargumentincasethereisaneedforavaluetobeattachedtothe“req”
whentheIDisbeinggenerated.Thedefaultvalueforthiswillbeafunctionwhichcanuse
“uid2”forthegenerationoftheIDs.
Note:Toavoidconflictionofthesessions,makesurethatthegeneratedIDsareunique,
thatis,theyshouldbedifferentfromeachother.Considertheexamplegivenbelowwhich
showshowthiscanbedone:
application.use(session({
genid:function(req){
returngenuuid()//usingUUIDsforthesessionIDs
},
secret:‘mysecret‘
}))
Name
ThisisthenameofthesessionIDcookiewhichistobesetintheresponse.Notethatitis
readfromtherequest.Thedefaultvalueforthisisthe“connect.sid.”Forthosewhohave
multipleappswhicharerunningonthesamehost,thenthesessioncookieshavetobe
separatedfromeachother.Toachievethis,onehastosetdifferentnamesineachofthe
apps.
Proxy
Wheneveryouaresettingsecurecookies,youhavetotrustthereverseproxy.Thiscanbe
doneviatheheaderfor“X-Forwarded-Proto.”Thedefaultvalueforthisis“undefined.”
Thepossiblevaluesforthisareexplainedbelow:
1. “true”-theheader“X-Forwarded-Proto”willbeused.
2. “false”-alloftheheaderswillbeignored,andtheconnectionwillbeconsidered
onlyifadirect“TLS/SSL”connectionexists.
3. “Undefined”-thiswillusethesettingsfor“trustproxy”fromtheExpressitself.
Resave
Thiswillforcethesessiontobesavedbacktothesessionstore.Thishappenswhetheror
notthesessionwasmodifiedduringtherequest.Thenecessityofthiswilldependonyour
sessionstore.However,ifaclientmakesparallelrequests,raceconditionsmaybecreated.
Rolling
Thecookiewillbeforcedtobesetoneachoftheresponses.Theexpirationdateisalso
reset.Thedefaultvalueforthisis“false.”
saveUninitialized
Withthis,asessionwhichwasnotinitializedwillbesavedtothesessionstore.An
uninitializedsessionisonewhichisnewandnotmodifiedinanyway.Thedefaultsetting
forthisis“true.”However,thishasdeprecatedandisexpectedtochangeinthefuture.
Requiredoption
ThisisthesecretwhichisusedforsigningthecookieforthesessionID.Itcanbemade
upofanarrayofsecretsorastringjustforasinglesecret.Incaseyouprovideanarrayof
secrets,onlythefirstelementinthearraywillbeusedforsigningthecookieforthe
sessionID.Therestoftheelementswillbeusedforverificationofthesignaturein
requests.
Store
Thisistheinstanceofthesessionstore.Itsdefaultisanew“MemoryStore”instance.
Considertheexamplegivenbelow:
varapplication=express()
application.set(‘trustproxy’,1)//trustingthefirstproxy
application.use(session({
secret:‘mysecret’,
resave:false,
saveUninitialized:true,
cookie:{secure:true}
}))
Weneedtobeabletousethecookiesinaproductionenvironment,andatthesametime
allowfortestinginadevelopmentenvironment.Thesetupcanbeenabledbyuseofthe
“NODE_ENV.”Considertheexamplegivenbelow,whichshowshowthiscanbedone:
varapplication=express()
varsession={
secret:‘mysecret‘,
cookie:{}
}
if(application.get(‘env’)===‘production’){
application.set(‘trustproxy’,1)//trustingthefirstproxy
session.cookie.secure=true//servingsecurecookies
}
application.use(session(session))
Thedefaultsettingfor“cookie.maxAge”is“null,”anditwillneverexpire,whichmeans
thatthecookiewillbecomeabrowser-sessioncookie.Thecookieisonlyremovedonce
theuserhasclosedthebrowser.Thesessionisalsoremoved.
req.session
Forsessiondatatobestoredandaccessed,youshouldusetheproperty“req.session,”and
thestoreinitializesthisasaJSON.Thesessionobjectswillthenbeleftfine.Considerthe
examplegivenbelow,whichshowsaviewcounterwhichisspecifictoauser:
application.use(session({secret:‘mysecret‘,cookie:{maxAge:50000}}))
application.use(function(req,res,next){
varsession=req.session
if(session.views){
session.views++
res.setHeader(‘Content-Type’,‘text/html’)
res.write(‘<p>views:‘+session.views+‘</p>’)
res.write(‘<p>willexpiresin:‘+(session.cookie.maxAge/1000)+‘s</p>’)
res.end()
}else{
session.views=1
res.end(‘Thisisademoforsessions.Refreshthepage!’)
}
})
Session.regenerate()
Thismethodisinvokedwhenwewanttogeneratethesession.Afterthis,anewsession
instanceandSIDwillbeinitializedatthe“req.session.”Thisisshownbelow:
req.session.regenerate(function(error){
//anewsessionshouldbeaddedhere
})
Session.destroy()
Withthis,thesessionisdestroyed,andthe“req.session”removed.Itwillthenbe
regeneratedinthenextrequest.Thisisshownbelow:
req.session.destroy(function(error){
//asessioncannotbeaccessedhere.
})
Session.reload()
Thisisusedforreloadingthesessionasshownbelow:
req.session.reload(function(error){
//thesessionhasbeenupdated
})
Session.save()
Thisisforsavingthesessionasshownbelow:
req.session.save(function(error){
//sessionhasbeensaved
})
Considertheexamplegivenbelow,whichusesthe“express-session”soastostorethe
pageviewsfortheuser:
varexpress=require(‘express’)
varpurl=require(‘parseurl’)
varsession=require(‘express-session’)
varapplication=express()
application.use(session({
secret:‘mysecret‘,
resave:false,
saveUninitialized:true
}))
application.use(function(req,res,next){
varvws=req.session.views
if(!vws){
vws=req.session.views={}
}
//gettingtheurlpathname
varpathname=purl(req).pathname
//countingtheviews
vws[pathname]=(vws[pathname]||0)+1
next()
})
application.get(‘/foo’,function(req,res,next){
res.send(‘youhaveviewedthispage‘+req.session.vws[‘/test’]+‘times’)
})
application.get(‘/bar’,function(req,res,next){
res.send(‘youhaveviewedthispage‘+req.session.vws[‘/bar’]+‘times’)
})
ThatishowsessionscanbeusedinExpressJS.
Chapter3-serve-index
Thisisusedforservingpageshavinglistingsofadirectorytoaparticularpath.Itcanbe
installedbyexecutingthecommandgivenbelow:
$npminstallserve-index
Theabovecommandwillinstallthe“serve-index”toyourcomputer.Touseitinyour
program,ithastobeincludedorcalledbyuseofthe“require”method.Thisisshown
below:
varsvIndex=require(‘serve-index’)
TheAPIwillthenbeincludedinyourprogram.
serveIndex(path,options)
Thiswillreturnthemiddlewarewhichservestheindexofthedirectoryinthe“path”you
havegiven.Thepathhereisbasedoffofthevaluefor“req.url.”Foryoutochangethe
URLbase,makeuseofthe“app.use.”
Thefollowingpropertiesareacceptedbytheserveindexintheoptionsobject:
Filter
Thisfilterfunctionisappliedtofiles.Itsdefaultvalueis“false.”Itiscalledforeachofthe
files,anditusesthesignature“filter(filename,index,files,dir).”“Filename”willbethe
file’sname,“index”willbethearrayindex,and“files”isthearrayofthefiles,while
“dir”willbetheabsolutepathinwhichthefileislocated.
Hidden
Thisisusedfordisplayingthehiddenfiles.Itsdefaultvalueis“false.”
Icons
Thisisfordisplayingicons.Itdefaultvalueis“false.”
Stylesheet
ThisisanoptionalpathwhichleadstotheCSSstylesheet.Itsdefaultvalueisthebuilt-in
stylesheet.
Template
ThisisanoptionalpathwhichleadstoanHTMLtemplate,andisusedforrenderingthe
HTMLstring.
View
Thisisthedisplaymode.
Considertheexamplegivenbelow,whichshowshowalltheabovecanbeused:
varfhandler=require(‘finalhandler’)
varhttp=require(‘http’)
varsvIndex=require(‘serve-index’)
varsvStatic=require(‘serve-static’)
//TheServedirectoryworkstoindexeforpublic/ftpfolder(havingicons)
varindex=svIndex(‘public/ftp’,{‘icons’:true})
//Servingupthepublic/ftpfolderfiles
varserve=svStatic(‘public/ftp’)
//Creatingaserver
varserver=http.createServer(functiononRequest(req,res){
vardone=fhandler(req,res)
serve(req,res,functiononNext(error){
if(error)returndone(error)
index(req,res,done)
})
})
//Listen
server.listen(3000)
Toservethedirectoryindexeswithexpress,dothefollowing:
varexpress=require(‘express’)
varsvIndex=require(‘serve-index’)
varapplication=express()
//ServingURLslikethe/ftp/thingaspublic/ftp/thing
application.use(‘/ftp’,svIndex(‘public/ftp’,{‘icons’:true}))
application.listen()
Chapter4-cookie-Sessions
Thisisamodulewhichisusedforprovidingguestsessionssothateachofthevisitorswill
haveasession,whetherauthenticatedornot.Incasethesessionisnew,theproperty“Set-
Cookie”willbeproduced,regardlessofwhetheryouarepopulatingthesession.
Itcanbeinstalledbyuseofthefollowingcommand:
$npminstallcookie-session
FortheAPItobeusedintheprogram,wehavetousethe“require”commandasshown
below:
varcookieSession=require(‘cookie-session’)
Thefollowingoptionsareacceptedinthecookiesessionintheoptionsobject:
Name
Thisisthenameofthecookiewhichistobeset.Itsdefaultvalueis“session”.
Keys
Thisisthelistofthekeystobeusedforsigningandverifyingthecookievalues.Cookies
whichhavebeensetarealwayssignedwiththe“keys[0].”Therestofthekeyswillthen
bevalidforthepurposeofverification,andthiswillallowfortherotationtobedone.
Secret
Thisisastringwhichwillbeusedasasecretkeyincasethe“keys”arenotprovided.
Thereisalsoanumberofcookieoptionswhichyouneedtoknowhowtouse.
Ifyouneedtodestroyaparticularsession,doitasfollows:
req.session=null
Considerthesimpleviewcounterexamplegivenbelow.Hereistheexample:
varcookieSession=require(‘cookie-session’)
varexpress=require(‘express’)
varapplication=express()
appliation.set(‘trustproxy’,1)//trustingthefirstproxy
application.use(cookieSession({
name:‘session’,
keys:[‘key1’,‘key2’]
}))
application.use(function(req,res,next){
//Updatingtheviews
req.session.views=(req.session.views||0)+1
//Writingtheresponse
res.end(req.session.views+‘views’)
})
application.listen(3000)
Considerthenextexamplegivenbelow:
varcookieSession=require(‘cookie-session’)
varexpress=require(‘express’)
varapplication=express()
application.set(‘trustproxy’,1)//trustingthefirstproxy
application.use(cookieSession({
name:‘session’,
keys:[‘key1’,‘key2’]
}))
//Thiswillallowyoutosetreq.session.maxAgeforlettingcertainsessions
//haveadifferentvalueotherthanthedefaultone.
application.use(function(req,res,next){
req.sessionOptions.maxAge=req.session.maxAge||req.sessionOptions.maxAge
})
//…thelogicshouldbeaddedhere…
Youhavetonotethattheentiresessionobjectwillbeencodedandstoredinacookie.The
maximumcookiesizelimitonthedifferentbrowserscanthenbeexceeded.Ifthesession
objectislargeenoughanditcanexceedthelimitofthebrowserwhenithasbeenencoded,
whatwillhappeninmostcasesisthatthebrowserwillrefuseoravoidstoringthecookie.
Chapter5-MorganinExpressJS
ThisisloggermiddlewarefortheHTTPrequestforNode.js.TousetheAPIinyour
program,youhavetousethe“require”keywordasshownbelow:
varmorgan=require(‘morgan’)
Thefollowingformatisusedforcreatingthis:
morgan(format,options)
Asshownintheaboveformat,wehavetwoparametersorarguments.
ThefollowingpropertiesareacceptedbyMorganintheoptionsobject:
Immediate
Theloglineshouldbewrittenonrequestratherthanonresponse.Thiswillmeanthatthe
requestswillalwaysbeloggedeveniftheserveritselfcrashes,butitwillbeimpossible
forustologthedatafromtheresponse.
Skip
Thisisafunctionusedforthedeterminationofwhetherornotloggingwasskipped.The
defaultvalueforthisis“false,”Considertheexamplegivenbelow,whichshowshowthe
functioncanbecalled:
//EXAMPLE:onlythelogerrorresponses
morgan(‘combined’,{
skip:function(req,res){returnres.statusCode<400}
})
Stream
Thisisanoutputstreamwhichisusedforwritingloglines,anditsdefaultvalueis
“process.stdout.”
Considertheexamplegivenbelow,whichshowshowalltherequestscanbeloggedinthe
ApachecombinedformattotheSTDOUT.Hereistheexample:
varexpress=require(‘express’)
varmorgan=require(‘morgan’)
varapplication=express()
application.use(morgan(‘combined’))
application.get(‘/’,function(req,res){
res.send(‘hello,there!’)
})
vanillahttpserver
Anexamplewhichdemonstrateshowthiscanbedoneisgivenbelow:
varfhandler=require(‘finalhandler’)
varhttp=require(‘http’)
varmorgan=require(‘morgan’)
//creatingthe“middleware”
varlogger=morgan(‘combined’)
http.createServer(function(req,res){
vardone=finalhandler(req,res)
logger(req,res,function(error){
if(error)returndone(error)
//respondingtotherequest
res.setHeader(‘content-type’,‘text/plain’)
res.end(‘hello,there!’)
})
})
WritingLogstoaFile
Considertheexamplegivenbelow,whichshowshowtherequestscanbeloggedin
Apachecombinedformattoourfile“access.log”:
varexpress=require(‘express’)
varfs=require(‘fs’)
varmorgan=require(‘morgan’)
varapplication=express()
//creatingawritestream(intheappendmode)
varaLogStream=fs.createWriteStream(__dirname+‘/access.log’,{flags:‘a’})
//settingupthelogger
application.use(morgan(‘combined’,{stream:aLogStream}))
application.get(‘/’,function(req,res){
res.send(‘hello,there!’)
})
logfilerotation
Intheexamplegivenbelow,theappwilllogalltherequestsintheApachecombined
formattoanyofthelogfilesinourdirectory“log/”byuseofthefile-stream-rotator
module.Theexampleisasfollows:
varFStreamRotator=require(‘file-stream-rotator’)
varexpress=require(‘express’)
varfs=require(‘fs’)
varmorgan=require(‘morgan’)
varapplication=express()
varlDirectory=__dirname+‘/log’
//ensuringthelogdirectoryexists
fs.existsSync(lDirectory)||fs.mkdirSync(lDirectory)
//creatingarotatingwritestream
varaLogStream=FStreamRotator.getStream({
filename:lDirectory+‘/access-%DATE%.log’,
frequency:‘daily’,
verbose:false
})
//settingupthelogger
application.use(morgan(‘combined’,{stream:aLogStream}))
application.get(‘/’,function(req,res){
res.send(‘hello,there!’)
})
Customtokenformats
Inthenextapp,wewillusethecustomtokenformats.ItworksbyaddinganIDtoallof
therequests,andwillthendisplayitbyuseofthe“:id”token.Hereistheapp:
varexpress=require(‘express’)
varmorgan=require(‘morgan’)
varid=require(‘node-uuid’)
morgan.token(‘id’,functiongetId(req){
returnreq.id
})
varapplication=express()
application.use(assignid)
app.use(morgan(‘:id:method:url:response-time’))
app.get(‘/’,function(req,res){
res.send(‘hello,world!’)
})
functionassignId(req,res,next){
req.id=uuid.v4()
next()
}
Chapter6-CORS
ThisisaNode.jspackagewhichprovidesanExpressJS/Connectmiddlewarewhichcanbe
usedforenablingofthevariousoptionsforCORS.
Toinstallitvianpmcommand,executethecommandgivenbelow:
$npminstallcors
Thiscanbeusedasshownbelow:
varexpress=require(‘express’)
,cors=require(‘cors’)
,application=express();
application.use(cors());
application.get(‘/products/:id’,function(req,res,next){
res.json({msg:‘ThishasCORSenabledforalltheorigins!’});
});
application.listen(80,function(){
console.log(‘webserverwhichisCORSenabledlisteningonport80’);
});
ToenableCORSforasingleroute,doitasfollows:
varexpress=require(‘express’)
,cors=require(‘cors’)
,application=express();
application.get(‘/products/:id’,cors(),function(req,res,next){
res.json({msg:‘ThishastheCORSenabledforalltheorigins!’});
});
application.listen(80,function(){
console.log(‘webserverwhichisCORSenablednowlisteningonport80’);
});
ToconfiguretheCORS,doitasfollows:
varexpress=require(‘express’)
,cors=require(‘cors’)
,application=express();
varcOptions={
origin:‘http://sample.com’
};
application.get(‘/products/:id’,cors(cOptions),function(req,res,next){
res.json({msg:‘ThishasCORSenabledonlyforsample.com.’});
});
application.listen(80,function(){
console.log(‘webserverwhichisCORS-enabledisnowlisteningonport80’);
});
ConfigurationofCORSw/DynamicOrigincanbedoneasfollows:
varexpress=require(‘express’)
,cors=require(‘cors’)
,application=express();
varwhitelist=[‘http://sample1.com’,‘http://sample2.com’];
varcOptions={
origin:function(origin,callback){
varorIsWhitelisted=whitelist.indexOf(origin)!==-1;
callback(null,orIsWhitelisted);
}
};
application.get(‘/products/:id’,cors(cOptions),function(req,res,next){
res.json({msg:‘ThishasCORSenabledforthewhitelisteddomain.’});
});
application.listen(80,function(){
console.log(‘CORS-enabledwebserverlisteningonport80’);
});
HowtoenableCORSPre-Flight
CertainrequestsforCORSareconsideredtobecomplex,andtheseneedaninitial
OPTIONSrequest.ACORSrequestwhichusestheHTTPverbisconsideredtobe
complexcomparedtotheonewhichusesPOST/GET/HEADortheoneusingcustom
headers.Forpre-fightingtobeenabled,anewOPTIONShandlerhastobeaddedforthe
routewhichneedstobesupported.Thisisshownbelow:
varexpress=require(‘express’)
,cors=require(‘cors’)
,application=express();
application.options(‘/products/:id’,cors());//enablingapre-flightrequestfortheDELETErequest
application.del(‘/products/:id’,cors(),function(req,res,next){
res.json({msg:‘ThishasCORSenabledforalltheorigins!’});
});
application.listen(80,function(){
console.log(‘ThewebserverwhichisCORS-enabledislisteningonport80’);
});
Pre-flightcanalsobeenabledacrosstheboardasshownbelow:
application.options(‘*’,cors());//includingbeforetheotherroutes
AsynchronousconfigurationofCORS
varexpress=require(‘express’)
,cors=require(‘cors’)
,application=express();
varwhitelist=[‘http://sample1.com’,‘http://sample2.com’];
varcOptionsDelegate=function(req,callback){
varcOptions;
if(whitelist.indexOf(req.header(‘Origin’))!==-1){
cOptions={origin:true};//reflecting(enabling)therequestedorigininourCORSresponse
}else{
cOptions={origin:false};//disablingtheCORSforourrequest
}
callback(null,cOptions);//callbackneedstwoparameters:errorandtheoptions
};
application.get(‘/products/:id’,cors(cOptionsDelegate),function(req,res,next){
res.json({msg:‘ThishasCORSenabledforthewhitelisteddomain.’});
});
application.listen(80,function(){
console.log(‘webserverwithCORSenabledislisteningonport80’);
});
Thatishowitcanbedone.
Chapter7-Express-Paginate
Thisistobeusedtogetherwiththepaginationpluginsfordatabasessuchasthe
MongoDB.
Toinstall,executethecommandgivenbelow:
npminstall-Sexpress-paginate
Forittobeusedintheprogram,onehastousethe“require”keywordsoastoincludeit
intotheprogramThisisshownbelow:
varpaginate=require(‘express-paginate’);
With“paginate,”anewinstanceof“express-paginate”willbecreated.Considerthe
examplegivenbelow:
//#app.js
varexpress=require(‘express’);
varpaginate=require(‘express-paginate’);
varapplication=express();
//keepingthisbeforealltheroutesthatwillusepagination
application.use(paginate.middleware(10,50));
application.get(‘/users’,function(req,res,next){
//weareassumingthat`Users`waspreviouslydefinedinourexample
//as`varUsers=database.model(‘Users’)`forthoseusing`mongoose`
//andthattheMongooseplugin`mongoose-paginate`hasbeenadded.
//tothemodelforUsersviathe`User.plugin(require(‘mongoose-paginate’))`
Users.paginate({},{page:req.query.page,limit:req.query.limit},function(error,
users,pageCount,itemCount){
if(error)returnnext(error);
res.format({
html:function(){
res.render(‘users’,{
users:users,
pageCount:pageCount,
itemCount:itemCount
});
},
json:function(){
//CreatedbytheAPIresponseforlistobjects
res.json({
object:‘list’,
has_more:paginate.hasNextPages(req)(pageCount),
data:users
});
}
});
});
});
application.listen(3000);
Thesecondcodefortheappshouldbeasfollows:
//-users.jade
h1Users
//-alinkforsortingbynamewillbecreatedbythis
//-youmusthavenoticedthatweonlyhavetopassthequerystringparam
//-whichistobemodifiedhere,butnottheentirequerystring
a(href=paginate.href({sort:‘name’}))Sortingbyname
//-thiswillassumethatyouhave`?age=1`or`?age=-1`inthequerystring
//-sothevalueswillbenegatedbythisandyouwillbegiven
//-anoppositesortingorder(thatis,descwith-1orascwith1)
a(href=paginate.href({sort:req.query.age===‘1’?-1:1}))Sortbyage
ul
eachmyuserinusers
li=myuser.email
include_paginate
Thethirdcodeshouldbeasfollows:
//-_paginate.jade
//-Inthisexample,wewillmakeuseoftheBootstrap3.xpaginationclasses
ifpaginate.hasPreviousPages||paginate.hasNextPages(pageCount)
.navigation.well-sm#pagination
ul.pager
ifpaginate.hasPreviousPages
li.previous
a(href=paginate.href(true)).prev
i.fa.fa-arrow-circle-left
|Previous
ifpaginate.hasNextPages(pageCount)
li.next
a(href=paginate.href()).next
|Next
i.fa.fa-arrow-circle-right
Chapter8-Multer
ThisismiddlewareinNode.jswhichisusedtohandle“multipart/form-data.”Thisisused
forthepurposeofuploadingfilestotheserver.Tomaximizeitsefficiency,itisbuilton
topof“busboy.”Youhavetonotethatanyformwhichisnotmultipartcannotbehandled
byMulter.
Theinstallationofthiscanbedonebyexecutionofthefollowingcommand:
$npminstall—savemulter
Itworksbyaddinga“body”anda“file/files”objecttothe“request”object.Inthe“body”
object,thevaluesfortheformfieldswillbestored.The“file/files”objectwillcontainthe
fileswhichhavebeenuploadedtotheserver.
Considertheexamplegivenbelowwhichshowshowthiscanbedone:
varexpress=require(‘express’)
varmulter=require(‘multer’)
varuploadfile=multer({dest:‘uploads/’})
varapplication=express()
application.post(‘/profile’,uploadfile.single(‘avatar’),function(req,res,next){
//req.fileisour`avatar`file
//req.bodyisforholdingthetextfields,ifanyareavailable
})
application.post(‘/photos/upload’,uploadfile.array(‘photos’,12),function(req,res,next){
//req.filesisanarrayof`photos`forfiles
//req.bodywillcontainthetextfields,iftherewereany
})
varcUpload=uploadfile.fields([{name:‘avatar’,maxCount:1},{name:‘gallery’,maxCount:8}])
application.post(‘/cool-profile’,cUpload,function(req,res,next){
//req.filesisourobject(String->Array)wherefieldnameisourkey,andthevalueisanarrayofthefiles
//
//example
//req.files[‘avatar’][0]->File
//req.files[‘gallery’]->Array
//
//req.bodywhichcontainsthetextfields,ifanywereavailable
})
Forthosewhoareinneedofhandlingatextwhichisinmultipartform,anyoftheMulter
methodscanbeused.Thesemethodsincludethe“single(),”“.array(),”and“fields().”
Considertheexamplegivenbelow,whichshowshowthe“.array()”canbeused:
varexpress=require(‘express’)
varapplication=express()
varmulter=require(‘multer’)
varuploadfile=multer()
application.post(‘/profile’,uploadfile.array(),function(req,res,next){
//req.bodyhasourtextfields
})
WithMulter,anoptionsobjectisaccepted,inwhichthemostbasiconeisour“dest”
property,anditspecifiesthedestinationofouruploadedfiles.Iftheoptionsobjectis
omitted,thefileswhichyouuploadwillbekeptinthememoryotherthaninthedisk.
Toavoidconflictsbroughtbynaming,theMulterwillrenamethefilesandthisisits
defaultsetting.Therestofthefunctioncanbecustomizedaccordingtowhatyouneed.
ThereexistsavarietyofoptionswhichcanbepassedtotheMulter,somakesurethatyou
understandhowthesecanbepassed.
Inanormalwebapplication,onlythe“dest”propertymightberequired,andthiscanbe
configuredasshownbelow:
varuploadfile=multer({dest:‘uploads/’})
Forthosewhoareinneedofexercisingagreatercontrolonyouruploadedfiles,justuse
the“storage”propertyotherthanthe“dest”property.“DiskStorage”and
“MemoryStorage”storageenginesareshippedwithMulter.Youcanusethirdpartiessoas
toaccessmorestorageengines.
Ifyouneedtoexercisefullcontrolofyourfileswhicharestoredonthedisk,usethedisk
storageengine.Thisisshownbelow:
varstorage=multer.diskStorage({
destination:function(req,file,cb){
cb(null,‘/tmp/file-uploads’)
},
filename:function(req,file,cb){
cb(null,file.fdname+‘-‘+Date.now())
}
})
varuploadfile=multer({storage:storage})
Theonlytwooptionswhichareavailableincludethe“filename”and“destination.”They
arethefunctionswhichdeterminehowthefilesaretobestored.The”destination”
propertywilldeterminethefolderinthedirectoryinwhichtheuploadedfileistobe
stored.Thiscanalsobespecifiedasapathintheprogram.Ifthispropertyisnot
specified,thenthedefaultpathisusedintheoperatingsystem.
FileFilter
Thispropertycanbeusedforsettingthefileswhicharetobeuploadedandtheoneswhich
aretobeskipped.Thisfunctionshouldbeusedasshownintheexamplegivenbelow:
functionfileFilter(req,file,cb){
//Thefunctionwillcallthe`cb`withaboolean
//toindicatethatthefileshouldbeaccepted
//ifthefileistoberejected,pass`false`,likeso:
cb(null,false)
//forthefiletobeaccepted,pass`true`,likeso:
cb(null,true)
//youcanpassanerrorsincesomethingmaygowrongatsomepoint:
cb(newError(‘Ihavenoclue!’))
}
ErrorHandling
Whenanerrorhasbeenencountered,theMulterwillpassittoExpress.Thestandard
Expresserrorwaycanbeusedforthepurposeofdisplayinganerror.
ForyoutocatchtheerrorswhichareoriginatingfromtheMulter,justcallthemiddleware
functiononyourown.Thisisshownintheexamplegivenbelow:
varuploadfile=multer().single(‘avatar’)
application.post(‘/profile’,function(req,res){
uploadfile(req,res,function(error){
if(error){
//Anerrorhasoccurredwhenuploading
return
}
//Everythingwasokay
})
})
Thatishowitcanbeused.
Chapter9-Compression
ThisismiddlewareavailableinNode.js.Itsupportsthefollowingcompressioncodes:
deflate
gzip
Toinstallthismiddlewareinyoursystem,executethefollowingcommand:
$npminstallcompression
ToincludethisAPIinyourprogram,usethe“require”keywordasshownbelow:
varcompression=require(‘compression’)
Therearedifferentoptionswhichcanbeusedsoastoreturnthecompressionmiddleware.
.filter
Thisisthedefaultfilterfunction.Itisusedforconstructionofacustomfilterfunction
whichwillbeanextensionofourdefaultfunction.Theexamplegivenbelowshowshow
thiscanbeused:
application.use(compression({filter:compress}))
functioncompress(req,res){
if(req.headers[‘x-no-compression’]){
//responseshavingthisheaderrequestshouldnotbecompressed.
returnfalse
}
//fallbacktostandardfilterfunction
returncompression.filter(req,res)
}
red.flush()
Withthismodule,theresponsewhichhasbeencompressedpartiallyisflushedtothe
client.Letusgiveexamplesofthese.
express/connect
Thismodulecanbeusedbyuseofthe“app.use,”whichisavailableineitherExpressand
connect.Requestspassedthroughthemiddlewarearealwayscompressed.Considerthe
examplegivenbelowwhichshowshowthiscanbedone:
varcompression=require(‘compression’)
varexpress=require(‘express’)
varapplication=express()
//compressingalloftherequests
application.use(compression())
//addingalltheroutes
Thatishowitcanbedone.
Server-SentEvents
Theworkingofthismodulewithserver-sideisnotdoneoutofthebox.Forcontenttobe
compressed,awindowfortheoutputhastobebufferedupsothatwecangetagood
compression.
Todoallthis,wehavetocallthe“red.flush()”forthosewhoneedthedatawrittensoasto
makeittoourclient.Thisisshownbelow:
varcompression=require(‘compression’)
varexpress=require(‘express’)
varapplication=express()
//compressingtheresponses
application.use(compression())
//theserver-senteventstream
application.get(‘/events’,function(req,res){
res.setHeader(‘Content-Type’,‘text/event-stream’)
res.setHeader(‘Cache-Control’,‘no-cache’)
//sendingapingapproxafterevery2seconds
vartimer=setInterval(function(){
res.write(‘data:ping\n\n’)
//!!!ourmostimportantpartfortheprogram
res.flush()
},2000)
res.on(‘close’,function(){
clearInterval(timer)
})
})
Chapter10-csurf
ThisisatokenmiddlewareforCSRF.Itactsasamiddlewareforprotectionpurposes.For
ittobeused,onehastobeginbyinitializingacookie-parserorasessionmiddleware.It
canbeinstalledintoone’scomputerbyexecutingthefollowingcommand:
$npminstallcsurf
TousetheAPIinyourprogram,usethe“require”commandasshownbelow:
varcsurf=require(‘csurf’)
Thatishowitcanbeincludedintotheprogram.
Theoptionsforthismoduletakemultipleanddifferentobjectswhichyoucanlearnhow
touse.
Considertheexamplegivenbelow,whichshowsacodefortheserver-sidewhichcanbe
usedforgenerationoftheCSRFformwhichcanbeusedforpostingback.Thisisthe
example:
varcParser=require(‘cookie-parser’)
varcsrf=require(‘csurf’)
varbParser=require(‘body-parser’)
varexpress=require(‘express’)
//settinguptheroutemiddlewares
varcsrfProtection=csrf({cookie:true})
varpForm=bParser.urlencoded({extended:false})
//creatinganexpressapp
varapplication=express()
//parsingcookies
//thisisneededbecause“cookie”istrueinthecsrfProtection
application.use(cParser())
application.get(‘/form’,csrfProtection,function(req,res){
//passingthecsrfTokentoourview
res.render(‘send’,{csrfToken:req.csrfToken()})
})
application.post(‘/process’,pForm,csrfProtection,function(req,res){
res.send(‘Thedataisnowbeingprocessed’)
})
Insideyourview,thevalueforcsrfTokenshouldbesettothevalueofahiddeninputfield
“_csrf.”Thisisshownbelow:
<formaction=”/process”method=“POST”>
<inputtype=“hidden”name=“_csrf”value=”{{csrfToken}}”>
Bestcolor:<inputtype=“text”name=“bestColor”>
<buttontype=“submit”>Submit</button>
</form>
Thatishowsimplyitcanbedone.
IgnoringtheRoutes
InAPIareasforthewebsitesinwhichwewillhaveourrequestsfullyauthenticated,the
CSRFshouldbedisabled.APIroutingcanbeignoredbytheuseofroutersandExpress.
Considertheexamplegivenbelow,whichshowshowthiscanbedone:
varcParser=require(‘cookie-parser’)
varcsrf=require(‘csurf’)
varbParser=require(‘body-parser’)
varexpress=require(‘express’)
//settinguptheroutemiddlewares
varcsrfProtection=csrf({cookie:true})
varpForm=bParser.urlencoded({extended:false})
//creatinganexpressapp
varapplication=express()
//parsingcookies
//thisisneededbecause“cookie”istrueinthecsrfProtection
application.use(cParser())
//creatinganapirouter
varapi=createApiRouter()
//mountingtheapibeforethecsrfisappendedtoourappstack
application.use(‘/api’,api)
//addingthecsrf,afterthe“/api”hasbeenmounted
appliation.use(csrfProtection)
application.get(‘/form’,function(req,res){
//passingthecsrfTokentoourview
res.render(‘send’,{csrfToken:req.csrfToken()})
})
application.post(‘/process’,pForm,function(req,res){
res.send(‘csrfwasrequiredforgettinghere’)
})
functioncreateApiRouter(){
varrouter=newexpress.Router()
router.post(‘/getProfile’,function(req,res){
res.send(‘thereisnocsrfheretoget’)
})
returnrouter
}
Thatishowitcanbedone.
Customerrorhandling
WhenthevalidationoftheCSRFhasfailed,anerrorwith“err.code===
‘EBADCSRFTOKEN’”willbethrown.Thiscanalsobeusedsoastodisplayerror
messages.Considertheexamplegivenbelow,whichshowshowthiscanbedone:
varbParser=require(‘body-parser’)
varcParser=require(‘cookie-parser’)
varcsrf=require(‘csurf’)
varexpress=require(‘express’)
varapplication=express()
application.use(bParser.urlencoded({extended:false}))
application.use(cParser())
application.use(csrf({cookie:true}))
//theerrorhandler
application.use(function(error,req,res,next){
if(error.code!==‘EBADCSRFTOKEN’)returnnext(error)
//handlingtheCSRFtokenerrorsisdonehere
res.status(403)
res.send(‘Theformwastamperedwith’)
})
Thatishowitcanbedone.
Chapter11-body-parser
ThisistheNode.jsmiddlewareforbodyparsing.However,itdoesnothandlemultipart
bodiesbecauseoftheirlargeandcomplexnature.Whendealingwithmultipartbodies,
youmighthavetodealwiththefollowingmodules:
multer
busboyandconnect-busboy
formidable
multipartyandconnect-multiparty
Themoduleprovidestheuserwiththefollowingparsers:
URL-encodedformbodyparser
Rawbodyparser
JSONbodyparser
Textbodyparser
Toinstallit,justexecutethefollowingcommand:
$npminstallbody-parser
TousetheAPI,includeitinyourprogrambyuseofthe“require”command.Thisis
shownbelow:
varbParser=require(‘body-parser’)
Withtheobject“bParser,”variousfactoriesareexposedforthepurposeofcreationof
middlewares.Theproperty“req.body”willbepopulatedbyallmiddlewaresbyuseofthe
parsedbodyoranerrorwillbeparsedtothecallback.
InExpress,agenericJSONandURL-encodedparsercanbeaddedasatop-level
middleware.Withthis,thebodiesofalltheincomingrequestswillbeparsed.Considerthe
simpleexamplegivenbelow,whichshowshowthiscanbedone:
varexpress=require(‘express’)
varbParser=require(‘body-parser’)
varapplication=express()
//parsingtheapplication/x-www-form-urlencoded
application.use(bParser.urlencoded({extended:false}))
//parsingtheapplication/json
application.use(bParser.json())
application.use(function(req,res){
res.setHeader(‘Content-Type’,‘text/plain’)
res.write(‘youposted:\n’)
res.end(JSON.stringify(req.body,null,2))
})
expressroute-specific
Bodyparserscanbeaddedtotherouteswhichneedthem.ThisispossibleinExpressand
itcaneasilybedone.Thisisthemosteasyandrecommendedwaythatthebody-parser
canbeusedinExpress.Considertheexamplegivenbelow,whichshowshowthiscanbe
done:
varexpress=require(‘express’)
varbParser=require(‘body-parser’)
varapplication=express()
//creatinganapplication/jsonparser
varjParser=bodyParser.json()
//creatinganapplication/x-www-form-urlencodedparser
varurlenParser=bParser.urlencoded({extended:false})
//POST/loginwhichwillgettheurlencodedbodies
application.post(‘/login’,urlenParser,function(req,res){
if(!req.body)returnres.sendStatus(400)
res.send(‘welcome,‘+req.body.username)
})
//POST/api/userswillgettheJSONbodies
application.post(‘/api/users’,jParser,function(req,res){
if(!req.body)returnres.sendStatus(400)
//createauserinthereq.body
})
Changingthecontenttypeforparsers
Withallparsers,atypeoptionisacceptedandwiththis,thecontent-typewillbe
changeableandthisshouldbetheonetobeparsedbythemiddleware.Considerthe
examplegivenbelow,whichshowshowthiscanbedone:
//parsingthevariousanddifferentcustomJSONtypesasaJSON
application.use(bodyParser.json({type:‘application/*+json’}))
//parsingacustomthingintotheBuffer
application.use(bParser.raw({type:‘application/vnd.custom-type’}))
//parsingtheHTMLbodyintothestring
application.use(bParser.text({type:‘text/html’}))
Chapter12-Flash
ThisisthesimplestmannerinwhichExpresscanbeimplemented.Toinstallit,execute
thefollowingcommand:
npmiflash
Considertheexamplegivenbelow,whichshowshowthiscanbedone:
application.use(session());//thesessionmiddleware
application.use(require(‘flash’)());
application.use(function(req,res){
//flashingamessage
req.flash(‘info’,‘hellothere!’);
next();
})
Considerthesecondexamplegivenbelow:
formsgeinflash
a.alert(class=‘alert-‘+msge.type)
p=message.msge
Hereisthefinalexample:
whilemsge=flash.shift()//consumingthemessagesasjadehasreadthem
a.alert(class=‘alert-‘+msge.type)
p=message.msge
Anarrayoff
Lashmessagescanbeasshownbelow:
{
“type”:“info”,
“message”:“message”
}
method-override
ThisisusedforoverridingHTTPverbs.Withit,onecanuseHTTPverbssuchas
“DELETE”and“PUT”inplaceswheretheyarenotsupportedbytheclient.Toinstallitin
yoursystem,executethefollowingcommand:
$npminstallmethod-override
Forthismoduletobeused,youhavetoknowthatabithastobeusedbeforeanyofthe
moduleswhichareinneedoftherequestmethods.
Usingtheheadertooverride
Fortheheadertobeusedforoverriding,theheadernamehastobespecifiedasastring
argumenttothefunction“methodOverride,”Forthecalltobemade,thePOSTrequesthas
tobesenttotheURLhavingtheheaderastheoverriddenmethod.Considertheexample
givenbelowshowing,howthiscanbedone:
varconnect=require(‘connect’)
varmthdOverride=require(‘method-override’)
//overridingwiththeX-HTTP-Method-Overrideheaderinourrequest
application.use(mthdOverride(‘X-HTTP-Method-Override’))
Considertheexamplegivenbelow,whichshowshowthiscanbeusedwith
“XMLHttpRequest”:
varc=newXMLHttpRequest()
c.onload=onload
c.open(‘post’,‘/resource’,true)
c.setRequestHeader(‘X-HTTP-Method-Override’,‘DELETE’)
c.send()
functiononload(){
alert(‘Theresponsewasobtained:‘+this.responseText)
}
Chapter13-serve-favicon
ThisisaNode.jsmiddlewarewhichisusedforthepurposeofservingfavicons.Afavicon
isjustavisualcuewhichbrowsersandotherclientsoftwareuseforthepurposeof
identifyingasite.
Themodulecanbeinstalledintothesystembyexecutingthefollowingcommand:
npminstallserve-favicon
Considertheexamplegivenbelow,showinghowthiscanbeusedinexpress:
varexpress=require(‘express’);
varfavicon=require(‘serve-favicon’);
varapplication=express();
application.use(favicon(__dirname+‘/public/favicon.ico’));
//Additionofyourroutesshouldbedonehere.
application.listen(3000);
Inconnect,thiscanbedoneasfollows:
varconnect=require(‘connect’);
varfavicon=require(‘serve-favicon’);
varapplication=connect();
application.use(favicon(__dirname+‘/public/favicon.ico’));
//Additionofyourmiddlewareshouldbedonehere,etc.
application.listen(3000);
vanillahttpserver
Thisisatypeofmiddlewarewhichcanbeusedeverywhere,includingoutsideExpress
andconnect.
Theexamplegivenbelowshowshowthiscanbedone:
varhttp=require(‘http’);
varfavicon=require(‘serve-favicon’);
varfnhandler=require(‘finalhandler’);
var_favicon=favicon(__dirname+‘/public/favicon.ico’);
varserver=http.createServer(functiononRequest(req,res){
vardone=fnhandler(req,res);
_favicon(req,res,functiononNext(error){
if(error)returndone(error);
//justcontinuewithprocessingoftherequesthere,etc.
res.statusCode=404;
res.end(‘hello’);
});
});
server.listen(3000);
Chapter14-response-time
Thisisthenode.jsresponsetimeheader.Itworksbycreatingamiddlewareforrecording
theresponsetimeofitsrequestsintheHTTPservers.Theresponsetimeinthiscasewill
bethetimewhentherequesthasenteredthemiddlewaretothetimewhentheheaders
havebeenwrittentotheclient.
Thismodulecanbeinstalledbyexecutingthefollowingcommand:
$npminstallresponse-time
Themodulecanbeincludedintotheprogrambyuseofthe“require”keywordasshown
below:
varrespTime=require(‘response-time’)
Considertheexamplegivenbelow,whichshowshowthiscanbeusedinboththeExpress
andtheconnect:
varexpress=require(‘express’)
varrespTime=require(‘response-time’)
varapplication=express()
application.use(respTime())
application.get(‘/’,function(req,res){
res.send(‘hello,there!’)
})
Thatishowitcanbeused.
vanillahttpserver
Thiscanbeusedasfollows:
varfinalhandler=require(‘finalhandler’)
varhttp=require(‘http’)
varrespTime=require(‘response-time’)
//creatingthe“middleware”
var_responseTime=respTime()
http.createServer(function(req,res){
vardone=fnhandler(req,res)
_responseTime(req,res,function(err){
if(error)returndone(error)
//respondingtotherequest
res.setHeader(‘content-type’,‘text/plain’)
res.end(‘hello,there!’)
})
})
Thatishowthemodulecanbeused.
Responsetimemetris
varexpress=require(‘express’)
varrespTime=require(‘response-time’)
varStatsD=require(‘node-statsd’)
varapplication=express()
varstatistics=newStatsD()
statistics.socket.on(‘error’,function(err){
console.error(err.stack)
})
application.use(respTime(function(req,res,time){
varstat=(req.method+req.url).toLowerCase()
.replace(/[:.]/g,”)
.replace(/\//g,‘_’)
statistics.timing(stat,time)
}))
application.get(‘/’,function(req,res){
res.send(‘hello,there!’)
})
Chapter15-express-namespace
Withthis,namespacedroutingcapabilitiesareaddedtoExpress.Toinstallitintothe
system,onecanexecutethefollowingcommand:
$npminstallexpress-namespace
Considertheexamplegivenbelow,whichcanbeusedforrespondingtoanyofthe
requests.Hereistheexample:
GET/forum/12
GET/forum/12/view
GET/forum/12/edit
GET/forum/12/thread/5
DELETE/forum/12
Forthemoduletobeused,onemustusethe“app.namespace()”and“require(‘express-
namespace’).”Themodulewillthenbemadeavailabletoyou.
Touseit,wehavetopassacallbackfunction,andthenperformaroutingtothemethod.
Aftereachofthecallbacks,theinvocationwillbecompleted,andthenamespacewillbe
storedtogetherwithitsstate.Thisisshownbelow:
application.namespace(‘/forum/:id’,function(){
application.get(‘/(view)?’,function(req,res){
res.send(‘GETforum‘+req.params.id);
});
application.get(‘/edit’,function(req,res){
res.send(‘GETforum‘+req.params.id+‘editthepage’);
});
application.namespace(‘/thread’,function(){
application.get(‘/:tid’,function(req,res){
res.send(‘GETforum‘+req.params.id+‘thread‘+req.params.tid);
});
});
application.del(‘/’,function(req,res){
res.send(‘DELETEtheforum‘+req.params.id);
});
});
Thecurrentnamespacecanalsobeaccessedviathe“app.currentNamespace.”Youshould
alsoknowhowtorunthetests.However,beforedoingthis,makesurethatyouhaveallof
thesub-modulesinstalledintothesystem.Thesecanbeinstalledbyexecutingthe
followingcommand:
$gitsubmoduleupdate–init
Thetestscanberunbyexecutingthefollowingcommand:
$maketest
Thatishowthemodulecanbeused.
Chapter16-express-expose
Thisisusedforexposingtheobjects,functions,andrawjstotheclientside.Thisfeature
isgoodforsharingofsettings,utils,andthecurrentdatafortheuser.Thehelpersandthe
localvariablesarealsoexposedtotheclientside.
Toinstallthismodule,executethecommandgivenbelow:
npminstall-Sexpress-expose
Itcanbeusedasshownbelow:
varexpress=require(‘express’);
varexpose=require(‘express-expose’);
application=expose(application);
application.expose(…);
Theaboveishowthemodulecanbeusedinexpress4.x.Inexpress2.xand3.x,itcanbe
doneasfollows:
varexpress=require(‘express’);
varexpose=require(‘express-expose’);
application.expose(…);
Howtoexpresstheobjects
Onewaythatobjectscanbeexposedtotheclientsideisbyexposingtheproperties,and
mostprobablytheExpressconfiguration.Whenthe“app.expose(object)”isexposed,the
propertieswillbeexposedtothe“application.*”Theexamplegivenbelowshowshow
thiscanbedone:
application.set(‘views’,__dirname+‘/views’);
application.set(‘theviewengine‘,‘jade’);
application.set(‘title’,‘Sample‘);
application.set(‘defaultlanguage’,‘en’);
application.expose(application.settings);
Helpermethodscanalsobeexposedbyanotherusecase.Thiscanbeinthesamewaythat
youarecurrentlyexposing.Thisisshownbelow:
application.expose({en:‘English’,fr:‘French’},‘application’,‘languages’);
Youthenneedtooutputyourdefaultbuffertoyourtemplate.Forjadeusers,itcanbedone
asfollows:
script!=javascript
ForEJSusers,thiscanbedoneasfollows:
<script><%-javascript%></script>
RawJavaScriptstringscanalsobeexposedasshownbelow:
application.expose(‘varsome=“variable”;’);
ExposingFunctions
Anamedfunctioncaneasilybeexposed.Youonlyhavetopassitwithadefaultnamefor
thebuffertoreplaceitwithatemplatename.Anexampleofthisisshownbelow:
application.expose(functionsomeFunction(){
return‘yes’;
},‘foot’);
Thatishowitcanbedone.
Self-CallingFunctions
Ananonymousfunctioncanalsobepassed,andthiswillexecuteitselfsoastocreatea
wrapperfunction.Considertheexamplegivenbelow,whichshowshowthiscanbedone:
application.expose(function(){
functionnotify(){
alert(‘thiswillbeexecutedfinely:D’);
}
notify();
});
Thatishowitcanbedone.
Request-LevelExposure
Alltheabovewhichhasbeendiscussedcanbeappliedtotherequest-level.Considerthe
examplegivenbelowshowinghowtodothis.Hereistheexample:
application.get(‘/’,function(req,res){
varuser={name:‘john’};
res.expose(user,‘application.current.user’);
res.render(‘index’,{layout:false});
});
Chapter17-connect-render
Thisisahelperforthetemplaterenderinconnect.Itcanbeinstalledbyexecutingthe
followingcommand:
$npminstallconnect-render
Itcanbeusedasshownbelow:
varconnect=require(‘connect’);
varrender=require(‘connect-render’);
varapplication=connect(
render({
root:__dirname+‘/views’,
layout:‘layout.html’,
cache:true,//`false`forthedebug
helpers:{
sitename:‘connect-rendersamplesite’,
starttime:newDate().getTime(),
now:function(req,res){
returnnewDate();
}
}
})
);
application.use(function(req,res){
res.render(‘index.html’,{url:req.url});
});
application.listen(8080);
TheAPIcanbeusedasshownbelow:
/**
*connect-render:ATemplateRenderhelperfortheconnect
*
*Usecase:
*
*varrender=require(‘connect-render’);
*varconnect=require(‘connect’);
*
*connect(
*render({
*root:__dirname+‘/views’,
*cache:true,//mustbesetto`true`intheproductionenv
*layout:‘layout.html’,//orfalseifthereisnolayout
*open:“<%”,
*close:“%>”,//thedefaultejsclosetagis‘%>’
*helpers:{
*config:config,
*sitename:‘NodeBlogEngine’,
*_csrf:function(req,res){
*returnreq.session?req.session._csrf:””;
*},
*}
*});
*);
*
*res.render(‘index.html’,{title:‘IndexPage’,items:items});
*
*//nolayout
*res.render(‘blue.html’,{items:items,layout:false});
*
*@param{Object}[options={}]fortherenderoptions.
*-{String}layout,layoutname,thedefaultoneis`‘layout.html’`.
*Set`layout=”`or`layout=false`meaningthatnolayout.
*-{String}root,therootdirforviewfiles.
*-{Boolean}cache,thecacheviewcontent,thedefaultis`true`.
*Mustbeset`cache=true`onproduction.
*-{String}viewExt,theviewfileextname,thedefaultis`”`.
*@return{Function}renderingmiddlewareforthe`connect`
*/
functionmiddleware(options){}
Conclusion
ItcanbesaidthatExpressJSisaNodeframework.Itprovidesdeveloperswitha
frameworkwhichtheycanusetocreatewebandmobileapplications.Ithasnumerous
featureswhichdeveloperscantakeadvantageofsoastocreatetheirapplications.Itworks
byuseofitsmiddleware.Theframeworkalsoprovidesdeveloperswithnumerous
moduleswhichtheycanuseforthedevelopmentoftheirapplications.
Eachofthesemoduleshasitsowncommandwhichcanbeusedforitsinstallation.Touse
ofanyofitsmodules,youhavetobeginbyinstallingit.Itsupportstheuseofsessions
whichareveryusefulinthecreationofwebapplications.Ithasavarietyofoptionswhich
youcanuseforthepurposeofdevelopment.Youshouldlearnhowtousethedifferent
optionswhichareavailableforeachExpressJSmodule.Theserve-indexmoduleisused
forservingpageshavinglistingsofadirectorytoaparticularpath.
Thisisveryinterestingindevelopment.Withthe“cookie-sessions”module,onecan
provideguestsessionssothateachofthevisitorswillhaveasession,whether
authenticatedornot.ThisisalsooneofthebestandinterestingfeaturesinExpress.This
Nodeframeworkisveryeasytolearnevenforbeginners.Thisbookhelpsyouinlearning
howtouseit.