All language subtitles for [English (auto-generated)] Node.js Full Course for Beginners _ Complete All-in-One Tutorial _ 7 Hours [DownSub.com]

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic Download
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranî)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
fa Persian
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

[Music]

hello and welcome to seven hours of

node.js tutorials and instruction this

video is made up of 15 tutorials for

learning node.js that build upon each

other much like the chapters of a book

you will build projects and learn the

fundamentals of node.js the express js

framework and mongodb

before beginning i recommend that you

already know the basics of javascript

this tutorial is for node.js beginners

but not absolute beginners in javascript

throughout the lessons in this video i

will mention links being available in

the description below i've compiled all

of these links into one github resource

that you will find in the description hi

i'm dave gray and i'm the creator of

these node.js tutorials you can

subscribe to my youtube channel for more

tutorials like this one you can also

follow me on twitter and if you're

feeling generous you can even buy me a

cup of coffee let's get started learning

node.js with chapter one

here we can see node.js is a javascript

runtime it's not a new language it's not

a different language it's a javascript

runtime and it's built on chrome's v8

javascript engine it's not a framework

or a library either but it does run on

the server and that's what makes it

different we're used to javascript

running in the browser where the html

and css is and that's all on the front

end but no js is on the back end

so you'll want to go to

nodejs.org if you haven't already

download note downloaded node.js

and you'll want to download the

recommended for most users version is

fine or if you want to get the one with

the latest features either way

download node.js

and you probably already have it or

familiar with it but if you're not i

just want to mention i will be using

visual studio code and you can download

that code editor you can also use

others that you're familiar with however

my examples will be with visual studio

code and you can get that for free at

code.visualstudio.com

okay with nodejs and visual studio code

both downloaded and installed let's get

started okay i've got visual studio code

open and you can see i have created a

new folder just for this tutorial called

zero one tut you can create a folder and

name it whatever you want to but open

that folder up in visual studio code and

then go ahead and create a new file

named server.js

now with that said i want to mention you

should already know some html css and

javascript before this tutorial series

possibly maybe some experience with

other libraries and frameworks like

react or vue but that's not necessary

but you will need the basics of html css

and javascript so while it is a

nodejs beginners tutorial series it's

not an absolute beginners for web devs

if you haven't already learned html css

and javascript you should probably start

there before attempting this series

now with that said we need to focus on

how no js differs from vanilla js just

plain old javascript first of all and

what will be the running theme

throughout the differences is that node

runs on a server

not in the browser and that is a big

difference so you're working on the back

end not the front end we're not relating

to the browser anymore

and because of that the console is now

in the terminal window it's not in

the console window of devtools in the

browser because we're not using the

browser at all let's open a terminal

window by going to the terminal menu and

choosing new terminal in vs code and

with the new terminal window open

we will be able to run node right inside

the terminal so if i type node we're now

running the console

directly in the terminal so if we can

add in any actual javascript that would

be

an expression such as two plus two and

we get four in return

so this is just like the dev tools

console

except we're now using the terminal for

node and with that said we can also exit

by pressing ctrl c and then it will tell

us to press ctrl c one more time and now

we've exited node but what if we put a

console statement in our file so if i

just put in

condyle console there we go console.log

and i put in your standard

hello world and save

we can also run

any javascript file from the terminal

with node we'll just type node and then

the name of the file we don't need to

put the js extension after i'll press

enter

and now we get hello world in the

terminal another difference between node

and vanilla javascript is that there is

a global object instead of a window

object the window object once again

referred to the browser where we could

do window dot inner height

and different properties like that the

global object is much smaller but it

does have some of the same properties we

were used to seeing in the window object

so what i'm going to do

is just say console.log

and i'll put

global in here because global is the

keyword for the global object

and i'll save

and now we can run our file once again

by typing node server in the terminal

and it logged the full global object

i'll expand the terminal window up and

scroll just so we can see this object

here so we have our hello world again

then here is the global object and you

can see there's a clear interval clear

timeout set interval set timeout those

are things that we already had in

vanilla javascript that we're used to

and it's a much smaller object than the

window object if you were to go into a

browser and to log that but that is

another difference in node.js a fourth

difference in node.js

is that there are common core modules

that we will explore and vanilla

javascript doesn't really have those

these are modules that relate to the

operating system the file system

and other things that we can do on the

server and to import those common core

modules as well as any other modules

we use common js modules common js

imports instead of es6 imports and now

there is some work being done

to use the same syntax that we typically

use in vanilla javascript that is such

as import whatever name from whatever

file

and that is how we do it in es6 however

common js uses a require statement so

let's go ahead and

import something and we can learn how to

do that with

let's call this os and set

this equal to

require dot

os

and that's pretty much all there is to

it it's just a different syntax than

we're used to seeing with the import and

now that we've imported the os let's go

ahead and get some information about the

os from it so we can say os dot

type and we'll go ahead and log that and

i'm going to copy this down a couple of

times and change type to a couple of

other values we can get about the os

such as

version

and home directory and that is

abbreviated with home dir you can see

that i'll comment out the global object

log because it takes up a little more

space let's go ahead and save this and

once again

call node server in the terminal

and here we get our hello world and then

you can see os type delivers

windows nt

os version is windows 10 pro

and then os home directory shows my home

directory in users

dave gray there are a couple of other

values that we always have access to in

node

and let me type the first one out it's

der name for directory name and it

starts with two underscores and that

will always give us the directory name

in node

and then the other one

is two underscores

and file name for the file name we're

using

here i can see i'm being inconsistent on

the semicolon so if anything i'll just

remove the one i typed let's go ahead

and save that and once again call node

server in the terminal and here's what

we get after the home directory that was

delivered from the os common core module

in our console log statement right here

you can see directory name

the value that we have we don't even

have to import a module to get that is

this full length here to my 01

directory and then you can see file name

gives that same full path but also

includes the file name at the end

there's another common core module that

we can import and i'll do that right now

and we'll call it path because

it is called path as well so

there is path with the common js import

and now we can use

file name within path so let me give

some examples of that to get more values

here we'll log the path

directory name and pass in

the file name and we'll see that it is

very similar to what we just got by

using the directory name here however if

we're using path that might come in

handy as well

there's also path dot base name

and we'll also pass in the file name

there

and i'll copy this down one more time

and there we'll just change base name

and this will be

extension name and we'll go ahead and

save that

now let's run the file one more time

with node in the terminal

and see what we got in return so after

our directory name and file name here if

i drag this up just a little we can see

it all

so we have the directory

that's the value before we use the path

import and here is the server

file name before we use the path

now the final three that we used with

the path import

we got the same as we did above for the

directory so using the path directory

name is the same as using this value in

this instance

and then the base name was just

server js so that allowed us to just

pull the file name out instead of having

everything included

as the file name value does up here on

line 22

and then the extension name gave us just

the extension of the file the dot js

what i've found to be even more useful

than any one of those individual values

is to oh i had my fingers on the wrong

keys console.log

path

dot

parse

and then pass in the file name

and we'll see what we get in return

once we call this one more time in the

terminal node server and here we get an

object with all of these values so we

have

the root

the directory

the base

the extension

and the file name itself so we can

really pull all of that together in any

way we want to if we just go ahead and

parse and then get each individual value

as well now besides the common core

modules we can also pull in packages

that other developers have created and

some of you may be familiar with node

package manager already and i will cover

that in some detail in the near future

but we can also create our own modules

and so we have a couple of imports here

we'll make room to import one more but

first in the file tree let's create

another file and i'll just call this

math.js inside of mathjs i'm going to

create some functions i'll call the

first one add and set it equal to

a

anonymous function it's an arrow

function really

and from there it'll just be a plus b

which would return the sum of the two

parameters a and b now i'm going to copy

this down three times and we can just

change these so

here we'll have

subtract they'll all have the two

parameters a and b we can also have

multiply

and we can have divide

so instead of a plus b of course it

would be a minus b

a times b

and a divided by b

right now though while we have these

four functions we have not exported them

in any way so we can have a statement at

the bottom that says

module dot exports

and then we can set that equal to an

object and we can pass in the names of

all the functions

there is another way to do this that

i'll show you right afterwards

but first let's attempt this way which

is a common way to see this so we're

exporting all of the functions that we

defined to import these back in the

server we need to come over here

and let's just define math and we'll set

this equal to

require

and now since it's not a common core

module we can't just say math we have to

say dot slash

and now math is available to us there

but we don't need the js extension so we

can save that and then let's go ahead

and comment out all of these console

logs

and we'll add the console log for the

math underneath here so console.log and

then we could say

math.ad and we could pass in two

variables two and three

and let's go ahead and call that below

with our node server

and we got hello world of course it's

still in there and then we got the total

five

so there is math being called however

we don't need to call it as an object

where we use dot notation we could

destructure right here so instead of

math we could destructure

and just say add

and remove the math dot and save and

this should work in the same way so if

we go ahead and call the server again

and we got five once again with our

hello world now we could go ahead and

destructure and pull in the rest

of the functions as well

subtract

multiply

and divide

we have all those functions available to

us now so if we go ahead and copy down

and we'll change each one to

subtract

multiply

and divide

we can

save go ahead and call the file once

again and here are the values looks like

i'll need to move this just a little bit

to see all the values but we've got five

and then two minus three is minus one

two times three is six and two divided

by 3 is essentially 2

3.66

and on now before we're finished with

the custom module let's go back to math

and i'll show you one other way this

could be done instead of combining all

of these at the end

there we go if i'll comment out this

export here

instead of the const here with each

definition

i'll just select all of those

we could change this to

exports dot

and then it's essentially adding each of

these functions to the export so

exports.add is equal to this anonymous

function and

exports.subtract is equal to this

anonymous function and so on but this

will work in the same way so once again

if we go ahead and call

the server file from node we've still

exported all of those functions

and we actually deconstructed them over

here to pull them in so you can also

export

in that way instead of using module

exports at the bottom okay with that

said we have covered quite a bit but

there's one more difference to point out

that we will see down the road and i'll

just put it here under number five and

that is nodejs is missing some of the

apis that are available to vanilla

javascript and one notable one is fetch

but of course we can always pull in

packages into node and there is a large

amount of packages available through

npm4 node so we won't miss it that much

in the next tutorial we'll be working

with files as far as reading writing

creating updating deleting all of the

things that we can do with files and

we'll be using the file system common

core module for that

today we're going to look at the file

system common core module for node.js it

allows us to create read update and

delete files and work with directories

on the server and that's because node.js

is a javascript runtime that actually

runs on the server instead of in the

browser now i'm going to click docs at

nodejs.org

because nodejs.org is the source of

truth for information about node much

like mdn would be the source of truth

for information

about vanilla javascript as well as html

and css currently the stable version

that i have installed is 14.17.5

as you view this tutorial the versions

that are stable may change so go ahead

and click on whichever version you have

and now you can see we have node.js

documentation today we're looking at the

file system module so i can click that

right here

and there are many things you can do

with the file system with directories

and different files so amongst all of

those things what i usually do is press

control f i'm on windows and then i type

what i'm looking for and we're going to

start out by

reading files so when i type read file i

can see the fs dot read file and it

shows the structure here for what i want

to call

and then you can click it and get

details about that i just wanted to show

you how to find the different

documentation on node.js and now let's

get started in visual studio code as we

work with the fs the file system common

core module i've got visual studio code

open with an empty index.js file i've

also got a files directory here in the

file tree and you can see a couple of

starter text files a lorem text file

that has a lot of text in it and a

starter text file that just says hi my

name is dave we're going to start by

importing the fs common core module here

and we use common js imports for that

and so it's just require fs

after that let's go ahead and read

that starter file so we need to specify

the file

and it's in files and then it's at

starter

dot text

from there

we have a callback function

that has error and data that we read

and so we'll say if air we need to throw

the error

and otherwise let's log the data to the

console

now if you remember the console in

node.js

is in the terminal so i'm going to press

control and backtick to open a terminal

window you could also do that from the

terminal menu

now here to run our little node file in

index we just type node and then index

we don't need the js and let's go ahead

and take a look at this data from

starter

and notice after we read the data

it's presented as buffer data so that's

what we get right here if we want to be

able to read the data we can put a to

string method afterwards i'll save

and i'll go ahead and call this again

and now we can see hi my name is dave in

the console

but instead of two string we can also

put in a parameter here that says

the encoding

or defines the encoding so we'll say

utf-8

before the callback as a perimeter and

now let's go ahead and run it again node

index in the terminal and once again we

get hi my name is dave now notice the

throw error here according to the node

documentation if we get an uncaught

exception we need to go ahead and catch

that and i'm just going to paste this in

if we have an uncaught error we should

exit

so

we listen for this uncaught exception

using process now process is one of

those values that node has available to

us we don't need to import it it's

already there so we're listing for an

uncaught exception then we pass in the

error to the callback here

and we're just logging the console

error there was an uncaught error and

then we put the error there and then we

exit the application and this is direct

from the node documentation so let's go

ahead and throw an error on purpose i'll

just look for a file to read that

doesn't exist named hello

and once again we'll call node index and

you can see we get an uncaught error

and here it is there is no such file or

directory now let's change this back to

starter so we can keep reading the data

that exists

and i'm going to put a console log

statement underneath

and this is to demonstrate

that

read file and node in general the

functions or methods you'll find from

node will be asynchronous and so we're

logging the data here but we're also

logging hello here

and node has the ability to say i'm

going to process this but let's go ahead

and tackle the rest

of the tasks in the program and when i

finish reading the file i'll get that

data to you if you're familiar with

async a weight this should be a familiar

concept but let's go ahead and save this

and let's see which we get in the

console first hello or the data

and we get hello and then we get hi my

name is dave so node said it would read

the file but it went ahead and processed

this console log statement and it

actually was logged to the console first

and then when node completed reading the

file it logged the data to the console

instead of hard coding the path like we

see here in read file there is a better

way

and let's pull in the path module to do

that so we have path and then we use

require and we're requiring path

and the reason is the slashes sometimes

if you're familiar with different

operating systems sometimes backwards

sometimes forward there can be some

problems not always but there can be

when you hard code file paths like that

but if we use the path module we can

eliminate this problem so let's use path

dot join i typed json there we go

join

and then we need to specify

first the directory name and that's two

underscores first and remember that's a

value that's always available to us in

node

after the directory name

we'll say the files directory to attach

on to concatenate to that directory name

and then we need to say the actual name

of the file itself so now we've got

starter text so if we supply this

instead of hard coding a file name it's

a much better approach let's go ahead

and save and run this one more time

and everything still works as it did now

that we know how to read files and catch

an error let's go ahead and copy the

read file and underneath this console

log statement i'll paste this in and we

will write a file but it's just a little

different i can change

just a little bit of the copy and paste

so instead of read file we've got write

file

and this path here will change the file

name because we're going to write a new

file this will be reply dot text now we

don't have to specify

the utf-8 that is by default now

we will have a callback and the callback

will only have an error we're not

reading data we're writing it

so if we have an error we'll throw the

error in here instead of data we can

just say

operation

complete or more specifically

let's say

write complete

and we can save this and now let's go

ahead and run this code

and we got an error oh and that's

because i forgot to specify exactly what

we're writing to the file i'll just say

nice to meet you

[Music]

and then we have our callback had things

out of order so again path name

content we're going to put in the file

and then the callback

with that saved let's run it

and there we go we've got hello hi my

name is dave and then the right is

complete let's look at the reply file we

created and it says nice to meet you i'm

going to copy all of this right file

operation down one

and

then we can change it to append file

which is updating a file

adding more content to it

we'll go ahead and create a different

file here

and that is to show you that a pin file

will go ahead and create a file as well

if it doesn't exist so let's just call

this test

and we'll say

testing text or something like that here

and other than that it is basically

the same syntax as

right we'll save this and go ahead and

run the code again

and we got write complete and append

complete and then notice due to the

asynchronous

fashion of node.js

the read completed last this time and we

have hi my name is dave after the other

operation is completed in the file tree

we now have our test file as well it has

the testing text in it so append file

worth noting that it will modify an

existing file

and can append content to it but will

also

it will create a file if it doesn't

exist

so due to the asynchronous nature of

nodejs and these different methods we're

calling here from read file write file

and append file if we wanted to modify

the file that we created such as reply

it would be

better to put a pen file i'm going to

cut this and put it inside of the

callback

of the write file operation that way it

would definitely create the file

and then we would be ready to append to

it

instead of wondering if we would

possibly create the file first with

append

and then write over it with write file

so here let's change this to

reply.text and it says nice to meet you

let's give a couple of line breaks

and then say

yes it is

and if we save that we'll go ahead and

delete the test that we're no longer

using

and our reply because we will create it

once again so we've got reply and then

we will modify reply with append and

it's inside of the callback

of write file

call node index in the terminal

hello

write complete

then we got the read operation completed

and then the append completed

so if we look at reply now it says nice

to meet you and yes it is in the order

we expected now as you might imagine if

we wanted to do something to this file

after we added more content and we

wanted to make sure it happened in the

order it needed to such as renaming the

file then that would need to be in the

callback of the append file i'm going to

go ahead and copy a pen file

and then inside of the callback i'm

going to paste it

and change this

append here

to

rename so we can rename the file and

we're grabbing

the reply file

and then we're going to replace this

parameter with

what we're going to name it

and we'll just call this

new reply

and then of course it has a callback

with an error as well and then we can

put

rename complete

now let's go ahead and call all of this

in the terminal with node index and it

does happen in the order we expect we

got write append and rename and you can

see this time the read operation

completed before the others once again

asynchronous so we don't know which will

happen before the next but in this way

we're controlling it because we're

putting the append inside the callback

of the right and we're putting the

rename inside the callback of the append

let's go ahead and look at our new reply

and it does have the content we expected

now if you've worked with javascript for

a while at this point you would be

saying

yes this is nice dave but this is

starting to look like what is called

callback hell and yes it is because

we're

putting one inside the next inside the

next and they're all inside the

callbacks of the other so

we are controlling the flow but at the

same time we're able to avoid this in

vanilla javascript using async await and

now we can look at how to avoid it in

node by doing the same i'm going to

comment all of this code out

and up here we can get rid of the

console log hello as well

and then at the top where we have fs

we'll switch this to fs

promises

and let's attach

dot

promises to our import here so we are

now importing the file system promises

instead of just fs and now i'm going to

create a function and i'm going to call

it file

ops for file operations and this will be

an async function

and then inside this function we can use

try catch

so here we'll have our catch for any

errors

and now inside here i'll just say

console.error

and pass in the air

or we could throw the air but that's

actually what's happening here and we're

catching them so it will not be an

uncaught error and then inside the try

block i'm going to define data

and set that equal to

fs or sorry before that a weight

fs

promises

dot

read file

and now we need to specify our file path

and that's what we have here part of why

i saved that so i could just copy it up

and i'm going to hide the file tree

momentarily so we can see a little more

after that we can still specify

utf-8

and then we don't need the callback here

that has the error and the data because

we're using a weight and we're catching

the error down here

so this should be just fine now now once

we have the data

let's go ahead and log the data once

again

and i didn't remember my semicolon after

that being a little inconsistent okay so

we have file ops i'll delete the read

file operation

and now here

we're just going to call file ops into

action

we'll have node index in the terminal

oh and i didn't save the file yet

there i'll save the file

hopefully we don't have unexpected

results now and node index in the

terminal and we got hi my name is dave

the data that we expected to get let's

add another await in this process of

file operations

we'll say await fs promises and now we

will write a file

and this file is going to be promise

right so we'll have the same type of

path once again which i can just copy

and paste

but we'll just call this

promisewrite and after that we want to

pass in the data

that we just read

and now i'm going to copy down once

again

and after we write a file let's go ahead

and append to the file

and now

in the append area

we'll just say

nice to meet you

oh let's put a couple of line breaks

here

with backslash

lowercase in so two line breaks

and one more copy down

and now let's rename

[Music]

and we're renaming promise right so

we'll just copy this once again

and instead of content now we need to

put

the new name of the file and this will

be

promise

complete

and we can save that so you can see

we're taking the data from the starter

then we're writing a new file called

promise write then we're appending to

the file

and then we are renaming the file and

finally let's go ahead

and copy these two lines once again

and put them right here

and now we'll call this

new data

and here we want to read the new file

which is

promise

complete and then we'll go ahead and log

that data as well so you can see there's

several different operations happening

here we are reading data from a file

then we're writing it to a new file

then we're appending to that new file

then we're renaming that new file then

we're reading the new file and logging

the data from that file so i hope that's

not confusing i just wanted to show all

the operations that we have gone over

and then use them

in an async await fashion so here is

node index

and here was the original content

hi my name is dave but then the new file

has hi my name is dave and nice to meet

you and let's go ahead and look at the

file tree

there it is

and we've got promise complete right

here that has hi my name is dave nice to

meet you let's go back to the index and

let's add one more thing right here i'm

just going to copy this one line

and above it

i'll paste in again and here instead of

write file i'm going to say

unlink

and after that

we don't even need to pass in data

because unlink

is actually a delete so we can delete

this original file

that is called

starter text there it is

and now

that we have it being deleted and i can

get rid of the space here as well so

we're reading the file logging the data

to the console and then deleting that

file then creating the new file

and we can even get rid of promise

complete here again

and we'll get rid of new reply we're not

using that anymore

let's make sure we save the index

and we'll call it into action

once again we got the same in the

console and we have promise complete

over here but no more starter text it's

gone because we deleted it with the

unlink right here and this is also

available without fs promises as the

first examples i showed that were just

fs and then read file write file and so

on unlink is what you would use to

delete a file okay now i'm going to

create a new file over here and i'm just

going to call this

stream.js

now if we have larger files sometimes it

is good to not grab all of the data at

once it could be too much just like

moving a

large pile of sand bucket by bucket or

moving all the water in a swimming pool

bucket by bucket rather than attempting

to grab everything all at once so this

could be more efficient and a little bit

easier on the application if we do this

so let's say cons fs and once again

let's require

fs not fs promises just fs

and here

i'm going to define rs and we're going

to set this equal to fs dot

create

read stream

from here

i'm going to specify our files

slash

lorem.txt once again you could use the

path module would probably be a better

option i'm just doing this quickly so

i'm hard coding that in

and now

putting in the encoding and this is

utf 8 once again so we've created a

readable stream and we've specified the

encoding in the options now let's go

ahead

and specify

a writable stream and this is going to

be ws.com

write stream

[Music]

and now what do we want to

write this to would be the question so

let's call this

from

stream ah let's call it

new dash lorem because it is our lorem

text still that works

so we have new lorem

and really we don't need to specify

anything else here we already specified

what was being read is utf-8 so we're

good there and i did make a mistake here

i needed to make this fs not ws because

this is

getting this from the fs module the

create write stream and that's why it

didn't help me out when i was typing it

okay so once we have that we need to

listen for the data coming in from the

stream so here is our readable stream

and we can say on

now we're listening for the data that's

coming in

and here let's say this is a chunk of

data or a data

chunk if you will

and inside of here we could console log

the chunk or we could just

write to our writable stream and pass in

that data chunk

so let's do that

and i will save

and now let's go ahead and run this so

we'll type node

stream and notice now we have new lorem

as well and this will be a large

file of lorem probably about a thousand

lines yes so it did it very rapidly but

once again a example of a large file

just a

test example we could have much larger

files but in that case when you're

working with a large file this is much

more efficient now speaking of

efficiency i'll go ahead and comment

this out there is even a better way to

do this instead of the listener

just take

the readable stream and use pipe

and then you can pass to the writable

stream this will accomplish the same

thing and piping is more efficient than

this structure with the listener here

i'm going to save this i'm going to

delete the new lorem file

and now let's go ahead and run our

stream once again by typing node stream

in the terminal

and you can see we once again got our

new lorem text file and it has all 1000

lines of lorem ipsum text

okay i'm going to create one more new

file in the file tree and call this

dur.js which is short for directory

once again

let's go ahead and define

fs at the top and require it

and after we do that what i want to do

is create a directory with

fs.mkdir which stands for make directory

and we'll have

let's just call it new we're specifying

what we want to call it right here and

then there's a callback that has an

error

and this is the same as we've seen

previously so if error we could throw

error now i won't go ahead and copy and

paste the uncaught error handling code

in here that i showed you earlier just

to save time but you could use it in the

same way

so if we have an error throw an error

and if not we've created the new

directory so we'll just log

directory

created

and we can save this let's go ahead and

run our code so here we'll type node dur

which is our new file dur

and directory is created and now we can

see here is our new directory now

earlier in the tutorial we threw an

error on purpose because we attempted to

read a file that did not exist

well we can check to see if files and

directories exist or not so we don't get

those errors and we also might want to

check in this regard to say if the

folder if the directory already exists

let's not create it because we don't

want to write over what we already have

so we can use

the exists sync method and let's start

out with if and then we'll say if it

does not and not would be the

exclamation mark

fs dot

exists

is it exist yet two s's exists sync

and then we'll say the same

folder slash or the same directory dot

slash new so if it does not exist

then go ahead and do what's inside of

the if statement

and we'll put that right there let's go

ahead and close that out and close this

out

and save and now let's see if we create

the directory when we run it in the

terminal

and no no directory was created because

it exists

so this says if it does not exist create

it so let's go ahead and delete the

directory

and now let's run this once again

and now it created the directory again

because it did not exist you might find

checking for file existence fairly

useful before you attempt to delete a

file if it exists or not or before you

attempt to even rename a file or copy a

file several things that you want to

make sure the file exists likewise you

can check directories in this regard now

let's go ahead and write some code that

deletes

the new directory okay let's copy this

down

highlight everything

and bring it down here to line 10

and now let's check to say if it does

exist

and this is the folder we're going to

remove the directory and that is

rmdir for remove directory so this would

be a zero sum game here if it does not

exist create it

and if it does exist remove it so now

let's say directory

removed

and

we'll be able to tell by the console but

in the file tree

we should not have a directory when

these operations are complete

and the directory was removed it already

existed so it wasn't created but it was

removed let's go ahead and run it again

and now it was created and removed and

so it's still not in our file tree but

we can see both operations completed

today we're learning about node package

manager which is also commonly known as

npm and when you install nodejs from

nodejs.org which i have open right here

you also install npm however npm also

has its own site and documentation at

npmjs.com so let's take a look at that

and you can see the

npmjs.com site here one little quirk i

really like about

npmjs.com is they give

wrong answers for what npm stands for in

the top left so every time you come back

to the site you'll see something

different here right now it says new

prog mixtape it really stands for node

package manager and npm provides

thousands of packages for us to use in

our applications the difference between

a node common core module and an npm

package is that npm packages are node

modules that are created by third

parties in other words other developers

so let's search for something here like

axios which is a node package

and we see the results axios is at the

top with an exact match and you can see

they're also ranked by popularity

quality and maintenance and you see the

little chart over here to the right so

essentially other developers create

reusable modules and share them through

npm so instead of recreating the wheel

we can search for a module that already

exists and then we can import that

module into our applications now today

i'm going to go over what i consider to

be essential npm knowledge and we're

also going to install some packages that

we'll need in the near future when we

create an event logger i'm going to

start by showing you where the

documentation is at

npmjs.com click on documentation at the

top then it takes us to docs.npmjs.com

now when we're there what we're really

working with

is the cli

and that's what developers typically use

when they're integrating npm into their

projects and their cli commands

configuring npm and using npm there's

quite a few commands i'll just go over

what i consider to be essential what i

use the most and what you really need to

get started but i always want you to

know where to find that documentation

and reading the docs is definitely a big

part of being a developer okay let's

move over to visual studio code i've got

visual studio code open and i have a new

folder for the tutorial and then an

index.js file that is completely empty

right now we're going to start off by

just putting a console log statement and

saying testing

inside of our index.js and we can save

that file now i want to open a terminal

so we can go to the terminal menu or

since i'm in windows i'm just going to

press control and the back tick and it

will open up a terminal

now in the terminal

we can install a node package globally

that we can just call from the command

line without adding it to a specific

project so i'd like to do that first

i'll type npm

and then the word install works but you

can also use the alias i or there's also

an alias ad

i typically use just i

from there i want to install node mon

and this is a great development package

but it's also good to install globally

because you might just want to call it

from the command line

and with nodemon

we want to put dash g now what nodemon

does is it monitors your files and as

you save it automatically restarts the

server so we're not always typing node

and the file name in the terminal it

just kind of does it for us so i'm going

to go ahead and press enter to install

this package globally and then when it

finishes we'll see how it works with our

index.js okay and the package installed

we're ready to try out nodemon so let's

type nodemon instead of node

and it's going to look for the index.js

by default so i don't really need to

type that name but if i had a different

file name like server i would type

server or something like that right now

i'm just going to type nodemon

and it will know to look for the

index.js and it says it is watching the

extensions js mjs and json and it

started our index.js

and here we can see the message testing

so it did go ahead and log to the

console testing now i'm going to change

the file

add an exclamation mark and save and

then you can see it was restarting due

to changes and then it went ahead and

ran the file and we got testing in the

console so that's how nodemon works now

to exit nodemon you can press ctrl c

just like we would exit a node

application that we were running if we

tested it by typing node index now that

you know how to install a package

globally let's go ahead and add a

package to our project but before we do

that we have to initialize npm for our

project i'll type npm and then just like

when we initialize git if you're

familiar with working with git

we type init now it will ask some

questions at the beginning if i want to

skip those questions i'll just put in

the flag hyphen yes to answer yes to all

the defaults but i'll go ahead and not

do that just to show you the questions

it will ask

and then i'll just press enter on each

one to go ahead and accept the defaults

but first it's going to initialize npm

okay it's asking me the package name and

the default would be zero three tut what

i named the folder

and then the version by default is 1.0.0

description you don't have to enter one

entry point by default is

index.js but we could change that to

server.js or something else if we wanted

to

test command nothing to enter there we

don't have a git repository yet no

keywords you could put your name for

author if you want to

and there's the license by default and

then it says is all of this okay and the

default is yes so i'll just press enter

one more time

now if we look over

in the file tree we see a package json

file and this pretty much has all the

information that we answered those

questions to then the package json file

is important because this is what npm

reads to know what packages to install

for your project and that is because

this file will stay with your repository

if we send it to github

but we won't send the packages itself

and that way we don't have to transfer

as much data or store as much data

and then when somebody else clones or

installs this application it can just

read the package json or likewise if we

were to host it and build the

application

at a host and run a build command

then it would install those packages

there without having to transfer them

over from github

so now that we have this let's go ahead

and add a package to our program and i'm

going to say npmi

and then i'll type

date dash fns which stands for date

functions

and press enter and it will install this

package as a dependency which we will

see in our package json file okay that

completed installing and we now see

dependencies listed in our package json

file and these are production

dependencies we see listed here so when

the project would build with a build

command it would include this package

because we would know it would be part

of the overall application that needed

to go into production but we can also

have dev dependencies before we get to

the dev dependencies though let's go

ahead and look at the file tree because

now we have a package dash lock dot json

and we don't want to change anything in

there that's just handled by npm but you

will see it show up in its file tree

we just work with package.json we also

see a node modules folder and this can

get fairly large fairly fast because

there will be a lot of

files and folders in here and that's

because any dependency that we add can

also pull in other dependencies and if

this package needs all of these

dependencies

this gets very large and that's why we

don't want to store that in github so

what we should do

is always add a dot

git

ignore file oh and i didn't press dot i

got a slash there we go dot

get

ignore

and in this get ignore file

the first thing you should add

should be node

underscore

modules

now i'll go ahead and press save and now

if we were to initialize git and save

this to github the node modules folder

would not be included and that's

important because there is a lot of data

in node modules now i'm not going to

delete the node modules folder right now

but if you were to clone another

repository and it had the package json

but did not have the node modules you

would get an error if you tried to run

or tried to start the project so what

you want to do is type npm

install and if you just type npm install

and press enter it's going to read the

package json file and go ahead and

install the node modules you need and

that's important of course when you're

pulling down another repo say from

github maybe you cloned it and

then you want to install the node

modules that are used in that

application okay with the date fns

dependency let's go ahead and use it now

in our index js i'll get rid of this

console log statement that we have here

and at the top we want to go ahead and

import and we're going to destructure

because we'll just import format

and this is using common js again so we

use require and then we'll say date dash

fns

and now that we have that imported we

can use it in the statement so i'll just

put another console log here and i'm

going to paste in the format but then we

can go over it so we're calling the

format function from date fns and it

accepts a new date

and after it accepts a new date we have

to tell it how we want it to format it

and of course you have to read the docs

to know how to format it and i am

pulling in the year

the month

and

and i didn't mean to do that let's undo

that the month and the days

and then i'm putting a tab in and then

i'm putting in the hours minutes and

seconds and so this will be tab

delimited so we'll have two columns

we'll have the date and the time and we

could use this in a log format and that

will be the end goal eventually as we

learn about events but right now let's

just format this date and go ahead and

send it to the console

now remember we're not running nodemon

again yet so let's go ahead and add

nodemon

as a dev package to our project

okay back in package json we're going to

add a dev dependency now easily

i could run nodemon right here from the

terminal as a global dependency because

we'd already installed it but i just

want to use this as an example of

installing a dev dependency so here we

type npmi once again i'll type nodemon

but then i want to give the flag you

could do dash dash save

dash dev

but there is just a shorthand for that

and it's dash with a capital d and this

will save nodemon as a dev dependency so

i'll go ahead and press enter and let

that install all right now with nodemon

installed as a dev dependency you can

now see that in the package json as well

and it lists a dev dependency so let's

talk about scripts and how to run

our application using scripts because

that's what a server would use if we

were to host this somewhere and you

often see a start script a dev script

and a build script if you're familiar

with react or something similar you have

definitely seen some of those before so

let's go ahead and add a start script

and now in the start script

we need to just go ahead and call node

not nodemon but node

and we can say index right here because

that is what we want to run our project

with

but then let's go ahead and we don't

need a test script so let's change this

to dev

and i'll go ahead and replace

the test script now with nodemon

and we'll go ahead

and we can specify index here as well

but remember it defaults to index js

anyway so let's go ahead and save that

now if we're to start the project start

is one of the few words that works

without the word run so we could just

type npm start

and start our project but we don't need

to do that yet we want to use

dev so let's say npm

run dev and press enter and you can see

nodemon started and we've got the date

over here with the format i gave it

which is

year month and day and then there's a

tab spacing and then we have the time

and you can see we're using military

time which would be 0 through 23 hours

and then minutes and seconds now back in

the index if we were to make any other

changes nodemon will continue to watch

this

and go ahead and restart the server so

then if i just put another console log

and said

hello

save the file nodemon restarts and we

should get the new information in the

console as well and that's what we get

with the hello now i want to go ahead

and stop this again because we want to

add another dependency to our project

while you don't have to look at the

package json while you install

dependencies i'm going to go ahead and

do that so we can see the new dependency

added and here i'm going to type npm i

for install once again and this is a

production dependency so we don't need

to put a flag after it it'll go directly

to the dependencies and we're going to

install uuid which allows us to generate

ids that of course are different for

each entry so i'll go ahead and press

enter and now we can see uuid installed

here as a dependency in our package json

also so let's go back to index

and use this package as well so we need

to import it at the top

and here we'll say const and now

this is a little different now with es6

imports we would say

import

uuid as and give the name that we want

to give it now here we need to import a

version which is a specific version it's

v4

but we want to import that as uuid

and then we can say equals require

and then specify uuid here now you may

see this done in different ways as well

so instead of the v4 this way some could

just use it as v4

or you might see

an import and just here have uuid

and let me get rid of that curly brace

there

and then in the code they could possibly

use it as uuid dot

v4

and call it that way as well what we're

going to do is use it as uuid so back

here we want to make sure it is v4 so

i'm going to say import v4 as

uuid

and now we can use this and this will

log

a different

id or generate a different id to the

console and then of course our console

log statement is what will log that so

let's go ahead and save this and now

once again in the terminal i'm going to

type npm run dev to start nodemon

nodemon started up and you can see we've

got the format of the date with the date

and time and then on the next line the

second console statement we got the

result of calling uuid and if we just

make any change basically to the console

it's going to generate

another

uuid that's different than the one we

got before of course so you can see how

it generates a different id each time

and that can be very useful including

with something we would log such as an

event whether it's an error or a request

or anything like that that we might

write to a log file we might want to

give each entry its own id i want to

jump back to chrome really quickly just

to draw your attention to

how we can search for these packages

because you might be wondering how do i

know about these packages well you could

search for id

and see what would come up and remember

they're also ranked by popularity and

we've got nano id short id but we don't

see uuid but somewhere i learned about

it along the way and if you do search

for uuid it will show up here it is the

exact match popularity is huge quality

is good and so then when you go to the

page you can read about the details for

the package you want to use so here's

some good information about it it tells

you how to install it and of course it

quickly tells you how to install it here

shows you where the github repository is

weekly downloads that's a very popular

package right there so this is a good

example of course there's some docs as

well and you can look that up and of

course you can search again at the top

i'll look for date dash fns

many times a package will have its own

website as well that has documentation

and date fns is definitely one of those

that do of course

notice it changed nomadic people

migration at the top for npm

i always like the different uh

definitions it gives npm again node

package manager this says it's like

lowdash for dates lowdash is another

package you could use but this datefns

has its own github repository it also

has its own web page that i believe is

linked here somewhere if i scroll down

maybe we'll see that oh here it is see

datefns.org for the docs so there's all

kinds of information about each package

as you explore that i just wanted to

highlight that again as we work with

these and now let's take another look at

the package json because there is a

little more detail we need to look at

look at the packages we have installed

here under dependencies

or also under dev dependencies and you

can see we get the semantic versioning

numbers

now let's talk about these because this

first number means a major version the

second number means a minor version

and the third number

means a patch

now the carrot we see in front

means go ahead and allow an update to

the minor version and the patch if

needed but do not update a major version

a major version could have breaking

changes to your application so you don't

necessarily want to allow those you can

now if you don't put anything in front

of the number

this is saying specifically this version

and only this version for this project

will work so once again if you put the

carrot that is saying go ahead and

update minor versions or patches but not

a major version

so now if we have what's called a tilde

the little squiggly kind of let me put

it there

this is saying go ahead and update a

patch version but do not update a minor

version so if you see the tilde that

will allow patches only and not minor

versions or major versions

now if we got rid of this all together

let me go ahead and put the carrot back

because i'm going to want to

replace that

and you just saw an

asterisk in here

this would mean go ahead and update

everything all the time use the absolute

latest version every time

that is not too safe although you might

see it this is what you'll typically see

and what is installed by default to your

package json is to have the carrot here

and it's worth noting that when you

install if you specifically want to

install a different version or

any kind of version you can just have

npm install

and then say we would type uuid and then

put the at symbol

and after that say the specific version

you want if you wanted

8.3.1

then this would install that specific

version however if you just say

uuid you're going to probably get the

latest version when you install here but

then it's going to mark it to not update

any major changes because those could

once again cause

a break in your application so that

could be what would be considered a

breaking change i'm going to go ahead

and save the package json now and if

there were updates or if you wanted to

check for updates to say okay is uuid

does it have a new miner version or

something like that if we had it like

this remember it would not install the

major version but if there was a minor

version or a patch you could just type

npm

update and npm will check for any

updates

for your packages and you can see i had

no updates or it would say something

about that as well so there were no

updates there so the only thing that i

typically use or would might need to use

that i haven't shown you on a regular

basis would be uninstall so here we can

type npm

and then you could use

the full uninstall

or you can just use on or you can use rm

for remove so let's just go ahead and

use rm and then we're going to uninstall

nodemon but nodemon is a dev dependency

so you always need to add that specific

flag if it's a dev dependency or if we

wanted to install the global version i

would put the dash g as well now if it

was production you wouldn't have a flag

at all

so let's go ahead and uninstall the dev

dependency node mod

this is worth noting we did uninstall it

so there is no longer

a dev dependency listed it went ahead

and kept the dev dependencies in here

but it's just an empty object right now

however we still have nodemon listed in

our script it's not going to

automatically change a script for you so

that could be an issue if you want to

install something that you have in a

script you need to remember to go

and check for that as well the nodemon

is something i would probably have

installed as a dev dependency so we

could just re-add that but again worth

noting if you uninstall a package it

doesn't remove it from your scripts so

you need to check that as well

today we'll be learning about the events

common core module in node.js and more

specifically how to both emit custom

events and how to respond to those

events when they are admitted

right now we're picking up where we left

off in the last tutorial about npm

modules and if you didn't see that

tutorial you can just catch up by

installing the dependencies you see

right here so for production

dependencies we have the date fns module

and the uuid module you could also refer

to those as packages also as a dev

dependency we have nodemon installed and

then in the scripts of course the start

script is node index but what we would

use in development is the dev script and

that is nodemon index so if we type npm

run dev it will launch nodemill and

nodemon will listen for the changes in

our files and restart the server without

us constantly having to type that so

again if you didn't see the previous

tutorial just update your package json

and

npm installs to this and if you don't

know how to do that please do watch the

previous tutorial okay let's move over

to the index js and you can see we're

already importing format from the date

fns module and then we're also importing

uuid and it's actually

v4 there's different versions in the uid

so we're importing v4 as this is an

alias as uuid so we can call that right

here and you can test these out with

these console log statements that we had

from the previous tutorial but what i

want to do right now is rename this

index file so i'm going to right click

and choose rename and i'm going to name

this

log

events in camelcase.js so this is a

complete different file and i'm going to

make this into a module that we import

into an index.js that we haven't created

yet so we need both of these imports

but we're going to make a logging

function of course logging events is

something that's very useful on a server

let's go ahead and also import the fs

module so

we'll require

fs

and then we're going to want to use

promises

so let's say fs

promises

set this equal to

require

fs

and then dot

promises

and we also need the path module

so here is require

path

and now that we have all of the imports

we need and notice these are the only

two that we really needed to use npm for

because these are all common core

modules here that we imported

now that we have that

i'll get a couple of extra lines let's

go ahead and define our log events

function that we can export

and it's going to be an async function

and it will receive a message parameter

now inside the function

we need to define we'll call it date

time and let's set this equal to

and let's just grab this format that we

have right here and copy this

because that's what we essentially need

i'll use a template literal

and inside here i'm going to paste

the format the new date it's got the tab

and then it will just in the template

literal

and leave it at that and then we're

going to take another definition here

and call it log

item

and we'll really use the date time so

i'll put another template literal

and we could have done this all in one

line but this gets kind of long if we do

that so i wanted to break it up

and so we've got the date time then i'm

going to put another tab and remember

there's a tab in here too so what we're

doing is creating a tab delimited log

file

and now i'm going to use uuid

and call that to get a unique id for

each log event

and then one more tab

and we'll just put in

the message

there we go and now that we have our log

item let's go ahead and log that to the

console so we can see it while we're in

development mode here as well

and now we need a try catch block let's

get to the async await portion of this

function

and we'll catch an error if an error

happens and let's just

log the error to the console if we have

an error writing to the log we won't be

able to write the error to the log so

this is the best thing we could probably

do right there

but in the try block

we can

await fs

promises

and then

let's go ahead and append file if you

remember from our tutorial on working

with files a pin file will also create a

file if it doesn't exist and now we need

to use path and we'll use path join

and two underscores and then we'll use

the directory name value and then let's

put it in a logs folder and after that

let's call this event log

dot text

and then we still need to pass in the

content that we're going to put in the

log right after that parentheses we need

the comma and that would be our log item

that we defined okay now we can save

this much

now i am thinking of something that

could cause an error in the future and

we'll get rid of these console log

statements down here but i want to leave

it like this for now so we can actually

test out getting the error as well or

catching the air

so let's do module.exports

and set this equal to

log events

now we're exporting our log events

function and we'll be able to use it in

the index that we're going to create so

over in the file tree we'll create a new

file called index js

from here let's go ahead and define

log events and set it equal to

require

and now dot slash because this is once

again a custom module not a common core

module or an npm module and so dot slash

log events and now we're ready to work

with the events common core module and

what we want to do is define an event

emitter and let's set this equal to

events the common core module events

after that we need to define a class

so class my emitter

and it's standard to capitalize instead

of use lowercase on the first my there

for a class

and then we want to say extends

event emitter

and then we can just have the empty

curly braces right here this is i know

it looks strange but it's directly from

the docs as well

from here we can

initialize

the object that we're going to create so

we want to create my emitter but now

oops

this needs to be a lowercase m to start

out so don't let it change on you or or

select the option that would select the

previous my emitter

and now that we've got my emitter

defined let's set it equal to a new

object that is

my emitter right here so we've

initialized the object i know that's a

little confusing

but that's what it looks like in the

dock so i just stuck with that

and then we've got

add a listener

before

the log event

so then we can say my emitter

dot on and that is how we listen for an

event and i'm just going to call this a

log event

we could be listening for any event we

want to this is the first parameter of

listening for an event so we just say

which event we're listening for

and then we can call this anonymous

function to pass in the parameter

message

and now inside this anonymous function

we'll call log events

and once again send that message that

was passed in

so now that we are listening for the log

event

we need to go ahead and omit the event

to test this out now i want to set a

timeout

which will hopefully

let us understand how everything is

processed a little bit better but we're

just going to

emit the event

you don't have to have a timeout to do

this i just wanted to put a little delay

in there so once again we use my emitter

dot omit now not on on is listening so

emit is emitting the event now we'll

emit the log event

and then let's go ahead and send our

message i'll just say log event

emitted

that looks good now let's put a delay in

here with the timeout and i'll put

two seconds that may be too long it may

not be long enough to see the difference

just depends how long it takes nodemon

to restart the server

so now that we've got that saved and

this is our index let's go ahead and

open a terminal you can do that from the

terminal menu or i do control backtick

i'm in windows

and now i'm going to type npm run dev to

launch nodemon and our index js

and we get an error so let's see what we

got i did expect to get one

notice we did log to the console so

here's what we would have written

to a log file

we've got the date we've got the time

we've got the unique id and we've got

our message log event admitted so that

all worked out as expected but we have

an error and let's see what it says here

console error is not a function well i

should have typed console log here let

me go back and fix that

we definitely have another error that i

was expecting to see so let's drop this

back down and of course nodemon should

restart after i change this so instead

of console error let's put console log

we might have to restart nodemon let's

see yep now it restarted and we can see

the message that i was expecting to get

so here once again we got the log file

and then we got no such file or

directory

and that is because append file will

create the file if it doesn't exist but

it won't create the directory and we

didn't have a logs directory yet so we

need to modify our function because if

you think about this when you install

some software

there may not be all of the directories

created that you need so let's modify

this try block to account for not having

that logs directory to begin with if you

notice we haven't used the fs module yet

we had used fs promises so in the try

block let's say if

and then we'll say

not if it not exist is what we're going

for here so fs dot

exists

sync

and then we want

path path.join

two underscores and directory name and

then we're just looking for the

directory so if this does not exist

essentially is what we're saying

then as you might guess we want to

create that so we'll say await and now

use fs promises

oh and then we need dot

mkdir which is make directory

and we can say path.join

once again

two underscores in the directory name

and create

the logs directory please so now

if the logs directory does not exist it

will create the directory and then it

will either create or append to the

event log file so let's make this change

and now if we look back

we can see we got no error on this

latest execution once again everything

wrote to the console and now i'll bring

this down

and if we look over here we have a logs

folder

and we have an event log

and there it is we wrote to the event

log

now let's go ahead and run

the program again we'll need to make a

change of some sort to do that

and then we can check the event log so

let's just make a quick change here by

putting in a

console.log or no you know what we don't

need to do anything like that we could

even just put in a comment

say testing

save

and we should be able to see some

changes once again if we go back to the

event log oh we've got another problem

after our message

we didn't put a line break

and so then it just wrote the next log

on the same line so we need to put in a

line break after that as well so let's

go to our log events

and where we define our log item at the

end of message then

let's put a line break with a slash in

and now this should make a difference

let's check the event log again

and maybe it made a difference

i'll tell you what let's try this i'll

just delete this all together

now the file doesn't exist

i'll get rid of the testing

save

write the file let's look at the file

there it is

now

back here once again i will undo

put the testing back and save

and let's look at the event log there it

is we've got another log event emitted

on a new line and everything is lining

up as we expect

delete testing again and save

and there it wrote a third line to the

log so this is working as expected so

here is a abstracted

log events function that you could use

you could accept more than one uh

parameter as well

and if there was a second parameter here

when we would be in

the index.js when we admit this we would

just need to put the next parameter

right here

so there can be more than one parameter

as well and this is how

you set up an emitter to not only listen

for

but to emit events now there might be

all sorts of actions that you want to

emit events for when we create a web

server we're wanting to emit events to

show what requests came in

and log all of those so we have some

detail of the activity for our web

server and that's what we'll be building

next a web server with node.js

today we will be building a web server

with node.js no framework will be

utilized and this will help us learn

more foundational knowledge about nodejs

and then in future tutorials i will

introduce the express js framework we're

picking up right where we left off from

the last tutorial about the nodejs

events module so let's go over some

quick changes and file additions and i

will be providing a link to a github

repository in the description below okay

in the package json you can see i have

changed the name to o5 tut for the fifth

tutorial in this series you can change

that whatever you want

now i've also got

server.js instead of index.js as the

main file and i have changed the scripts

accordingly so it says node server and

nodemon server instead of node index and

nodemon index other than that we still

have the same dependencies as the last

tutorial so date fns and uuid are here

and the dev dependency of nodemon is

here and those are the few changes for

the package json of course i have

renamed the index file to server.js you

can see everything else is currently the

same here

in the server.js file that was

previously the index.js file and we will

come back to that i want to delete the

event log file that is currently in the

logs folder you can leave the logs

folder if you want to if not it will be

recreated and that's because we still

have the same log events js from the

last tutorial here as well

and we might make a change to that but i

won't do that now either we'll come back

to the whole events topic

what i do want to show you are the other

folders and files that i've added and

these are simply to be served by the

server so we can make sure it's working

i've got a style dot css file

in the data folder i've got a data.json

and a data.txt

and you can just put in whatever

information you really want to and style

the page or web pages however you want

to i've got one image in here again you

can download the repository and get

exactly what i have or you can use your

own and then in the views folder i've

got a 404.html

an index.html and a new dash page.html

and i also have a subdirectory named

subdir

and in this subdirectory is another

index.html that will be the default page

for this subdirectory route and so we're

going to serve all these different file

types or content types from the server

today now let's make some changes and

additions to the server.js file i'm

going to eliminate some of these blank

lines and then when we created a class

my emitter that extended the event

emitter in the last tutorial it got kind

of weird when we initialized our object

and it was also named my emitter so i

just want to name the class emitter and

this is just kind of for my peace of

mind after that we can get rid of that

extra space too we will leave all of

this here i'm going to get rid of the

comments

about the listener i'll also get rid of

the timeout that we added because that

will not be needed and i'm going to

comment out

both of these right now

and then we'll come back to those later

on when we need them

give a little space in between now let's

go ahead and import the common core

modules that we'll need for this file at

the top and the first one we need is

http

and so that's one we haven't covered yet

that we will today

and we just require http

after that we need path

and we'll require path

and we'll also need

fs for the file system so we'll require

that

expo require

and we're also going to need fs

promises so that equals

require

fs but then at the end dot

promises and those are the common core

modules we're going to need and now we

need to define a port for our web server

so not only will it have the address of

localhost because it will just be a

development server on our local machine

but we need to say what port it will be

on and so now we'll just define port in

all caps definitely a constant here

and we should say process.enb

dot port because if we were to host this

somewhere it would use this information

and then we can say or and i'll say 3500

today i've seen different ports used and

so today we'll be using port 3500 if we

were to host this somewhere

it would have a different value here now

that we have defined the port let's go

ahead and create

the minimal server we can do that by

defining

server and let's set it equal to http

dot

create server

and now that gets a request that we'll

just call req

and a response

in a function

and now we have our request and response

headed into the server and we won't

really do anything here at first except

let's log

the request

dot url

and let's log the request

dot method

we're not quite ready to launch our

server yet because it still needs to

listen

for requests so we say server dot listen

and this should always be at the end of

your server.js file

and we give the port value

and then we have an anonymous function

and here we'll just say console.log and

inside this

console we'll use a template literal

we'll say server

running on port

and then let's once again give the

port value here

and that's really all we need so once

the server starts we can see this

message and i'll go ahead and press alt

z to make it wrap so we can see it i've

got chrome open over here so we can

eventually request a page as well

and we should see this statement in the

console once we start our server i'm

going to go ahead and save the file and

then open a terminal window by pressing

ctrl in the back tick you can also do

that from the terminal menu that's

hidden behind the three dots right now

in my

visual studio code

and now let's go ahead and start the

server by typing npm let me lower case

there

run dev

and this will start nodemon that will

listen for changes

and the server should start up

and we can see that we now have server

running on port 3500 it's not going to

serve anything we're not sending any

type of response back yet we're not

using the response but it will log the

request and the request method so let's

go ahead and type

localhost 3500

and notice in the console we've got the

request here which is just the slash

and then the method is a get request not

a post request or a put request or a

delete request

but a get request

and so we did successfully log those

requests but there's just nothing that

comes back yet i'm going to go ahead and

press ctrl c for now because we don't

need to run the server while we're

making a few changes and now of course

it can't serve a page

but that's no worry we'll be serving a

page soon what we can do is talk about

what else we could put in the server

and so after we're logging the url and

the method and the url was just the

slash as we requested the index page

what we could do

is

build a path and then serve the file so

i'm just going to copy some code in to

discuss it

but this is not what we'll want to do

and i'll discuss why i'm going to go

ahead and expand visual studio code for

now too so we don't have to wrap the

lines

but we could listen for a specific path

so we're defining path here we've got

two semicolons we just need the one

and if it is just the slash or even if

we specified index html either one of

these would work and this is an if

statement

then we could set the response dot

status code to 200 which means

successful

we can set the response header content

type

to text slash html because we would be

serving the html page

and then we could go ahead and use path

to define the path value

and look in our views folder

for the index page that we have right

there

and serve that page and how we would do

that would be to read the file that we

currently have

and i didn't bother with

handling the error in this

version but

what we would do is read the file and

take this data

and then send the data

and we would be sending the contents

essentially of the index.html file this

would work but this is not efficient we

would have a statement

for every address that came in and

actually every file because of course

we'll be serving some files that are not

text html and feel free to try this

version out i'm going to show another

version that we will not use but that

you would also see in a possible simple

server and i'm just showing part of it

here i guess i could go ahead and close

it out

but we could put in a switch statement

and we could look at the request url

value that comes in and here if it's

just a slash we could go ahead and once

again set the status code set the path

read the file and then of course break

out of our switch statement and we would

have to have a case for every value that

came in even a duplicate case

essentially if this were to be

index.html and not the slash and this

would also be very big and you would

have to think of every possible file

that could be requested your default

could of course be the 404 if it doesn't

exist but this also takes up a lot of

space and once again it's not dynamic

and so this is not what we want to do

today either a switch statement is

useful though so let's take a different

approach but we will still use a switch

statement as we construct what our

server does today so we'll start out

once again let's keep the console log

statement with the request url and

method that could be useful as we

monitor things during development and

then let's look at the extension

of the request url that we get and so we

can use the path

dot

name method to get that extension so

let's just pass in the request url now

once again if it's a slash maybe there

will not be an extension name but then

we can handle that as well so now that

we've defined the extension

let's also define

content type

and now we will use a switch statement

to set the content type and i'm going to

paste this in because we'll be looking

at all the different

possibilities for file extensions so

there are several and now we can go over

this but what we see up here above

is we set our extension

and then we define

content type with a let at least we

begin the definition and then we can set

it in the switch statement so here we're

looking at the extension

and now if it's dot css we set the

content type to text css and we break

and we go on and do this for every type

of request that we expect to get or file

content type that we expect to have

requested and you can see there's a

couple of different images here we've

got an image slash jpeg and an image

slash png

text for text slash plain we also have

json which is application json so all

the different types of files we expect

to serve and importantly here the

default

is the text slash html because this

could

not have an extension at all it could

just be the slash

or it could have the extension of html

and so we just handle that as the

default okay the next part if you have

not worked with chain ternary statements

you may not like me too well right now

but i do like chained ternary statements

so i will paste one in and explain it

what i want to do is set the value of

the file path

and now a chain ternary statement like

this one can be confusing especially if

you haven't worked with them much or if

you have worked with them at all but

let's break it down

we're saying that whatever the result is

will be saved here in the variable file

path

so we say if the content type is html

and the request url is just a slash

then this will be the value and we set

the path name

using the views directory as well as the

full path name here we get from the dur

name value

and we set it to index.html

but if that's not the case then we look

at the next condition and that next

condition is here and we're saying okay

if it's an html file type or content

type

then

if the last character in the request url

is a slash

this accounts

for

our subdirectory possibly and not just

the main directory and so this would be

just a little different because we not

only need the views in the file path but

we need the request url that would

specify the subdirectory

and so this is what happens if that is

true

and then if not we go ahead and just

check

now to see if the content type is html

at this point since these other two were

not true

and then we would look at whatever was

requested in the views folder because

that's where the html should be

however

if that's not the case

then we're going to go ahead and just

use the directory name or the file path

and the request url because this could

be

css

or an image or something in one of the

other folders that would be specified in

the request url

so another way to break this down

is everything that starts with content

type is a conditional statement and

everything here that starts with path is

a result if the previous conditional

statement is true and then the final one

the final path because there's two paths

in a row is just the default if none of

the others were true

and so you could break this out into an

if

else if else if else statement if you

want to do that i prefer chain ternaries

myself

and that is what we end up with let's go

ahead and add one more statement here

for the file path and this will be an if

and we'll say if

there is no extension which means it was

probably a slash and didn't have a file

extension

and the request url dot slice

minus one which is the very last

character of the request url

is not

equal to

a slash

so maybe we've just requested a file

like about or new page we have a new

page over here but we didn't

type the dot html afterwards well this

will make that work anyway and sometimes

that's cool to do so this wouldn't

really be required but we're just making

our

addresses work even if we don't add the

dot html at the end so then we'll just

say file path plus equals

and then we'll add the dot html here so

we still serve the correct file although

we might not have typed in the dot html

in the url

bar in the browser so we should probably

add a note to this and i'll just say

whoa i went too far here we go

makes the

dot html

extension

not required in the browser

and that's what that statement is for

okay now we have our file path and

content type so we're ready to actually

check

and see if we want to serve the file and

we can do that with defining file

exists

and setting this equal to fs dot

exists

sync

and let's just pass in the file path

because now

we are checking to see if this file

exists or not so this will be a true or

false value that we get back and we can

check that by saying if

file exists we don't need to say if it's

true we're just saying if the file

exists

then we're going to

serve the file

but if it doesn't exist we also need to

have

an else and there are possibilities if

it doesn't exist this could be a 404

or this could be a 301 which is a

redirect now we still aren't serving

anything yet we have determined our file

path and we have determined our content

type but this is where we would serve

the appropriate files right here for now

let's just go ahead and log to the

console and what i want to log here

inside of the else is the path dot parse

that will tell us the different parts of

the file path

let's go ahead and pass file path in and

take a look at a file path that doesn't

exist so we need to start the server

again i'm going to go ahead and change

this so we can see the browser as well

and then i'll open a terminal window

and now let's go ahead and type npm run

dev

and the server is running we can reload

first and just make sure we get the home

page well i guess we won't get a home

page but we can make sure the request

goes through there we go

and so we'll add the homepage very soon

but let's go ahead and look for

something that doesn't exist at all

because the file does exist so when it

checked it didn't get into that else

area let's just say this is

old right here

okay there was something that didn't

exist i'm going to expand the terminal

window up so we can see this broke out

now and we can see

using the path.parse we get these

different parts

of the file path and what we're

interested in right now is the base

notice it's

old.html even though it didn't exist

that's what we get because it was added

in the file path

so that's what we're going to use

as we come into this area that does not

know if the

file should be a 301 or a 404

and we'll determine that with a switch

statement i'm going to go ahead and

highlight this and just change that

console log now

into a switch

and now instead of just

path.parse.filepath we want to put

dot base at the end of that so that

would be that value

and then we get our curly braces for the

switch statement we don't really need

the semicolon there and we need to put

our cases in here so

our first case would be

old-page

dot html

and this is an instance where we had an

old page and we want to redirect it to

the new page that we see over here in

our file tree so let's handle this

redirect first and this will be response

dot right head

and then a redirect is a status code of

301

and now we need to go ahead and put in

the value here for the header and this

would be location

and then the location is slash

new dash page

dot html

and now that we've handled the redirect

we need to go ahead and end the response

and after we end the response well we

need a little column there

we break out of the switch statement

there and now let's add our next case

our next case is going to be another

redirect

and it's www.page.html

and now i'm just going to copy this much

because it's very similar here for

another redirect

and paste it down we've got a 301 again

but instead of new page we're just going

to redirect to the root which is the

slash

and so that will just redirect back to

the home page once again end and break

and now let's have a default as well for

our switch statement and this could be

larger if you had more redirects to put

in here but the default should be the

404 and so this is where we're going to

serve

a 404

response and let's save this

once again i'm going to expand visual

studio code because that was wrapping a

little weird but here you can see what

we have now we're currently not ready to

serve the new page or the home page yet

we haven't got anything else being

served but we did handle the redirect so

what we need now

is a function instead of repeating the

same function here for a 404

or up here for other files a function

that we can call in both spots okay

let's scroll back up to define our

function and we will put that before the

server and after the port

so let's call this function

serv file because that's what it will do

it'll need to be an async function

and then it's going to need the file

path so we can grab the file that's

needed it's also going to need the

content type so we can set the content

type that is going to be sent and it's

going to need the response object to go

ahead and send that response

so now that we have our parameters

defined and we have the name of the

function

let's go ahead and start by defining the

try block we already know it will be an

async function so there will be a try

and a catch

so we can use await as we get the

information we need let's go ahead and

set the error block first so we'll log

the error to the console

and then we also want to set the

response dot

status code

this would be 500 it would be a server

error here if we could not read the data

from the server that we want

and then we need to end the response

notice i called the parameter the full

word response before we were sending

the res for response right here and

that's what we will pass in as we get

down there further but in the function

i'm using the placeholder here's the

parameter with the full word response

and now in the try block let's get the

data from the file so let's define data

and set this equal to await fs promises

and then dot

read file

now we need the file path to read and

we'll use utf-8

and after we read the file and we are

awaiting that information we can use

response and then right head and inside

right head

we'll go ahead and say

200 status code

and then the content type

there we go content type will be equal

to the content type value that we have

passed in

and then finally we'll have response dot

end and we can just send the data back

now some of you may be thinking ahead

and there are some problems that we will

have with this but this is the very

basic to start out with so i want to do

that first now let's go back down into

the code and call the function where it

needs to be

so after we have the file path and the

file event exists here we say serve the

file so this is where we would call our

serve file

and this should have

the file path value

you have the content type value and it

needs the response object and notice

here it's res because that's what it's

defined as to begin with not in the

function definition of serve file but

what we're using in the server

okay let's just copy this and we'll make

some changes below

as we want to serve a 404 here

so i'm going to paste this in and then

we'll just change a few values

okay here we know exactly what file we

want to serve so we're going to use path

dot join

and pass in the directory name and then

we know it's in the views folder

and then we know

it's the

404.html file and we also know the

content type so we can just set that

to text html right away and then once

again we need to pass in the response

object so let's save that as well now

i'm going to resize visual studio code

again

and we'll go ahead and scroll down and

it looks like of course nodemon's

already working

and yes the requests are coming in and

we served our 404 already because old

doesn't exist so let's go ahead and back

out of here

and see if we can serve the index

and yes the index page serves just fine

too i'm going to go ahead and show the

terminal so we can see all these

requests coming in

and you can see old was a get request

and then it requested the style sheet

requested a fave icon which we don't

have

requested a index page then and once

again the style sheet and once again the

fave icon after that but we still have

some file types that will be issues so

let's take a look at some of those as

well say if we went to our

data folder

data.txt well that seems to work okay

even if we aren't sending the accurate

file type with it but what about data

dot json

that's just text that's not really json

like we would want to send back even

though it looks like it and could

possibly be parsed into it that is not

the format that we really want to send

let's also check our new page

because it should have an image on it

and the image doesn't work either so we

have some file types creating problems

what should be working is the redirect

so let's go ahead and type in

old-page.html

and yes it does redirect immediately to

the new page so that's good and what

about

requesting something in our subdirectory

and yes we got our subdirectory index

page so that also works like we expect

it to let's go back to the data and see

if we can fix that json first so data

slash data.json

i'm going to hide the terminal window

for the rest

of this and scroll back up to

the function that we created serv file

and i'll go ahead

and expand the window once again let's

start by changing data that we've

defined here

to raw data and then let's define data

separately so here we have data and this

is going to be equal to a ternary

statement we'll look at the content type

that we already know

and if the content type is equal to

application slash json

then we'll have a true value that

follows the question mark

and that true value will be

json.parse

and this would be parsing

the raw data that has been read

otherwise the false value would simply

be

the raw data likewise when we send the

response we're going to need an extra

line for this so we'll just do it

on a separate line and keep the

parentheses up here and down here

now what we need is another ternary

statement here and we'll look at the

content type once again

we'll say if it is equal to

application slash json

make sure i spell json correctly then

we're going to have a true and a false

and the true would be

json.stringify

and we can go ahead and pass in

oh not the raw data the data and

otherwise it's just going to be data

that we send oh and i don't need that

semicolon that would cause an error and

we can save our file let's go ahead and

resize visual studio code and reload our

json and now we can see it is served in

a much more expected manner here and

this is truly json that has been

stringified

and of course it was parsed to begin

with now let's go back to new page where

we have a broken image

and we can fix that as well so right now

we definitely get our new page html but

the image doesn't come through now this

is because the image would not use utf-8

encoding i'm going to expand visual

studio code again

and let's go ahead and put these values

on separate lines as well

and now we can close out the parentheses

down here on a separate line too

now we still want the file path here but

instead of just utf-8 we're going to

start out by saying

if the content type

and that is not so we'll say if it does

not include but we're using includes

here

and we're looking for the word image in

the content type because both

the png and the jpg

had the image in the uh content type

that we have down here in our switch

statement and you can see it right here

okay so we're looking for that to see if

the content type includes

image and if it does

or if it does not include image i'm

sorry because we have the exclamation

mark that means if it does not include

it would be utf-8 but if it does

let's just put an empty string because a

string is expected in that spot but if

we don't specify then it will go ahead

and let the image go through so now we

can save this

and go back and check our new image page

let's go ahead and reload it

and we've got our image now that we have

the cute dog image there's one more

change we need to make as i expand this

and if you have thought about this we're

sending a status 200 even when it's a

404 because the 404 processes through

here as well so we need to check we

don't want to send a 200 if it's a 404

so right now in the right head let's go

ahead and break these out as well

into separate lines

just gives us a little more room to work

and see everything that's happening so

now instead of just saying it's a 200

status code we can say if the file path

dot includes once again and if it

includes

404.html

well then we know it should be a 404

and else it should be a 200 so once

again a ternary statement just

determining the status code between a

200

and a 404 here in our function we can

save that and now we are close to being

finished we are serving all the files

and they are having the correct content

type header sent with them but we

haven't logged anything yet so let's go

ahead and

remove the comments here and let's copy

each one of these

and first let's take where we're going

to emit from before we handle the

listener

and as we do that we'll scroll up here

to see the server now right after the

console log where we're looking at the

url and method would be a good place

to emit

and we're going to admit a log but what

we want to say here is a template

literal instead of that generic log

event emitted that we had we'll go ahead

and pass in the request url

and then after the request url

we have a tab delimited log file so

we'll put in a tab

then we'll put in

the request

method

and after the request method we'll go

ahead and put a comma because we're

going to add another parameter to our

log event handler and so now what we

want to say is which file we want to put

this log to and this will be to the

request

log

dot txt so we can save that one

and we'll go ahead and copy the emitter

one more time because we also want to

put the emitter up in the error where we

could catch a server error

and here we'll log something different

so instead of request url this is going

to be

the

error.name

and instead of a tab here

we're going to have a colon and a space

and then we can put in the error

dot message

and we're going to go ahead and log this

to the

error log dot txt

and we can save that too now let's go

back and grab that listener

that we need

and get rid of these extra lines at the

bottom you can see we've used just about

a hundred lines even and let's go ahead

and get rid of one of the lines here

because by the time we finish we will

have 100 even that way

now where we'll put this is right

between the emitter and the port

and we will be listening for a log

but instead of just a message we're also

going to have

a file name passed in

and then here

we'll take the file name in the log

events function as well so let's save

that too

but we need to go back to our log events

function

and here

we can say

it's really the log name so let's say

log name and we need to replace the

event log that we used as a generic

example last time for log name right

here and with that saved we should be

good to go so let's go back to the

server just to have it pulled up and i'm

going to open the terminal window again

and looks like we're already running on

port 3500

so let's switch this over

and now let's reload our new page

and we got several things here including

the log statement because i believe

we're still logging those to the console

so that's kind of cool let's look in our

logs

and i'll make the terminal windows

smaller

and here's a request log so we got a

request we got several requests in

and we logged

exactly what we were getting the request

url and the method and they're all get

methods they're all get requests so what

about an error well we're going to have

to create an error so let's do something

simple like

change something we know is wrong so

where it says read file let's just

remove

the e off of read file

we'll save nodemon will restart the

server

and when we reload we should definitely

get an error

yes and we log the air to the console

because that's part of our function

we didn't get a page served because we

crashed with the error here or at least

it caught it and that's what we should

do

let's look at the error log and this is

what we would want to check out if we

had a problem it tells us of course the

date and time is the stamp and there is

the error name a type error and there is

the error message

fs promises dot read fill is not a

function and that's because we had a

typo with read file so we can go back

and fix that

now being in development mode

nodemon is going to restart due to the

changes and all should be well as soon

as the servers back up and run

so let's go ahead and reload

and we got our new page again of course

we can get our index page as well

and everything seems to be serving as it

should now there are some issues here as

we look at our typical

request log file what really stands out

is these are all get requests we didn't

put anything in our code

to handle any other type of request

really we just assume the request method

is git and of course we would have to

put in

more checks to see if it was a post or a

put or what we might want to do with the

information in interacting with a

database so there could be a lot more to

it but this is a dynamic server that

will serve the typical files you would

have with a website and even some data

files that we have as far as data

json and text file here now

express js makes this so much simpler

but this gives us a lot of context to

think about and what all goes into

creating a web server so i think you

will appreciate express js

that much more once we begin to work

with it now that you have created a web

server with node.js only

here we're at the webpage for express

and you can see the definition of

express it is a fast unopinionated

minimalist web framework for nodejs and

this is found at expressjs.com

now you need to have node installed

already and be able to use npm and then

you can add express to your project and

as it shows here it shows npm install

express and then dash dash save you no

longer need that you can actually just

type npm i

express today we're going to reference

some documentation not from the getting

started link but from the guide and go

to the routing page and this way you'll

know how to find the documentation for

what we're going over today let's go to

visual studio code in the last node.js

tutorial we build a web server using

only node.js i'm going to start with the

completed code repository from that

tutorial and that's what you see right

here in visual studio code but if you

don't have this repository you should be

able to easily follow along without it

or you can download or clone it from the

starter source code link that i'm

providing in the description below okay

i'm looking at the package.json file for

the repository now if you just

downloaded or cloned the repository

you're still going to need to install

the dependencies not that we're going to

use all of these today but if you just

want to get the repository up to where

we are you could go to the terminal from

the terminal menu and choose new

terminal or you can use control and the

backtick that's what i use in windows

mine defaulted to powershell and that's

not what i want let me switch that over

real quick

to get bash that's what i expected it to

be

and once i have a get bash terminal you

would type npm

install

and this will go ahead and update all of

the dependencies or install them if you

don't have them so i'll go ahead and do

that as well and you can see it will

just check my dependencies here it

shouldn't take long and when it's

finished i'll know i've got everything

installed that would be

in this repository so currently i have

nodemon as a dev dependency uuid and

date dash fns which stands for functions

all installed as either a dev dependency

or a regular dependency now what we want

to add is express so we'll type npm i

express we don't need the dash dash save

that's

understood at this point so we want to

install express as a dependency

and it just takes a few seconds and

express should be added and you can see

it here in my dependencies listed

between date dash fns and uuid now just

to update a couple of things for this

tutorial i'll switch the name to

zero six tut instead of zero five and

instead of node.js web server tutorial

i'll just put

express tutorial in the description but

those are minor changes and nothing that

you actually have to do i just wanted to

go ahead and update that let's move over

to the server js file or we'll make the

rest of our changes today now much of

what is here and i can close the

terminal as well much of what is here we

don't need anymore so if you want to

make a copy of this file or if you want

to rename the server.js to old server.js

or something like that to save this code

in your repository go right ahead

because we're going to get rid of most

of it we need to keep the path

requirement the path import at the top

and then i'm going to remove everything

else

down to line 12 where we keep the port

definition

and then i'm really going to remove

everything for now

except

where we listen here at the very bottom

on the specific port now we can go ahead

and make some changes right at the very

top on line one let's go ahead and

import express so we'll define express

and we'll set it equal to require

express after that let's define app now

we could use another name here like

we've used server

but

typically you'll see examples using the

word app so that's what we'll go ahead

and define as well and you set it equal

to express and you call express and so

now we can use the app

where we've been using server so we'll

have app dot listen at the specific port

that we have provided now we'll use path

later it's the only thing we haven't

used up to now and now let's come down a

couple of lines and we can define our

first route so we use app and then we

specify the http method that we want to

route so we'll use the get method here

so any get request that comes in

that looks for

just the root this would be our index

page

then we can specify what to do with that

and this takes an anonymous function

here or a function it doesn't have to be

anonymous but this is what you would

typically see and what i will do

and so now what we do with the route

it happens right here inside this

anonymous function so let's start out

very simply as you might expect and

let's just say response dot send

and then we can say

let me use a single quote just because i

like to better hello world

and that's what would be sent in

response

and so now we can go ahead and start the

server and we will expect to get this at

the index page now to start our

development server if you remember as we

specified in our package json we can use

our dev script that uses nodemon so

nodemon knows to restart anytime we make

changes when we save our file it will

identify those changes and it will

restart the server

js so let's go ahead and open our

terminal again and with the terminal

open at the bottom i'll type npm

run dev and it should take just a second

but the server will start up and we

expect to see that server running on

port message

inside the terminal window let me drag

this up and see what we get

there we go server running on port 3500

so now we'll go to chrome

and open up chrome let's open a new tab

and let's go to localhost and we've got

port 3500

and we get a very small hello world that

is simply delivered in text okay let's

minimize chrome

and let's

drag the terminal down so it doesn't

take up quite as much space but we'll

keep the

dev server running

but let's go ahead and serve our index

file that we have in the views folder

now we do have an index.html here

instead of just sending hello world we

can send a file and you do that with res

which is the response dot

send file now inside of send file

there's a couple of different ways we

can specify

the file to send in express one

is to put in

the path say dot slash views slash

index.html

and then we can provide options

and one option is to specify the root

directory and this is where we can use

that

dame value that is

native to node

and this will tell

node and express exactly where the root

directory name is and then inside the

root directory we would look inside of

views and there we would find the index

file so this should provide the file

let's go ahead and save

and it says it's restarting due to

changes once the server restarts will

bring

chrome back up and now that we've got it

let's reload

and now we've got our index page and i'm

going to resize chrome so we can

just see it and the console when we want

to at least when i pull chrome back up

if i can get it to drop down

not that we really need the whole thing

we don't have much content here

but we've got that so now i'll go ahead

and minimize and pull it back up again

when we need it so that is one way to do

it now let me copy this down

so we can just leave that in

commented

and the other way to serve a file is

what we're already used to doing in node

and that's why i usually do it this way

is we can use

path.join

and then

we specify the directory name

and then we join in the views folder

and then we go ahead and join in the

index.html and this will work in the

same way so let's go ahead and save this

now let's bring chrome back and we can

reload

and we should just get the same result

and we do we still have the index page

so that is more

how i would do it because i'm used to

using path.join but you could do this

either way okay in the file tree we can

see we also have new dash page.html so

let's just highlight all of this and i

press shift alt and the down arrow and i

can just copy all of it down and then

we'll remove the commented outline

and then we'll change our app.git route

here so instead of just looking for the

root we're looking for new dash page

dot html and upon that request of course

we want to switch this to new dash page

dot html as well

and save

now let's go ahead and look at chrome

and see what we get

if we type in our new dash page

dot html so we have slash new dash page

dot html

and we get the new page so that works

just fine so we can tell

that we're not just intercepting the

route right here because this is only

looking for the slash so even though

this has a slash this does make it past

and this is okay we get new dash page

dot html instead of stopping right here

because this does read this down like a

waterfall so it would check this route

first

but now we know it does make it to this

route however if you have the same

question in your mind that i would you'd

be thinking about what if somebody

requests this slash

index.html well this is where express

really helps us out because express also

accepts some regular expressions in the

routing so instead of just saying slash

here we can specify

and we can say this must

begin with the slash and this must

end with the slash

and then we can say

or

and then we can also say slash

index

dot html so if that request comes in it

will route also to the index.html

let's go ahead and save that and once

again look at chrome

and now let's switch back to our

slash without the index

and now if we go ahead and put slash

index.html

we still get the index and if you

remember when we built the node server

we also made it so you could just type

in index without the dot html let's see

what happens if we do that

oh we get cannot get index

so that means it could not find that

page and this is what express returns by

default if it's a 404 and cannot find

that and it's also worth mentioning

where we did a considerable amount of

code to handle things like the status

code and the content type in our nodejs

only web server here express

automatically sets the correct status

code and content type so for that 404 it

already set the 404 likewise for this

html and we're sending an html file it

already sets the correct content type

and of course it sends a 200 if it finds

it as a successful response

now we can add just a little bit more

regex

and that way we can make the dot html

optional

on this request

and if we put the dot html inside of

parentheses and put the question after

it that's exactly what it does so let's

go ahead and do that to our new page as

well

and so we'll put the dot html

and a question mark after it making the

dot html optional in the request

so we'll save both of those

let's come back to chrome

take another look and now index without

the dot html let's go ahead and reload

oh and the server is still restarting as

we see down here restarting due to

changes let's see if it's going to

restart it's taking just a little bit

may need to restart the server

altogether do control c to get out of

that and then i'll do npm run dev again

and we'll get that server running again

okay with the dev server once again

running i'm not sure why it hung up

there let's go ahead and refresh the

page and now we get our index page with

no dot html inside of the url something

else we handled in our node web server

that we created was a redirect so let's

do that with this express server now and

i will copy down the new page request

but now if we're requesting

an old dash page

with or without the dot html at the end

we want to redirect that to the new page

express makes this very simple so let's

go ahead

and remove a lot of what you see right

here

and we'll put in

res.redirect

and now we are sending that to the new

page but we do need to put a slash here

so we have our new page and we'll go

ahead and get rid of that parenthesis we

don't need now there is one thing

missing and what's missing here is the

response code now one will be sent by

express but it's going to send a 302

by default

and a 302 will not necessarily get the

search engine to change

saying it is a permanent redirect what

we really want is a 301 so we can do

that by specifying

the status code at the beginning of the

redirect and then putting a comma

afterwards

and that will go ahead and send the

correct status code that we need because

we would want the search engines to go

ahead and say hey this has been

permanently moved to new page there is

no more old page and we can go ahead and

check that in chrome as well i'll pull

that back up and inside of here we can

just type

old dash page we don't even need the

html

and it redirects to the new page now as

i mentioned express handles these routes

like a waterfall so at the very end of

the route you can essentially put your

default your catch all if you want to

and here once again we'll use just for a

get request

we'll put in the slash

and then an asterisk afterwards which is

the all

and that's kind of like if you're used

to writing sql a select all

so what we have here with regex is a

slash followed by anything will default

to this route let's go ahead and put in

our function as well so we have our

request

and response

and the arrow function and now inside of

here what we can do is essentially send

our file so i'm going to copy this line

and bring it down here and we do have a

custom 404 page and that's what this is

for because express will send a 404

status code and tell you it cannot find

what it's looking for even if you don't

supply anything but we want to supply a

custom 404

and so i'll go ahead and switch new page

to 404 here but what it won't do because

it will find the file to send is it will

not send the 404 status code it would be

a 200

because it could find the file and it

would be serving exactly what we told it

to so it wouldn't know to send a 404 at

this point so what we can do is chain in

the status code here with a status

404

and just another dot so that all changed

together so now we have a response with

a status code of 404 and we're sending

our custom 404 file let's save this and

go back and just request something that

doesn't exist so

up here instead of new page

i'll just put page

and we get our custom 404 what we

haven't talked about yet are route

handlers so i'll just put that here in a

comma

we have route handlers and that's

exactly what these are following our app

get route where we tell it what we are

routing these anonymous function

expressions that we have here following

the route are route handlers and we can

chain those or use more than one of

those so let me give you an example of

that so we'll have another app get and

let's say the request comes in for

hello.html

and let's go ahead and make that

optional as well since we're doing it

with the others so we have the dot html

is optional

and after the quote we put a comma and

now we have

our function expression here the

anonymous function and it's request

response but then we also add in a next

and this is an arrow function

inside this function i'm going to

console.log and just say

attempted

to load hello.html

and then after our console log or our

call to the console log

we call next and what that does is it

moves on to the next handler or the next

expression and you won't see this often

but you can put a comma

and then just put the next

function right afterwards so here we'll

have a request and response we could

have a next if we were going to chain

another one after this

but if this is the last one in the chain

it won't have a next it would just be

the request and response and here we can

response.send and we'll just go back to

our

hello world message that we had at the

very beginning

and if we save this we'll go ahead and

be able to see the console at the same

time let's pull up chrome

and over here we'll go ahead and request

the hello

and now we get hello world in our small

text in the browser

and we also got our console log message

attempted to load hello.html so you can

see

we're calling one function and then when

next is called

it goes on and calls the next function

in the chain now let me show you another

way that you might see functions chained

together and this way is

really the way you would probably see it

more often i'm just pasting in some very

very basic functions here so i've got

function one that has request response

and next and logs of the console 1 and

calls next function 2 same construction

logs of the console 2.

function 3 doesn't have a next it logs

the console 3 it also sends the response

finished

and then it is complete so how would we

use that in a route all three of those

so instead of the commas we saw chaining

the anonymous functions we can say

app.get and let's say this is for the

route let's just call it chain and we'll

go ahead and make the html optional as

well

and after that

you can provide

these handlers in an array so we'll just

have one two

and three

in this array so all the route handlers

are provided

right here in this simple line and we're

calling all of the functions that are

above so let's go ahead and save and go

to the route chain in the browser

i'll switch from hello up here at the

top

type in chain and you can see in the

console we got one two three and in the

browser we got finished in the small

text because it just sent the text

finished and these route handlers work

in a way that is very similar to what we

would call middleware and middleware is

what we'll be covering in the next

tutorial but you'll get used to seeing

this call to next so it can call the

middleware likewise we'll make a change

for our 404 as well because right now

we're just delivering a custom 404

for get requests

and that come in right here with this

path but we can go ahead and improve

that using middleware as well

and we'll also talk about how to serve

those static deliverables like our style

sheet the css any javascript that we

want to go to the browser and anything

else like images that we have currently

broken on the page when we go to new

page or some data so we'll talk about

how to provide all of those as we cover

middleware in the next tutorial

today we'll learn about middleware in

the expressjs framework we're going to

start out with the code repository from

the last tutorial but if you don't have

it you should be able to easily follow

along without it or you can download or

clone the starter source code from the

link i'm providing in the description

below so what is middleware it's really

anything between the request and the

response so the route handlers we

created in the last tutorial are really

middleware too and we can see one of

those right here that i'll highlight on

the page we've got a route handler for

the new page route so you could consider

this middleware and of course we covered

different things you can do with these

route handlers including chaining them

as we see right here i've got a route

handler a comma and then a second

handler or we chain them in an array by

creating three separate handlers here

and then putting them in an array in the

route right here so just a little bit of

a recap but those are overall considered

route handlers even though they are

essentially middleware so what about

creating some specific middle well where

there are three types of middleware

there's built-in middleware there's

custom middleware and there's middleware

from third parties of course the custom

middleware is what we create ourselves

so let's get started with the built-in

middleware i'm going to create some

space right underneath the port

definition and i'm going to paste in

some built-in middleware and the first

thing we should notice here is that is

app.use

and app.use is what we often use

to apply middleware to all routes that

are coming in and of course just like

our http methods get and of course we

could use post delete put and other

methods as well just like those methods

this all

works as a waterfall so if we put

app.use above our routes

then this will apply to all routes that

come in

and you can see in here we're calling

express dot url encoded and then this

receives an options

options object there i can say it

and extended is set to false and that's

usually how you see it you can look in

the documentation if you want to dive

deeper into that but that is typically

what you see so what is this middleware

for

well it's for handling url encoded data

in other words

form data so when that comes in in the

url

then you can pull the data out as a

parameter so we need to add this

middleware that is built into express in

order to get that data when form data is

submitted now i'll add an additional

layer of middleware

and this is for json as you might expect

so not form data but if json data is

submitted we need to be able to get

those parameters or that data out of the

submission and we use this middleware to

do it so once again app.use and then

express.json and now this is applied to

all routes as it comes in and finally

for the last piece of built-in

middleware that we'll apply today we're

going to serve static files and this is

important because if you remember from

the last tutorial we were not yet

applying css we had a broken image in

our new page and files that should be

available to the public were not

available and that's what this

middleware does it serves static files

so once again we start with app use

and then it's express dot static and we

supply the path and here i'm using path

join as we have many times before we

supply the directory name value

and then

the public folder is what we're going to

put all of those in so when we save this

we now need to create a public folder

and inside this public folder we need to

drag our css folder and we need to drag

our image folder

and let's go ahead and create one more

folder in here and let's call this text

and then from our data folder let's pull

down the data dot text and put it inside

the text folder so now we have some

files that we want readily available for

the public and express will

automatically

route those files there because this is

applied before our other routes so it

will search the public directory for the

requests before it moves to these other

routes let's go ahead and open a

terminal window from the terminal menu

you can choose new terminal or like me

control and

the backtick and it opens up the

terminal here i've got a bash window and

that should work just fine i'm going to

type npm run dev to start nodemon for

our development server and this should

launch everything and yes we're already

running on port 3500. let's go to chrome

and i've got a blank window open in

chrome so we can type localhost 3500 was

already there and we get index and it's

already applying the css so now let's go

ahead and comment out

the middleware

so we're not using those static files

and let's reload our index page

and see what we get now there's no css

applied so it is absolutely finding

those public files and applying them

however we didn't really change the path

in those files and we should now i'll

reload this and we do see it's applied

but let's take a look at those files

here's our index and we were going up

out of the views directory

and then into the css directory and

that's not really there so this is being

a little forgiving let's just get rid of

that because we know this path is

available to the public of course after

the directory name there so after the

root of the url it should just be css

style

dot css and we can double check that by

going to chrome

and from there we can just type slash

css

style dot css sure enough we pull up our

css file in the browser so it is

available to the public let's go ahead

and make these same changes

on our new page dot html we can get rid

of the dot dot slash for image for the

image directory and for the css

directory and save that and also in our

custom 404

we can get rid of the dot dot slash and

save now all of those should be working

fine and they really were before but

this cleans it up now let's go back to

the server js and let's consider adding

some custom middleware that we write

ourselves let's create a custom logger

and we want it before anything else

because it we could put it i guess after

the static files are served but then we

would not log the request for the css or

the images or anything like that so if

we put it at the very top

then we'll see the requests for

everything as they come through so we'll

just call this custom

middleware

logger and now we'll start with app.use

and inside of app.use we'll put an

anonymous function that gets a request

response and since we're creating this

it needs to have next so we can move on

notice the built-in middleware did not

need next call it's already built into

that but we need to call next inside of

our custom middleware so let's log to

the console inside this logger

and we'll go ahead and log the request

method where here's the request dot

method

and then give a space and we'll log the

request dot path as well

and now with both of those sent to the

log the only other thing we need to do

is called next so let's save this

and now let's go back to chrome

and we can still see our console here

let's request the page

and you can see we get the get request

here and there's the slash which is the

home page and we also see the request

for the css file while logging to the

console is okay for our middleware

logger what we really would like to do

is create a log file and we've already

created a log events function

back when we were working just with node

so we can go ahead and use this log

events function

in our logger as well let's create a new

folder in the file tree and call this

folder middleware

from here let's pull the log events

dot js file straight into that directory

and now that we have log events there we

really don't need to change much and we

are already exporting log events as well

so that's good what we will need to

change is where it writes the logs

because we don't want it to create a

logs folder in the middleware folder so

if our with our path dot join

what we need to do

is add in one extra spot here i did not

mean to hit return there we go and

just go one directory up with the two

dots

and now that we've got that i'll copy it

and we need to add it to this path

and this path as well so when the logs

directory is created

it is here where we already have our

logs directory from the past rather than

being created in the middleware

directory and now we need to take log

events

and import it into our server so we'll

scroll to the top and let's just put it

underneath path

and we'll say const log events

equals require

dot slash

middleware slash

log events

and that completes that we can save

and now we can use log events

inside of our custom middleware logger

let's put it right above the console log

and we have log events and log events

accepts two parameters the first is the

message and the next is the file that it

should write to or create

so inside for the message we'll create a

template literal and i'm just going to

paste this in so you can see the full

message it is the request method and

then we put a slash t for tab so we have

a tab delimited log file and then it's

the request.headers.org

which should be saying where the request

is coming from what website sent it to

us

and then

we should get what url was requested so

say it's a get method and the request is

coming from google.com and they are

requesting our index page after that we

need to tell it what file to create or

write to

and we'll call this rec for

request.log.txt

and now we should be good to go with our

log events function let's go back to

chrome one more time

and let's go ahead and request our index

page

it was requested we see the requests

here and now we also

see a request log has been created and

there are two requests

it was a get request both times and it

was undefined because we're just running

our node server right here on our local

host

and you can see what was requested as

well the slash for index and the css

style.css

and while this works once again let's

look at the server.js

while this works we're really importing

a function to use inside of our

anonymous function that is our logger

that has the request response and next

as any middleware should so we can clean

this up a little bit let me go ahead and

copy the anonymous function and

everything inside of it

ctrl c to do that and now we'll go back

to the log events.js file and here we

can define

another function just called logger

we'll set that equal to this anonymous

function and now logger can be our

custom middleware that we export so down

here instead of just exporting log

events which we'll use later or we

wouldn't need to right now at all

i'll go ahead and put both inside of

curly braces once again we won't be

using log events anymore inside of the

server js though i'm just exporting this

for use later when the need arises so

back at the server js instead of log

events we'll need curly braces now that

there's two functions being exported

and we'll import logger from the log

events file and now with logger being

imported and all of this logic inside of

logger we can just say app use

logger

and now this is much cleaner and should

still work in the same way so let's pull

up chrome once again

and let's request the index

and we see the console logs still work

let's look at the request log

and yes we have two more requests in the

request log once again notice that it

says undefined here is the origin

because we're just using our local host

server here as we pull this up so let's

make a request from another domain i'll

pull chrome back up

and now

a new tab and we'll go to google

and on google let me go ahead and expand

this and open up the dev tools with

control shift i now that i have dev

tools open

what i want to do

is just call fetch and i'm not really

interested in the data we're just going

to fetch the destination and let's see

what we get

we get a course error it says no access

control allow origin but let's go ahead

and check our log file

and

our log file does show google.com as the

request origin so you may have seen that

error we got before from google that

showed the cores error and that stands

for cross origin resource sharing and

now this will lead us to third party

middleware so we can install a

dependency i pressed control c to stop

our dev server i'm going to type npm i

for install

and then cores cors and this should take

just a second to install and we'll be

able to see the new dependency in our

package json when this is finished

and it says it's finished already let's

check the package json and here we see

cores now added as a dependency so let's

go back to the server.js file

okay so we're in the server.js file here

and we need to go ahead and import

cores so we define

cores and set it equal to

require

cores

once we have that we need to apply the

middleware so we want it to come as soon

as possible but after the logger so

let's go ahead and apply cores here so

we'll say app.use

and then we can just call cores inside

of the app.use i'll go ahead and put a

note here that core stands for

cross

origin

resource

sharing

let's save that and now go back and

start our dev server again with npm

run dev and once the dev server has

started we'll pull up google it says

it's good to go it looks like

and let's go back to google and let's

make the same request

and now there's no cores error we get a

promise pending of course from fetch as

we expect you there but there's no error

and that's the main thing is we can

request data now from the google.com

domain and it doesn't create a course

error let's minimize chrome

and let's look at our request log again

and we once again see google in there so

the domain the request origin did come

from google.com okay now let's go a

little deeper into course i don't want

to make this a full tutorial on cores

because that can get pretty deep however

cores for cross origin resource sharing

is something that does need to be

applied or you will get those errors

however this just leaves it open if you

had an open to the public api

this would be fine you're using cores

and everyone can use it but for many

applications that's not really what you

want so let's create a white list and

we'll define it with const

white list

and inside of that we can have more than

one domain

so let's say https

slash and then www dot your site

whatever your dot com is whatever

application web application domain will

that will access this back end node

server that's where you want to put this

domain here but say you might also have

a variation maybe you've got a variation

without the www dot or

maybe you're working on a local dev

server and you launch from go live down

here click to run live server live

server always runs on http

colon slash

127.0.0.1 which is your computer and

then it gets a port like 5500 i believe

is the default so

maybe as you're building a react app

you're running your react app on this

port or a different port on your local

host or you've used the ip address which

127.0.0.1 is the same as having

localhost there anything like that so

let's add those to the whitelist and of

course we should add

http slash

local host and we're using 3500 here

today now you would take these out after

development but of course you would

leave in whatever domains should be able

to

access your data or your back-end server

and that would be your web application

say your react application is at

whatever domain you would leave that in

here so we've created a list that is

allowed to access the back end that

cores will not prevent so now we need to

create the function that will allow

cores to do this and this is all

contained within the cores options so

that's what we'll call this lowercase

cores and then camelcase here with a

capital o for options and we set this

equal to

an options object and the first property

is origin and origin can accept a

function so we have an anonymous

function here

and it gets the origin which is not the

same as the origin right here

necessarily this is the origin

coming from whoever requested it say

google.com

and then a callback function

and again the two origins a little

confusing but it's right from the

documentation so that's kind of how we

need to do it so we've got the origin

there with the anonymous function and we

can say if

the white list

dot index of

and then we pass in the origin that is

passed in to the function

if that index is not equal to

-1 in other words

if the domain is in the white list

then we're going to go ahead and let it

pass

and then we can do the callback

and the first parameter in the callback

is null which is usually the error so

there's no error and then we set the

second one to true and that just means

that the origin will be sent back saying

yes that's the same origin and it is

allowed and then we can have an else

and in the callback here

we have an error instead of null and we

create a new error and we can just say

not

allowed by

cores

and so that is the message to go along

with the error now that is the first

property here

in the course options we need to add one

more so we put a comma and then we put

lowercase here options

success

status there it is and we send a 200.

and with that we can save

and now that we've created the course

options we need to pass those

in right here and notice we did not

include google in these course options

now google could access without an error

before we put in the options let's go

back and make the same request from

google and see what happens now

we once again have a course error so

let's go back

and let's go ahead and change your site

to

google.com

server is restarting it looks like it's

hanging up nope it's going to go ahead

and do it there we got it

and we go back to google once again and

now it's in the white list

and we fetch and there is no error so we

know our function is working as we

expect it to so when we come back and

look once again you can change this to

your domain whatever your project

wherever it will be hosted say you've

created it in react or view or even

vanilla javascript spelt even whatever

you might create a front end project

with that will access this back end you

want to put that domain in here or maybe

variations of again remember you might

not have the www or it might be optional

anything like that so that allows you to

put in domains that can access the

routes and otherwise cores will prevent

them so very useful third-party

middleware i want to go back to chrome

one more time and create that error one

more time now that we've taken google

out of the white list

at least i thought we took google out of

the white list maybe i didn't save after

we did that that's exactly what happened

i hadn't saved the server js file yet

save here

nodemon is restarting

it's taking it just a little bit

maybe i need to go ahead and restart it

once again every now and then i have to

restart it manually so npm run dev

get the nodemon server up and running

i'll pull up chrome

and let's see if we can get that error

again

so yes we've got the cores error here

now let's look back in

visual studio code as well

and you can see we got the server's

still running but we got this big error

and up here it says our message error

not allowed by cores

and this huge error here now we can

handle errors in express as well but

express is already handling them it has

the built-in error handler by default

and that's what's happening when we

throw this error it is going there

however let's go ahead and add a little

custom error handling

so we scroll down to the very end

remember it's a full chain so we want

this after everything else even after

our 404 here i'm going to paste this in

and you can see i'm using app use once

again and then this is an anonymous

function

and it doesn't just get the request

response and next it also receives an

error parameter

and then we can log to the console the

error stack if we want to or just the

message or whatever we can go ahead and

send a status 500 server error and we

can send the message to be displayed in

the browser so i'm going to save this

and we'll go back to chrome but we won't

use google anymore let's go ahead and

just use the page that we have here and

i'll see if i can resize there we go i'm

going to reload

and look we got a not allowed by cores

even though we requested our index page

but our custom error did work and it

sent this to the browser now why did we

get that well let's go ahead and look at

the log here's our request log

you can see it's once again undefined

so undefined is a problem because that's

not in the white list so during

development you want to go ahead and

make one modification to this function

right here after the minus one go ahead

and put in the or operator and then

say no origin essentially the

exclamation mark

origin which would be the equivalent of

undefined or false

and we save that and now it should work

now after development we probably want

to remove that as well just like we want

to remove

some of the

development urls that we have up here in

the white list so now let's go back to

chrome

and see if we can reload our index page

yes and now everything is working as we

expect it to and we can also tidy up

that custom error handler so let's

scroll back down to it

and we see the function that we have

here inside of app use i'm just going to

copy that complete function

and now inside the middleware folder

let's create a new file and let's call

this error handler with a capital h

there so camelcase

errorhandlerjs and now let's define our

error handler

and set it equal to

and we'll remove

the function keyword and we'll go ahead

and put an arrow after this

and we've defined our error handler but

what we want to do that we're not doing

yet is also create an error log and this

is where exporting the log events

function that we left here

comes in very handy so now we need to

import that here not the logger but the

log events so let's define

log events inside of the curly braces

set that equal to require

dot slash

log events

and now that we're importing log events

we can go ahead and use that in the

function as well so we'll call log

events right here before we log to the

console and once again this function

gets a message first and then the name

of the file that it needs to write to or

create so this will be a template

literal and i'm just going to paste in

the values once again here instead of

anything from the request such as the

method like we were logging before we're

going to log the error name

and the error message and then we'll put

a comma and go ahead and specify error

log dot txt as to where we want to write

the error to and we can save this but

we're not quite finished yet because we

need to export this function so we do

module dot exports

set this equal to

error handler

and now save and now we need to import

error handler into our server so let's

scroll to the top of our server js and

right underneath logger i'm just going

to go ahead and copy this down

and let's change this

to

error

handler

and instead of log events we're

importing from middleware

error handler

and save

now we need to use the error handler

where we previously had the larger

function in this file so it will be much

cleaner so let's go ahead and select

this full function

delete that and paste in

error handler

and we can save

and we got an error the app crashed

let's see what we've got so if i scroll

up

it says app.use requires a middleware

function so something about the function

probably didn't get imported correctly

let's go ahead and scroll up to the top

and look at our import statement and oh

yeah we were using curly braces around

logger because it was one of two

functions from the file but from the

error handler it's the only one so let's

go ahead and remove those curly braces

around error handler and see how

everything goes it's restarting the

server right now and server running on

port 3500 that part looks good so with

the server running the best way i know

to create an error would be to go ahead

and remove this or

no origin for now

and we'll go ahead and save and then

we'll try to reload

the index page once again in chrome so

it's starting the node.js server

and now that it's running let's reload

and we've got a not allowed by cores as

we expected an error in the console

and now we have an error log file over

here in the file tree and we can see we

got our error not allowed by cores

at

1827

so let's go ahead and look at the

request log and we should be able to

line that up with what request happened

here as well and we can't so everything

there is working as expected so now that

the error is logging let's go ahead and

put that or

no origin statement back in for now so

we do not keep getting rejected by cores

we can go back

and we can once again request the index

page

and everything should work well when the

server restarts there we go we've got

the index page now okay there's one more

thing to do before we're finished today

and that is to compare app use

to app dot all and that's what we're

going to do right here as we change up

the 404 just a little bit so with app

use

we could do something like this

app use and specify

here at the end of the chain everything

basically that came in

from the slash which would be the root

but app used does not accept regex and

also app use overall

is more likely to be used for middleware

but app.all

is used for routing and this means it

will apply to all http methods so it

also does accept regex so what we can do

inside of this is just put an asterisk

it's at the very end of the page

so we can just say pretty much anything

that made it here

should

get the 404 at this point let's go ahead

and save the file and test it out i'll

pull up chrome

and here

we can put in the

slash dave

and yes there's no page that's dave html

so that is a 404 although the request

did log just fine we can customize our

404 response just a little more so let's

start that out by just setting the

response status because we know it's

going to be a 404 no matter what

after that let's check the type so we

can say if

the request

accepts

and now we'll look at the type the

content type and we can just say html

here and express will translate that for

us and after that

then we'll put what happens because if

this will resolve till true or false

here so

then

we can go ahead and look at sending a

file or something else inside of here so

what we'll do is say

response

dot send file and go ahead and send that

404 now this is very much like what we

were already doing but now we can check

for other types as well that might be

accepted so let's go ahead

i'll just copy all of this down and

we'll change some of it so shift alt and

the down arrow copies everything

and now we'll say if the request accepts

json well then we don't want to send a

file at all so this will be entirely

different

let's get rid of all of this

and say response.json

and we can put some json here inside of

our response and let's just say error

and over here

we can say 404

not page let's just say

not found which is essentially what a

404 is and really what we're doing is

creating a small waterfall effect here

with the if so we could make it another

else

if here and then finally

an else for our last

possible outcome

once i can spell else and here we'll

just respond and we can set the type

to text

just txt for the type actually and then

we can

send and inside the send we'll just put

the same text that we have up here

404

not found so i'll paste that in and that

should work as well so now i'll go ahead

and remove these blank lines and we will

test out our 404 once again

i'll go to chrome

and i've already got

slash dave in the url so i'll just see

if i can reload this 404 once the server

restarts

and now it's restarted i'll hit reload

and we got the 404 and it is html

now i would have to use postman or

something else to ex try out the json

file or possibly text as well we would

change the headers for that and i'm just

going to let you trust me that that will

work for now instead of breaking out

postman or anything to just try out

those two other routes but overall that

is what you can do to customize a 404

with app all and i hope you understand

at least a little bit of the difference

between app.use which is for

middleware and does not accept regex and

app.all which is more for routing and it

will apply to all http methods at once

today we're going to talk about creating

routers in the express js framework and

we're going to start out with the code

repository from the last tutorial but if

you don't have it you should be able to

easily follow along or you can download

or clone the starter source code from

the link i'm providing in the

description below alright in visual

studio code we've got our server.js file

and from the previous tutorial we've got

a lot of code in here and really what we

can do is break these routes out into

individual routers that are essentially

mini servers for each specific route or

many apps as we create our app with

express here these will be mini apps and

we'll for refer to them as routers so

over in the file tree let's create a new

directory and let's call this directory

routes

and now inside the routes we can create

routers for each route that we are

handling so let's create a new file here

and let's call this

subdur.js because

we have a subdir directory in our views

folder that we haven't handled at all

yet

now in the subdir dot js we need to

start out with a few requirements once

again and the first would be express

just like we did in the regular app or

server.js if you will so we have require

express

and then after that just like we have

before

we have applied express however now

we'll define a router instead of an app

and we'll set this equal to express dot

router with a capital r

and then we're going to go ahead and

need the path module as well from

common core module in node.js

so we'll require path

after that

let's just go ahead and put our module

dot

exports and set that equal to router

because that's what we'll always do when

we create a router and then we can

import that back in the server.js when

we need it now we're ready to just pull

our routes in so let's look at the

server.js

and the routes that we had or did not

have at this point for the subdirectory

and i don't believe we had any yet we

were just routing to our specific views

for index and the new page and of course

we were redirecting the old page so we

hadn't handled anything for the

subdirectory yet it has its own index

and it has a file called test html so

i'm going to copy how we handled the

index for the root

and then we can just modify that in the

subdirectory

and instead of app.get we now have a

router so let's replace app

with router and now it's router.git and

then we can handle this slash or index

for the subdirectory the same way we did

for our root and we have a request and

response and we can get remove this

commented line that we had in there

before

and then we are sending a file and we're

sending the root directory we get the

directory name here

and then we want to have views but now

we have to think about this because

we are not

inside the root so we can't just look

directly into the views directory so we

need to come up out of the routes

directory we created and then into the

views directory and then

we're not only just looking for the

index because that would be the root

index now we need to specify

the subdirectory that we have

and then the index.html that's within

that subdirectory file

after that let's copy this down and i

can press shift alt and the down arrow

i'm using windows it may be different if

you're on mac or linux

and now we have another git route but

this will be for

the test dot html and so we can replace

index with test and remove the initial

slash we'll leave the html optional this

is regex that we can use within the

route

and now we're sending a file once again

but instead of sending index we're

sending

test not text dot html and we can save

that now that we've created the router

file for the subdirectory we need to go

back to server.js

and

underneath where we serve the static

files and we set that

we need to go ahead and provide a route

and we do that with app.use

in the server file and now let's provide

the route

that we are providing the router for

and then we can go ahead and require the

router that we have created and now this

will be in dot slash

routes slash

and there's the sub directory and after

we provide that we should be finished

and now this will route

any request coming for the subdirectory

to the router instead of the routes that

we are providing below through app.git

such as index and new page so this will

match in front of these and of course we

can put all of these in a router and we

will next but let's go ahead and start

the

dev server i'm going to press control on

the backtick but you can go to the

terminal menu and open a new terminal

window

and if you remember we type npm

run

dev and this will start our local dev

server with nodemon which will listen

for any changes and it's on port 3500 so

let's go to chrome

and i'll go to my blank page i'll type

local host

port 3500

and there we've got our index file and

that's fine but we want to go to the sub

directory and see if this is working so

we've got sub

dur

and yes we've got our subdirectory index

page and let's go ahead and see if the

test index page in the subdirectory is

also working i said index test.html

actually and there's our test page in

the subdirectory as well okay now let's

ask for a page that does not exist

in this sub directory and let's see what

we get

well we've got our 404 page but there's

something important to notice here in

the past when we've got our 404 page it

had css

supplied for it now we didn't put css

on the previous subdirectory pages that

was not included anyway but if we

requested a 404

on any other page that was not in the

subdirectory

it does have css applied so why is the

css

not working for our subdirectory well

it's because we haven't told express to

use

the public folder or public directory if

you will for the subdirectory so let's

copy this line down with shift alt and

the down arrow once again and now we can

specify the subdirectory here

and tell express to use that public

directory before we didn't supply a

directory but the default is the slash

anyway and so that's essentially what we

were doing but we can save these

and now we should be able to go back and

request our 404 basically any page that

doesn't exist in the subdirectory

and probably get the formatted 404 yes

now even though we're in the

subdirectory and i requested a page

named dave that doesn't exist

we got a 404 that actually has the css

supplied you can even see the request

coming through down here for the css in

the sub directory and it now works now

i'd like to make one quick correction

from the last tutorial that i did

provide information that was correct in

older versions however in newer versions

of express express does support regex

inside of app.use and i said it didn't

when i compared app.use to app.all but

now you can have regex there and so if

we are to require a router

and we put a slash with an asterisk here

this would supersede the subdirectory

router in other words all

routes would go to this router if we

supplied that of course we don't want to

do that so we want to specifically state

just the slash or we could even get more

specific and we could say hey it must

start with the slash

and it must

end with the slash

and then of course we would only be

providing that for the slash right here

but

that is because it supports regex and in

previous older versions express did not

support regex inside of app.use but in

the route it now does let's go ahead and

create a router for this

root directory here so let's say dot

slash

routes slash

root

and now add the

semicolon one more over

and save and now we need to go ahead and

create this route because right now it

doesn't exist

so let's go over here to the file tree

i'll collapse the views folder we don't

need to see what's open there but inside

of routes let's go ahead and create this

root

dot js

and now inside of the js file

let's go back to server and grab the

routes that we were using

for the root and we have our index page

our new page

and a redirect for an old page and

control x will cut those out and we can

paste those

inside of the root but we also need

those imports and basically

everything you would normally start out

with

for a router these three imports at the

top

express router and path

so we'll put those at the top of root as

well

and then at the bottom

once again you want to have module dot

exports and set that equal to

the router now what haven't we changed

yet is the keyword app here that we were

using in the server.js we need to switch

to router as well

we can once again get rid of this

commented file

and we have to once again consider the

route that we're providing because now

we're in the routes folder so yes we

have the directory name value but then

we need to come up out of

the routes folder

and then look in the views folder now

this will be correct now we're not

looking in a subdirectory so we no

longer have to provide it there let's go

ahead and copy this

and paste it into the route for the new

page as well however the route for the

old page is a redirect and this will be

okay to leave it as it is so let's save

the root

and let's go back to the server we can

also get rid of some of these examples

of route handlers that we had such as

the hello right here and the chaining

the route handlers that i had previously

provided for the chain route let's just

delete all of that to clean it up a

little bit

and save our server.js

it's now restarted so let's see if these

routes are now working with the new

router

and we'll come back and just go to the

root

and yes we got the root page

let's go to slash new dash page

html should be optional and there's our

new page and our image is working which

means we're getting our static file

routed correctly to the public directory

where the image is stored and now let's

go to old page and see if the redirect

still works

and yes we redirected back to the new

page let's go ahead and type in index

instead of just the slash and yes we

still get the index page everything in

the new router for the root is working

correctly with our routes working

correctly

let's talk about how we would set up an

api or a rest api if you will

and that's what is more important when

we're working with say the mern stack as

say

express node and of course react

on the front end or you could substitute

any database technology for but

we've got node and express here

and we want to organize

a api which is what we would more than

likely create with node and express say

compared to

a static server for web pages although

you can do that

it's much more likely that you'll create

an api and that's what we'll focus on

here so

underneath these routes we're going to

create one more route

and this will be

to

employees

and then inside of routes it's going to

be in a subfolder named api

and then the employees and notice this

will just be routed by the user going to

employees they will not have to type api

so let's go ahead and save this and then

let's start creating that route inside

of routes we want to create another

directory

and that's api

and then inside of the api

we want to create our employees router

and that's

employees.js now up here inside the data

folder we've already got a file named

data.json let's go ahead and rename this

file

and let's call it

employees.json

and let's give each employee inside of

this file an id

and we'll just make these chronological

so we've got one

and an id of

two

and now that we got that we can just go

ahead and save our small employees data

file and remember that's employees.json

inside the data folder

and we've created the route here inside

of server using app use now it does not

need to have any static files as we'll

just be delivering json data from our

api so we wouldn't typically have any

static files like we would with a web

page so now let's go back to our

employees.js

route let's start out our route just

like we did the others so we want to

define express we'll set this equal to

requiring express

and then we want to go ahead and define

our router once again and we'll set this

equal to express dot router with a

capital r and call router into action

and we'll once again need the path

common core module from node.js so we

can require

path

and after path let's go ahead and define

an empty object named data

and from there let's set data dot

employees

equal to

require and now let's get that json file

so we need to go up out of the api

folder and then we need to go up out of

the routes folder

then into the data folder and then to

get employees.json

and so this is kind of like connecting

to a database this is just what we're

doing for this tutorial and and dev of

course in the future

we'll work on connecting to

and of course you could replace that

with your database technology of choice

but once again just for this tutorial

just for dev we're just going to import

some json to simply work with here so

now let's go ahead and create our

module.exports

and set that equal to router again as we

always do with a router

and now we can set up our routes now

instead of just saying

router.git and creating

anotherrouter.post

and another router dot put

and of course putting those paths in

there like we could

one thing we can do is say router dot

route

and then provide the route and then we

can chain the different http

methods that we want to provide for this

same route as a get request and a post

request can both go to the same route

but there can be a different result for

each so let's handle the get request

first and here's a request and a

response

and now inside the handler of the get

request

let's just return json and let's return

all the employees so that will be

data.employees

now for the post request

we can just come down here and say

dot post and once again

we can have a request

and a response

we can handle this completely

differently for the http method post

than we do for git

and now with the post we'll get

parameters coming in

to the request and we can refer to those

parameters with request dot body and

then dot whatever the name of the

parameter is

and we had a first name and a last name

and a post request would be posting a

new employee

so what we want to do i'm not going to

put in the full code that we would have

in an api at this moment because it's

not really about coding an api right now

we're handling routes so we just want to

see how each one of these would work

so let's say the first name that we

return in the json will return what is

sent and that's request dot body dot

first name

and then let's go ahead

and return the last name as well

that's request dot body dot last name

once again not writing out all the code

for an api at this point just showing

how we can get

the parameters from a post request and

then we're just sending those parameters

back but this is how we could handle

each route in an api

now let's go ahead and do the same thing

with a put request

i have a request and a response and this

would be

the http method that you would use when

you're updating an employee for example

but we could do the same thing we could

get the

res.json here and as a matter of fact i

can just copy this down

and of course the code would be

different if you were writing an actual

api because you would be updating at

that point and we'll do that in the near

future just not going to do it yet and

then let's get a delete now a delete

would be different we wouldn't be

getting the first name and the last name

we would be getting the id

so we'll just send the id back in this

case

and that would be response.json once

again

let's go ahead and send the id back here

and this would be

request.body

dot id

now you can see we've chained each http

method together and we've got git post

put

and delete all coming into the same

route on our router they're just

different request methods and of course

this being the last one we'll go ahead

and stop

right there and i'm going to save this

but we're going to add one more route we

have the route coming in with just the

slash just the root but then also

we could have

router

dot route

and then a slash but we could have a

parameter directly in the url and that's

what we're showing here is a parameter

and this would be

a get request that has a parameter

inside of the url so now down here and

of course you could do that with other

requests too we're going to use a get

request so let's go ahead and put

the handler for our get request here we

have our request and response

and now inside the handler will once

again respond with json

and we'll just say

here's the id

requested and now this is different

instead of request.body it's

request.params.id

and that's because we're pulling the

parameter

it's a named parameter actually and

we're pulling it directly out of the url

so here we're responding once again with

just what we received just as an example

now i'll put in p future code will go

ahead and actually code out an api right

now handling the routes and so all of

this is inside the router and i guess we

didn't need path right here at this

moment so we can get rid of that but all

of this is inside the router for

employees let's go ahead and save this

and we can test it out and our server is

still running below so we can now check

these routes with thunderclient

thunderclient is an extension

in the past i've used postman which is a

separate program to test apis let's go

ahead and try this extension out you can

find it under extension search for

thunder client

and it allows you to save different

routes you want to test

so right here i'm going to go ahead and

choose the

get route that i created first there it

is for all employees which of course

there's only two and you can see

here is our http method and here is the

route and now i'll click send

and here's the response i can just make

the response full screen but we've got

both of our employees returned

and that's exactly what we expected so

now after testing the get route let's go

ahead and test the post route so i'll

choose that from our list well let me go

to collections i believe i saved

everything there there we go

let's choose post

and now we're once again going to the

employees route but it's got post

let's look at the parameters and see if

those were saved

and

it should be under body actually there

we go and i'm posting a new employee

named john doe

so let's see if we get that in return

we'll send that and let's look at what

was returned yes we got john doe

sent back to us and that's all we're

going for today once again as we're not

writing out the actual code to add the

employee or update the employee and

things like that in the near future yes

i will okay

put should be the next one to test so

now it's a put method at the same url

and once again we are sending some john

doe oh actually sending just the id

and the first name of what we wanted to

update and of course i think i had the

put request just sending back the first

name and last name so maybe we'll just

get the first name back let's see what

we get when we test

put

and

yes we just got the first name back and

that's what i expected so that works

also

now let's test the delete route of

course it won't actually

delete the employee this time around

and looks like we're sending just the id

and we should get that id back

expand and yes in return we've got the

id back so that route is also working

now there's one more git route where we

could get a specific employee

and let's see if that one's here or here

here we go so

this is our route with employees but

then it has slash and the number one

where we're requesting

just one employee not both so let's go

ahead and send that and see what we get

in return and we returned the id of one

so that route is also working and again

this extension is called thunder client

if you want to check it out for testing

the routes in your api now as a

challenge before my next tutorial you

could go ahead and write out the code to

update the

json that we were receiving and of

course just hold it in memory don't

really update the file but you could

test out what you want to do here for

each of these routes and you could

handle each one of those and i'll come

back with some code for that in the next

tutorial and what i really also want to

talk about in the next tutorial is

organizing the rest of this api

including the server file

and setting it up because after that

we'll pretty much be ready to connect

everything to whichever database

technology we would want to so we'll

organize this with an mvc pattern that

is model view controller and of course i

can come back and add some extra code

here to handle the api data just for the

json as an extra test it's not really

anything to do with specifically express

that's just javascript in handling how

you would

basically do crud operations create read

update and delete

today we will organize our node.js and

express api server with the model view

controller design pattern you may have

also heard this design pattern referred

to as mvc that said remember express is

by definition an unopinionated framework

and you can organize your project

however you would like i'm just

demonstrating mbc because it's a popular

pattern we're going to start with the

code repository from the last tutorial

but if you don't have it you should be

able to easily follow along without it

or you can download or clone the starter

source code from the link i'm providing

in the description below okay we're

right here in visual studio code and

we've got our server.js file and we want

to use the correct terminology so we

were keeping our data inside of a data

folder and you can see i've renamed it

to model it still has the

employees.json file in there and we're

just emulating a database here with a

employees.json file instead of

connecting to one at this point because

you might have my sequel or in

mind or whatever later on in the series

i plan to show however right now

we're just going to simulate that

connection to a database

and now besides that we have a views

folder and really with a restful api we

won't have many views if hardly one

maybe we would have a welcome page that

gives some directions about the api but

that's about it we're not really serving

a bunch of static pages or resources

what we will have though is a controller

folder so let's go ahead and create that

when i said controller and really i

should make this plural because it could

host more than one so let's go ahead and

call this controllers and it will hold

controller files so inside of here let's

go ahead and create an employees

controller

dot js file now currently we have all of

our logic really inside of our routes so

if we open up routes and the api

directory and then look at employees js

our logic is essentially the route

handlers so

for router dot route and then we come to

the get http method we've got this

handler that returns all of the

employees so what we would want to do

would be remove that logic from here and

take it to the controller so we could

name this something like

get all employees

and then we can just assign

that route handler as a function so now

we have a get all employees function

that is part of the controller so let's

save that but what we also need here is

the data so the data that we were

pulling in to the employees js route

inside the api

is actually will need to be inside of

the controller at this point instead of

the route we're breaking that out

and so we'll put that at the top of this

file as well so these functions can work

with that data so i'll save this again

and now back inside of employees let's

pull out the logic from the post

and here we go with that logic and now

we'll call this

function a different name we've got

create new

employee

and we'll set it equal to that action

and then the next function will go ahead

and name as well and that will be update

employee

we'll set it equal to what we find here

in the put

portion of this route

and now we'll come back and assign that

to update employee

and finally as you might guess we'll

have

delete employee

and we'll set that equal to the handler

for delete

not copy but cut there we go

and we can paste that in here as well

now i'll go ahead and save that now

we're not finished with the controller

by any means but we have the

first actions in here for these routes

and we haven't put anything back in here

yet but we will but there's one more

function to create here and this would

be called just git employee instead of

get all employees so let's go ahead and

get this

action as well

or route handlers what we could refer to

those as still

and let's say git

employee

and now we have all of these different

functions defined inside of our

employees controller

and of course we're pulling in the data

here at the top but as you might expect

we need to export these as well so we'll

have module dot exports

let's set this equal to an object now

and so we had get

all employees

and then we had

create new employee

and we had update employee

and

delete employee and then we had get

employee and so we're exporting all of

these functions now let's go back to the

employees js

routes and let's import our controller

so let's call this

employees

controller and we'll set it equal to

require and then we have to consider

where we are so we go up a folder

and then up another folder and once

we're there now we can select the

controllers folder and inside there we

find our employees controller now we

could deconstruct those functions here

as we import those in but i think i'll

leave the name employees controller

because we're emphasizing creating a

controller here and then we'll just put

in the functions and in visual studio

code i believe if i start typing the

functions

it's going to import the part that says

employees controller for me sure enough

it does so now we can have create new

employee and select that

and here we're going to have

update employee

and finally we should have

delete employee not this delete we

didn't quite get that right

delete

employee there it is and so all of these

actions are coming from the controller

or route handlers we could say and this

still doesn't look right we didn't get

we've got a d in front of there

employees controller dot

delete employee that's what we should

have and now here we should have git

employee

with the employees controller so this

definitely cleaned up our route file

here quite a bit and we've separated the

logic into our controller and that's

really what the model view controller

pattern is all about and so we could do

that with other routes if we had other

routes as well but now we've really

cleaned up our whole project let's go

back and do just a little more cleanup

in the server.js and we can get rid of

some of these views that we're no longer

going to use one other thing i'd like to

do is you see we're pulling some things

into the server file right at the

beginning and we're starting to use the

logger right away but we're taking up a

lot of space here with cores and we

don't have any kind of configuration

folder over here in the file tree yet so

let's go ahead and create a

config folder not js just config folder

and now we can go ahead and create a

course options

dot js file right there

and back in the server let's go ahead

and take our white list and cores

options

and cut those out of here

and paste them into our cores options js

here and i'm going to put each one of

the urls on its own line

just so it's easier to read

and after we define the white list at

the top we have our cores options

and as you might guess we need to do

module dot

exports

set this equal to cores

options

and now we'll need to import this back

inside of the server

so at the top of the server here we

could just put it right under cores

and we'll say

const cores

options and set this equal to

require dot slash

dot slash there we go config

and now inside of the config folder we

have our course options

we can save that let's see if there's

anything else we can clean up i've got

some extra comments in here of course

this being a tutorial that kind of makes

sense

let's make them a little bit smaller

let's put form data besides that

and the routes look good and we have our

catch all 404 here

and we have our error handler and we

have made our server.js much smaller

we're down to 44 lines of code including

some spaces here and we have pulled that

logic

out into a controller so that has really

helped clean up but we're really not

going to need these example of a

subdirectory anymore so let's go ahead

and get rid of that

and that means we can get rid of the app

used for the static files in the

subdirectory as well

and save that once again and that means

we can

delete

the subdirectory route from the tree

and we can also go ahead and delete the

subdirectory over here in the views

and let's go ahead and delete the new

page

and that means we can go into our root

routes

and we will not be routing to a new page

or an old page any longer either and get

rid of both of those

and now that's quite a bit of cleanup

but at least we still have our splash

page for the index if we wanted to put

some directions for our api there

and so we're handling that inside of the

root route

and that's in our routes folder and then

we have our api directory and that

handles the employees routes here

okay with everything cleaned up in the

last tutorial i promised to go ahead and

provide the javascript code this is not

so much just dealing with express or

node but the code if you were to have an

api that was going to update

not the json file but just in memory and

kind of emulate an api before we've

connected it to a database so at this

point i can go ahead and provide that

code and if you had went ahead and

worked on the challenge that i said at

the end of the last tutorial you can

compare your code to what i did i'm just

noticing i didn't change the path to the

data folder here either for the

employees because really it didn't need

to come up to anymore so you would just

come up out of the controller folder and

then you're not even going into a data

folder at this point you're going into a

model folder

but i'm going to change this all of this

now but i wanted to say that correction

about the path

and let's have the data

object set like this and if you work

with react i'm thinking in more of a

reactive way when i do this but i've got

the employees data set still pulling it

in and just setting it directly to the

employees property of the data object

but then i've got a set employees

function here as well that i'll use

inside of these other functions now as

you might expect get all employees

doesn't really need any extra work we're

just returning all of the employees by

referencing data dot employees and

that's fine now to create a new employee

i'll paste in my code and we can review

it

there's a little bit more work there so

when we get a new employee we want to

create the new id and instead of

importing a package like uuid or

something like that i'm just grabbing

the last employee

in the json array

and i'm adding one to the id that exists

there whatever the last one is so of

course i need to make sure they're in

chronological order which will come into

play later but that's what i'm doing

here other than that

first name and last name assigned to the

parameters we're getting from

request.body

and then of course it's first name and

last name

after that we're making sure

that a first name and last name are sent

and if not we're sending a response

400 saying hey

we didn't get the required data after

that i'm using the set employees

function to go ahead and set the

employees to the new information and of

course the new employee as it at the end

of the array and i'm just realizing here

i didn't send a different status when we

send the employees back and i'm sending

all of the employees instead of just the

new ones so we could see the update but

here we could also send a status of 201

which means it created the new record

and we'll go ahead and save that okay

update employee gets a little more

complicated but it's not too bad so

let's go ahead and paste this code in

and review it

so here we grab the employee if we

received an id

as a parameter and we should because

we're updating an existing employee and

if the employee does not exist we're

returning a response status 400 meaning

we did not get good data to update we

have the message here as well employee

id is not found and that would be the

end of it if we didn't get an id but

then if we did then we're checking to

see if we got a first name go ahead and

set the employee that we found to the

new parameter value and the same for

last name and of course to that

parameter value as well

and then we filter the array and we

remove

the existing employee record from it so

then we have an array with the existing

or i mean without

the existing employee id and then we

have the new

employee

data that we've updated here so we go

ahead and create an unsorted array and

we need to remember it's unsorted

because we do need this array in

chronological order by id

and so when i call the set employees

function from our data object i go ahead

and sort the array by that id column and

this is a chain ternary statement this

is where it could look a little

complicated if you have not worked with

sorting arrays before so

we start out with the ternary statement

here same pretty much if

the one element of the array dot id is

greater than the other than return one

and normally if we were just doing that

then if not it would be returning a

negative one but we need to have a zero

if they're even as well so then we chain

this into another ternary

and there

it returns a minus one

or the zero at the end of that

and then of course we send the employees

after they've been updated by set

employees and that puts the array the

json array back in the order we need it

right there okay scrolling up to get a

little room to put in the code for the

delete employee

we paste this in it looks very similar

we find that employee but if we didn't

get the id we send the 400 response just

like above we also create a filtered ray

a filtered array just like above we did

in the update but then at this point

we've deleted the employee so all we

need to do is set the employees to the

filtered array and then we once again

return the employees and finally the get

employee and of course

this is

handling a request for the data of just

one employee so we find out who that

employee is and once again if the

employee doesn't exist we send that same

response that we did not get good data

but if the employee exists all we need

to do is return that specific employee

and then we're down here to the exports

so i will include all of this code

inside of

the git hub repository for the end this

will not be the starter code but the

beginning and then you can see this and

compare to years if any of my

explanation did not make sense and it

looks like i've got an error here in the

code i think i missed the ending curly

brace there it is they should be yellow

at least the way i have my visual studio

code set up

tab that over and save and all looks

good now i think i still have an issue

here the delete employee did not close

out

if i close that out

then i can remove that there we go

almost had a bigger mistake that would

have taken me longer to figure out so

save that and now it looks like get

employee delete employee update employee

create new employee

get all employees that all looks like

they're defined correctly and there's no

more error here in the file getting rid

of the extra space and let's go to

thunder client but we also need to go

ahead

and start the server up because i don't

think we have done that yet

and with the dev server open

type in i mean the terminal open we'll

type npm

run dev

there we go

and start the dev server and then we'll

be able to test out our api running on

port 3500 that's what we needed we'll

open that employees api

collection that i'd created in thunder

client and now this you'll have to

create yourself of course if you haven't

but let's test get employees and see

what we start with there so we've got a

get request and we're going to the

employees route

see the results and we've got the two

starter employees dave gray and john

smith

okay now let's go to post and let's post

a new employee and if we go to body you

can see i'm sending some raw json here

we're posting employee john doe

we'll send that post request there's a

201 created response like we wanted to

send and now we have john doe here and

he has an id of three as we expected him

too

so now let's go to the

put employee

and

same route with a put request we'll go

to the body and see what i'm sending in

the json

and let's change this let's update

the second employee so it's right in the

middle

and change his name to david

now let's go ahead and send and now

let's look at our employees that were

sent back and yes second employee is now

david smith and they're still in the

correct order

he did not get inserted at the end it's

not out of order and so

that all worked as we wanted it to

now let's try the delete employee

and let's look at the body once again

what's being sent in the request and

we're going to delete employee number

three so let's go ahead and do that

and now if we look all the employees

were sent back now we only have two

employees once again and now let's

finally request an employee this is get

an employee we're going to request

employee number one

send that request and it looks like we

received the information back for

employee number one so all of our routes

are working as expected once again i'll

include everything that you saw today in

the employee controller if you're

curious about the api code i'll include

that and more in the github

link that i'm going to put in and don't

mistake the final code or the starter

source code i will have a link to both

today we will add user authorization to

our express api we're going to start

with the code repository from the last

tutorial but if you don't have it you

should be able to easily follow along

without it or you can download or clone

the starter source code from the link

that i've provided in the description

below we're going to get started by

simulating a user's database table in

our model directory with the user's json

file so let's open the model directory

and let's create a new file and name it

users.json

and now we really don't need to put

anything in here but i'll go ahead and

just put in an empty array as if it

would hold json but it's not right now

because we're going to write over this

really now user authorization requires

two routes a registration route to

register a new user account and an

authorization route to authorize the

user after they have created an account

but we're going to start in the

controllers folder because that's where

we'll really

handle the routes and what we do with

them so let's go ahead and create a new

controller and let's call this

register

controller.js

okay in the register controller let's

start out by pulling in our users from

the users database that we're simulating

with that json file i'm going to create

an object and set this up much like you

would see with use state and react where

we have our users state and we'll go

ahead and require those users

and this will be slash model

slash users.json

and after we do that let's go ahead and

have a set user's method for this object

as well and here we can say function

pass in the data

and now oops i'm so used to writing an

arrow function but this will not have an

arrow

and it's users

equals

data there we go

and now that we've got our set users

function and then our users pulled in so

we'll have our users database object

that contains both of these just a quick

way to simulate that so if you're used

to working with react this should look

kind of familiar even though it's not

really the use state and if you're not i

hope you're familiar enough with

javascript to understand how this will

be the users and of course we'll set the

users using our setter function right

here okay now we need some other things

because we're going to work with that

json file so let's go ahead and pull in

fs promises and that's the file system

so we require fs but then after it we

put dot promises

and then we're also going to need path

so let's require

path well there we go

if i can type path we'll get it and now

we're going to need to install a package

called bcrypt and bcrypt will help us

hash and salt the passwords that we come

in so we can securely and safely store

them in our database so let's go ahead

and open a terminal window i press

control back tick here in windows to

open my terminal window you could also

go to the terminal menu and choose new

terminal but here we're going to type

npm i and then b crypt

that's b c r y p t and we'll go ahead

and install this package it shouldn't

take long

and when it's complete we'll check our

package.json file to ensure that it has

been added to our project and it looks

like we're about ready to do that now so

let's see we've got it installed

scroll down here and i'll choose

package.json

and yes bcrypt has been added to our

package json file so go ahead and close

that out now we can require bcrypt

at the top of our file with our other

requirements so set that equal to

require

and

pull in bcrypt

okay now that we've done that let's go

ahead and define our handler for the new

user information that we'll receive at

this register route so i'm going to call

this

handle

new user

and this is going to receive a request

and a response

now what i forgot to do was make this an

async function which we need to do we

can use async await with bcrypt and we

might need it somewhere else too now

when we first pull this information in

the request is going to have a user and

a password so let's destructure that

from the request body so we'll get the

user

and the password

set this equal to the request.body

and now we can say if

there's no user or

there's no password we'll go ahead and

return right here with the response

the status will be 400 which stands for

bad request that's an http status

code and then json will go ahead and

send

a message down

and we'll say message

and now we'll say

username

and password

are

required and i'm noticing that we're not

wrapping lines so i'm going to press alt

z in windows that's what goes ahead and

tells visual studio code to wrap the

lines of code it may be different if

you're on mac or linux

okay so we're sending that response if

we did not receive the user password but

now at this point we'll know we have

received both the user and password and

this is where we would let me go ahead

and put a comment here check for

duplicate

usernames

in the database

and now since we're connecting to our

json file to use as our database just as

a simulation for this tutorial we can go

ahead and check for a duplicate in that

json by doing this let's go ahead and

define duplicate

and then we'll set that equal to

usersdb

dot

users which will pull in the users then

we can use find and now out of each user

let's go ahead and call this person so

it just doesn't get confusing by too

many users or using the word user over

and over this will be person and then

we're seeing if the person

dot

username from our user database

is equal to the user that has been

submitted the username that's been

submitted by the user

and therefore we can see if we get a

result as duplicate and then we can say

if

we have a duplicate

then we want to return a response

it's response dot

send status and it's 409

and that is a conflict is what that http

status code stands for but if not we're

going to start a try catch now so here's

our try and of course we have a

catch afterwards where we would catch an

error

and now let's go ahead and fill out that

error block first so if we get an error

here we're going to send a response with

a status of

500 which would be a server error

we'll have json and let's go ahead and

send a message here as well

and we can just pass in the error dot

message that is received

okay but in our try block now we need to

go ahead and create our new user and of

course also use bcrypt to hash the

password

okay i'll put a comment right here that

we're going to encrypt the password with

the next line and this is where we'll

use bcrypt so let's define our hashed

password and we'll set that equal to a

weight and then use bcrypt

and now oops i'm sorry we don't want

compare we want hash

and inside of that we pass in the

password that we've received from the

user we're going to hash it and here we

determine the salt rounds so it not only

hashes the password but it adds a salt

to it and that really helps protect the

password if your database is somehow

compromised because at that point if a

hacker were able to figure out the hash

they could crack all of the passwords in

the database but adding the individual

salts makes that much more difficult and

unique for each one so here we'll pass

in 10 salt rounds which is essentially

the default or the standard there

and that will add the salt and the hash

all at once and bcrip does a great job

of storing those together at the same

time so that's really all we have to do

there now that we've got the hashed

password we're going to go ahead and

store i'll put store

the new user

and this remember is just going to our

simulated user table that we're using in

the json so here i'm going to say

new user and define the new user object

first

we'll set this equal to username

we'll pass in the user and then we'll

have a

password that we're going to store

and this will be our hashed

password that we've created now let's

set the new data with usersdb dot

set users

and here we'll pass in all of the data

that we have so we're working with

immutable data instead of adding to the

existing array we're going to create

a brand new array and then set all of

that in the database very similar to

using state and react here so this will

be dot dot

users

db dot users and then we'll also add

the new

user all in this new array that we are

setting

as

the new users or the new users data

okay now that we've set that let's go

ahead and write it to our json file

which is our database in this simulation

so we'll have fs

promises

dot

write file

and now i'm going to break this out into

separate lines just so we can see

everything better i'll go ahead and

close our terminal window too so now on

the first line i'm going to use path dot

join and we're going to pull in the

directory name

and after that we need to go up

out of the controllers directory

and then we need to go down into the

model directory

and then we need to go ahead and write

our

users.json file so this will overwrite

any existing file there

and once we've done that we need to

specify the data we're sending and this

will say

json.stringify and we're going to pass

in our usersdb.users

okay from there let's just log to the

console so we can see all of the users

or at least the one user that we add but

we'll log all in case we go ahead and

test it more than once and add more than

one user

log those to the console and then we

need to send a status

and that status is 201 to say the new

user was created and let's go ahead

and send some json again with a success

you could put message here or whatever

you want but we'll put

new user

and then we'll pass in the user so we

get the username

and we'll say created and i needed to

make this

a template literal instead of using

single quotes we need backticks

and that way we can pass the user

straight into the string that we're

sending back

so we've created the new user and

there's the response

and that's basically it except at the

very bottom now we need to use

module dot exports and let's go ahead

and put this

in an object so we can pull in the full

name of the controller when we import it

just like we have previously done with

the employees controller and there were

finished with the register controller so

now let's go to the routes folder and

we'll need to create a new route for

this let's just call this

register.js

and now at the top of register js we

need to pull in express again and this

will be equal to require

express

and then we need to define our router

so we'll set the router equal to

express.router

and then we'll need to go ahead and pull

in the controller so let's call this

register

controller

and we'll set it equal to require

and then we need

to come up out of the routes folder and

then we'll go into the controllers

folder

and from there we'll choose the register

controller

okay now that we've got that let's

define our router or our route that

we're looking for here and it's a post

and this will come in at the slash just

the root

and then we'll pull in our register

controller dot

handle new user

and after that we can use module exports

on it i can spell module

we'll set this equal to

router as we do with our routes and now

finally in the server.js at the very

bottom of our file tree we want to go

ahead and add this route

with the other routes so i'll just copy

this down to start off

we have this slash and this will be app

use and now we're going to use the

register route

and we're going to require routes slash

register and we can save that i'm going

to collapse this open editor so we can

see all the file tree at once and if you

remember in our package json we have

nodemon installed as a dev dependency

and that will help us go ahead and start

this dev server so i'm going to press

ctrl backtick once again to launch a new

terminal window again you can do that

from the terminal menu as well

and now i'm going to type npm

run dev to launch our server and we

should get a message here saying what

port it's running on and it looks like

we've got an error let's see where the

error is

cannot find module

model user json

oh and that's because i named it users

json so we didn't import that correctly

let's go back to our register controller

and change that to users.json

and we'll save and now we should see

nodemon restart and we're running on

port 3500. okay now we can check our

route and i'm going to use an extension

called thunderclient to do that you see

thunderclient up here in the top left if

you don't have thunderclient installed

you can do that or you can use something

else like the app

postman would be a good one that is

normally used to check api routes with

but you can find thunderclient in vs

code extensions and i've found it's

pretty good to check apa api routes with

in a dev environment so here it is on

the left i've got the circle with the

lightning bolt and we can go ahead and

create a new request

and you can also save collections and

i've got a collection here already

with the request that i want to make so

i'll look at this first one and you can

see

it's a post request and it's going to

http colon slash

port 3500

and this goes to auth i don't want the

auth we created the register one let me

find that there's the register one okay

now if i click on

thunder client or the file tree or

anything else it will hide this and i've

noticed that thunder client has a much

better appearance when we hide that bar

over here so now we have the request on

the left we'll get the response on the

right and i can still see the node.js

console down here at the bottom so

with the register route in here and it's

a post route i need to check the body

and make sure i'm sending something i'm

going to send user walt 3 i believe i'll

just create walt 1 this time around

and here's a password

and of course it's unencrypted right now

but we'll see what we get in the node.js

console because remember we're going to

log to the console the users and that

should also include the password if i

remember correctly and of course we'll

get the response over here that the

client would get

so i'll click send

and on the right we've got success new

user walt one created now here at the

bottom it's got just a little more

information so we need to pull this up

so we can see more

and there you see

our user's json and it created wall one

and here is the encrypted password that

is both hashed and salted that bcrypt

helped us create from the password that

we passed in

so now let's go ahead and pull this down

and let's create one more user let's

just create

walt 2

and we'll send this

success new user walt 2 created

and now let's once again look at the

node console and you can see now both

users were logged to the console here in

node and they have different passwords

as well that are encrypted

and of course we could break all that

down but i'll let you look at the link

to be crypt and i've got another good

article on that as well i'll link to

both of those in the description below

so make sure you do that okay we have

tested and handled the registration but

of course now we need to go ahead and

handle the authorization as well i'm

going to close the terminal again

and i'm going to copy the import of

usersdb with users in set users

and i'll go ahead and create an auth

controller now in the controllers

directory so we'll call this

authcontroller.js

and now the first thing i'll do is paste

in the user's db where we import in our

users

json that simulates our users database

table and we're also going to need

bcrypt again so let's set this equal to

require and

be crypt

and now we can begin constructing our

function let's call this handle

login

and let's set it equal to an async

function that has a request and a

response

now inside the function will start out

just like we did inside the register

controller where we expect to get a user

and a password parameter both sent to us

and if we don't we'll send back that

400 http status code that says it is a

bad request so we can paste those right

in i'll press alt z again so the code

wraps

so they start out the same way but after

that there are definitely some

differences and what we need to do now

is try to find the user that's sent in

before we even concern ourselves with

the password let's just see if the

username exists so i'm going to call

this found user

and set it equal to usersdb.users.find

and then we'll look at each person in

the users table and we'll say

person.username

equal

to user and find works this way until it

actually finds somebody and then if it

finds somebody it will return that value

and if not of course it will be false or

undefined at that point so

now we could log this and take a look

but let's just say if

we do not

find a user if we do not have a found

user

we'll go ahead and return the response

dot

send status

and we're going to send a 401 which

means unauthorized

and i could put a link to mdn that lists

all of the http status codes in the

description below as well i think i will

do that so there if we do not find the

user we know hey that's it there's no

need to look any further this is

unauthorized and so it won't work

but now if we do find a user we need to

go ahead and let me put a note here just

say

evaluate

now if i could spell evaluate there we

go evaluate password

and we'll use b to do that so let's

say match

is what we're going to define and we can

just say await

bcrypt dot

compare

let's pass in the password that we

receive with the request and we're going

to compare it to the user that we've

found

and the password that exists for that

user and now if we do have a match

if the passwords match we can reply

with the json and once again we could

send a success message

and we'll just say oh back ticks again

and we'll say

user and pass in the user value

and from there we'll say is

logged in

but we could also have an else there

and

if we do not have a match at this point

then we'll say response send status and

once again this will be a 401

unauthorized

and we can save that and we're

essentially finished with the function

except for

adding the module.exports here once

again

and we'll put it in an object again and

we'll say handle login

but the other note that i want to add to

this and we're not doing it in this

tutorial but we will in the next

is this is where we would create

a jwt to send

to use with the other routes that we

want protected in our api

so we'd actually create and send a

couple of jwts which would be a normal

token and then the refresh token so

let's put create

jwts that would be right here in this

spot and we'll just leave this note here

for the next tutorial but now we've

created our handle login

in our auth controller so we once again

need to create

here we go scrolling the tree we need to

create a route for auth

so we'll just put auth.js right here

and we can copy

most everything we have in the register

and just change this over in auth so at

the top we need express and router just

the same but instead of register this is

the auth controller

we can select all of those with control

d and change them to auth

and after that instead of handle new

user

it is handle

login that we want from the auth

controller and save and our auth

route is complete now let's go back to

the server once again

and let's add the auth route as well so

let's just copy down i press shift alt

and the down arrow to copy a line down

in windows

and i'm going to put in the auth route

here i'll press ctrl d to select both

and just put off

and save that as well with that complete

let's go back to thunder client

and we'll look at our auth collection

there it is

and let's see if we can pull up the

correct route this is the auth route

that's great so i'll hide the rest and

we get a better look here i want to see

that terminal again so i'm going to

press control and back tick to pull up

the node terminal and here we are in

port 3500 so we're sending another post

this is going to localhost port 3500 and

the auth route right here so let's look

at what we're sending in the body

and we want to log in with walt

1

and the password that we had previously

submitted as well so we'll see the

client what the client receives here on

the right

and we'll see if anything is logged i

can't remember if we logged anything to

the console this time around let's go

ahead and send this

well we at least log what route we hit

here in the console but now this says

user wall 1 is logged in

let's go ahead and try to log in with

the user we don't have like walt 3

and now we get our 401 unauthorized

which is exactly what we wanted and i'm

just thinking now earlier

we didn't send something to register

that already existed so let's try to

register a name that we've already

registered we registered walt 2 last

time this is going to the register route

so now let's try to register

and we got a 409 conflict that's exactly

what we expected there as well so it

appears our routes are working correctly

and everything seems good so this is

handling

authorization with username and a

password on the back end

and we have simulated a database by

using

users.json but in the future we could

connect this to mongodb

mysql or some type of database

technology and you really wouldn't use

just a json file in production or at

least i wouldn't recommend it but we

will come back in the next tutorial and

learn how to protect routes with json

web tokens

today we will add protected routes to

our express api by using jwts let's

discuss the jwt strategy we're going to

implement today so what are jwts what is

the acronym jwt and abbreviation for

well i'm very excited about the upcoming

launch of the james webb telescope but

in this case that is not the correct

answer concerning our node and express

rest api jwt is an abbreviation for json

web tokens jwts can be considered to be

a form of user identification that is

issued after the initial user

authentication takes place

when a user completes their login

process and they are authenticated our

rest api will issue the client

application an access token and a

refresh token the access token is given

a short time before it expires for

example 5 to 15 minutes and the refresh

token is given a longer duration before

it expires possibly several hours a day

or even days while no security measures

are perfect we do want to consider the

risks of cross-site scripting and

cross-site request forgery i will

provide links about both in the

description below our api will send and

receive access tokens as json data to

avoid the previously mentioned risks it

is recommended for front-end client

applications to only store access tokens

in memory so they will be automatically

lost when the app is closed they should

not be stored in local storage or in a

cookie essentially if you can store it

somewhere with javascript a hacker can

also retrieve it with javascript just

keep access tokens in memory which you

might also refer to as the current

application state our api will issue

refresh tokens in an http only cookie

this type of cookie is not accessible

with javascript refresh tokens do need

to have an expiration which will then

require users to log in again refresh

tokens should not have the ability to

issue new refresh tokens because that

essentially grants indefinite access if

a refresh token falls into the wrong

hands so the overall access token

process involves issuing an access token

during user authorization the user's

application can then access our rest

api's protected routes with the access

token until it expires

our api will verify the access token

with middleware every time the access

token is used to make a request

when the access token does expire the

user's application will need to send

their refresh token to our api's refresh

endpoint to get a new access token of

course the refresh token is also issued

during user authorization our rest api's

refresh endpoint will verify the token

and cross-reference the refresh token in

our database too storing a reference to

the refresh token in the database will

allow refresh tokens to be terminated

early if the user decides to log out and

again refresh tokens need to be allowed

to expire so indefinite access cannot be

gained we're going to start with the

code repository from the last tutorial

but if you don't have it you should be

able to easily follow along without it

or you can download or clone the starter

source code from the link that i've

provided in the description below let's

get started today by installing the node

packages that we're going to need so i'm

going to press ctrl and the back tick

you could also go to the terminal menu

and open a new terminal window from

there i'm going to type npm i and then

we can add all of the packages that we

need all on one line so the first one is

dot env

the next one is json web token

no spaces there and then the last one is

cookie

dash

parser and we'll press enter and all of

those packages will install and then

we'll check our package json just to

make sure the dependencies have all been

added and that was fairly quick let's go

ahead and look at the package.json

and we can see under our dependencies

we've got the cookie parser we've got

dot env

and we've got the json web token package

with that complete i'm going to close

the terminal window and over in the file

tree i'm going to create a new file at

the root level and i'm going to name

this dot env just like that and now we

can put our environment variables in

here i'm going to use all caps and type

access

underscore

token underscore secret

and set that to an equals and then we'll

get the value in a second and then i'm

just going to copy that down and change

the word access

to refresh because we're going to create

an access token and a refresh token so

let's save this much for now open the

terminal window back up and now we can

type node in the terminal to go into

node and now we're running node at the

command line interface node has a common

core module called crypto so right here

at the command line we can type require

and now we can put

crypto in here and from there we can add

random bytes with camelcase with a

capital b

the number 64

and then dot to string and we'll say hex

and this will give us

a

random crypto bytes string that we can

use as our access token secret so i'll

press enter

and now i'm going to copy this and we

don't need the quotes at all inside of

our dot enb now ctrl c to copy and i'll

just paste this in here as our access

token secret now i can press alt z in

visual studio code to get that to wrap

so it doesn't go

beyond the edge of the screen so that is

our full crypto line that we just

created there now let's go ahead and

create one more i can press the up arrow

in the command line just to pull that

command back up press enter and it

generates another

random crypto line here that we can

copy and paste right into our dot env

file and with that i'm going to press

control s to save and close the terminal

actually i'm going to open the terminal

back up real quick because we didn't

exit node we press control c and then it

says press control c again so we press

it again and now we have exited node at

the command line now i'll close the

terminal window one other thing we want

to do with the dot env file is make sure

it has been added to our get ignore file

you do not want to send your environment

variable values that you're storing in

the dot env file or you could just say

you do not want to send your env file to

github you want to

keep this in your dev environment and

then when you host somewhere whichever

host you have they should have a way to

put the environment variables into their

hosting service then you can pull those

out now we need to go to our controllers

folder and open up our auth controller

that we've created in the last tutorial

and we left a note for ourselves that

this is where we want to create the jwts

on line 15. before we get started on

line 15 let's go ahead and pull in

everything we will require today so

let's define jwt

set that equal to require and then pull

in our json web token package

after that we need to go ahead and

require

dot

env

and then we need dot config after that

and after that we need our

fs promises because we have not

integrated or any other database

technology yet so we are still working

with simple files and json values so we

need this fs promises and we'll set that

equal to

the fs module

and after that we need dot promises

and then finally we need the path module

we'll set that equal to path

now let's scroll down so we have just a

little more room to work on the screen

and we're back here and now line 15

turned into line 20 where we're creating

our jwts and let's define our access

token

we use camelcase with a capital t on

token and we'll set this equal to jwt

dot

sign

the first thing we need to pass into the

jwt

is a payload so what we're going to use

is our username object you don't want to

pass in anything like a password or

anything that would

otherwise hurt your security because

this is available to all if they get a

hold of your token so what we want to

pass in is just the username i'm going

to do this on a separate line and so

we'll create this object

with username

and here above we had a found user and

then we can say

username now this is coming from up here

where we found the user that was logging

in after that the second thing we need

to create our access token is our secret

that we defined in the dot env file so

we access this by process

dot env dot

access

token

underscore

secret

and then finally what we need is an

options value here and we can say when

this token expires

and this is camelcase expires in and

we're going to make this very short for

this tutorial that will allow me to show

the token expiring and see what happens

but what you might want to do in

production would be maybe 5 minutes or

15 minutes some small window of time but

30 seconds might be too short it is all

a preference though and with that

defined let's go ahead and highlight all

of this and then i'll just press shift

alt and the down arrow to copy it all

down and we'll just make a few changes

to go ahead and create our refresh token

as well so i'm going to type

refresh here instead of access we're

once again going to pass in the username

but then we need the refresh token

secret

now a refresh token needs to last much

longer than the access token but you do

want it to expire at some point and so

i'm going to make this

one day and i'm going to give a link to

the package the json web token package

on npm js and there you can see

another link and more documentation on

the different values you could put in

here but one day is what we're going for

and then we want it to expire and we

want our users to have to log back in

you could make an indefinite refresh

token but that means if someone gets a

hold of it and they're not the correct

person they will always have access and

you do not want that with both tokens

created i'm going to scroll up for a

little more room again and we want to

save our refresh token in the database

which will also allow us to create a

logout route in the future that will

allow us to invalidate the refresh token

when a user logs out so let's start by

doing that and once again we're just

working with our json files for now and

we haven't connected this to an actual

database that we will do in future

tutorials but of course that lets us

modulize these tutorials and then we can

attack say or go over to postgres

or anything we want to in separate

tutorials so for now just the json file

and i'm going to define other

users we had a found user

so now we'll set other users equal to

the users

db dot users

dot filter

and now for each person that we have

we're going to say person dot

username

not equal to

and now let's have that not equal to i

believe it was

the user that we came in with the

request right here however we also have

our found user dot user name and i

believe i'd like to use that since we

have found it so let's say found

user

dot username

and now that creates

an array of the other users that are not

the username that is logged in and now

let's create a current user

we're going to set this current user

equal to the found user

and then we're also going to add in the

refresh token

that will be saved with this current

user and now let's set our users once

again and we can say users db dot

set users

and in this new array

we'll go ahead and

add the other users

and then we'll add the current user that

we just created i really don't know why

i'm putting spaces there really don't

usually do that in an array and okay

let's go ahead and put the semicolon and

let's write our new users file this

would be await and then fs

promises

dot write file

i'll go down to a separate line i'm

going to scroll up once again just to

put that in the middle say path dot join

we'll pull in

the directory name

then we need to go up one directory

and then we need to go into the model

directory

and then we need to go ahead and name

this users.json as our users file is

after that what we want to put in we

need to json stringify and pass in

usersdb

dot

users which will write our new users

file and so i should have put a little

comment here at the top this is

saving

refresh

token with

current user which again doing this will

allow us to invalidate that refresh

token as the current user logs out if

they log out before their one day has

expired so as a quick review we have

created the jwts once we have authorized

the login which was with bcrypt in the

previous tutorial

but now that we authorize the login we

create the jwts we have a refresh token

that's been saved

into the online database and an access

token and yet we still need to send both

the refresh token

and the access token to the user the

easy part of this is to just remove what

we were sending in our json and instead

send the access token we can send that

as json and on the front end the front

end developer or as a full stack

developer if you're developing the back

end and the front end you really want to

store this access token in memory

it's not secure in local storage and any

cookie that you can access with a

javascript could also be accessed so

anything that really that javascript can

access where you would store it it's not

really that secure so if you store the

access token in memory which has a very

short life span we only gave it 30

seconds here but like i said maybe you'd

give it 15 minutes by keeping that in

memory

you're not storing it anywhere

vulnerable after that the refresh token

well what we're going to do i've

definitely seen tutorials that also just

send it along in the json but that kind

of creates a dilemma for the front end

developer or as you develop the front

end because you do need to store the

refresh token we want to send it as a

cookie and i know i said a cookie could

be vulnerable to javascript but if we

set the cookie as http only it is not

available to javascript so that's what

we want to do so let's say res.cookie

and now here we can name the cookie i'll

just name it jwt

from there we want to pass in our

refresh token

and after that we want to give options

and the first option i'll give a space

here http only

set that to true

and after that we want to set a max age

here we go and now i'm going to set this

to 24 which would be 24 hours

60 times 60 times

1000 and this is in milliseconds here so

what we're really getting

is one day because that's what that is

equal to as we set the max age of the

cookie and i'll go ahead and cap that

off here you could set it for longer as

well now cookie is always sent with

every request but the nice thing about

an http only cookie is that it is not

available to javascript and while it's

not a hundred percent secure it's much

more secure than storing your refresh

token in local storage or in another

cookie that is available to javascript

so let's save this and now we know we

are sending our refresh cookie that is

http only to the user we're also sending

the access token

oh here we're sending our refresh token

is what i meant to say in a cookie that

is http only

we're also sending the access token as

json that the front end developer can

grab

and we're also storing this same refresh

token in a database here that can be

cross-referenced when it is sent back to

create another access token with our

auth controller complete let's now go

look at the middleware folder

and we need to create a new middleware

file here and let's call this verify jwt

dot js and we're going to need jwt and

dot env once again in this file so i'm

back in the auth controller just long

enough to copy these two and then go

back to the verify jwt dot js

and i'll paste in our required packages

right at the top

after that i'm going to create verify

jwt

set this equal to a function that has a

request

response and next as middleware should

and now let's define the auth header at

the very top and this is going to be

equal to request

dot headers

oh and then we need a bracket not a dot

and then

authorization

and of course we need to check to see if

that is actually received so now we can

say if

no auth header

we're going to send a response which we

need to return

and then just send

the status 401 which stands for

unauthorized

after that i'm going to go ahead and put

a console log statement to just go ahead

and log the auth header for when we test

this we'll be able to see that in the

console you'll see a line that looks

like this and it will say bearer

and there will be a space and then there

will be

the token after that so we can define

our token now

and we can set this equal to

the auth header and then we can call

split on that space that i just

described and we'll put the space in

here on the split and then we need the

token so it wouldn't be in the zero

position it's in the one position after

that

and now we can verify the token with the

jwt dot verify

and here we'll pass in

the token first

after the token

we'll pull back in our secret and this

will be the access token secret because

that's what we'll verify with this

middleware

and after the access token secret there

will be a callback that gets an error

and then we'll call this you could call

it token if you want we'll call it

decoded

because it will have decoded information

from the jwt

and now we'll say if we have an error

let's go ahead and return

and send a status once again

this status will be 403 forbidden

because at this point we'll know we

received a token

but something about it wasn't right in

other words it may have been tampered

with and so

this means we have a invalid token

so we'll send a 403 instead of a 401

which means you are forbidden from

accessing this

and then we'll set the user

equal to

decoded dot username remember we passed

in the username to the jwt so now it's

been decoded and we can read that

and then we'll call

next from our middleware

and that pretty much wraps up that whole

middleware function right there except

we need to remember to export it so

we'll say module.exports

set that equal to verify

jwt and save with the middleware now

complete we can add it to a route or

routes that we want to protect

so let's open up routes and api and go

to our employees js file that has all of

the employee routes in it and we need to

import that middleware here so we'll say

const

verify jwt

equals

require

and now we need to go up out of the api

folder

up out of the next folder the routes

folder and then go to middleware and

then choose

verify jwt

and once we have that we can just put it

let's say in our git route if we only

wanted it in the get route

before

we call the controller and so it will go

through the middleware first and then go

to the employees controller here so

let's save this and now let's test this

with thunderclient so over here to the

left i'll open up thunderclient

and we're going to need to log in first

so i'll go to our collections and i have

an auth collection that i created and i

want to go to the auth route

i'll click this and now i'm going to

click over here again to hide the tree

so we can see better and i'm also going

to press control and backtick to open

our terminal window we haven't started

the server yet so that's something else

we need so we need to type npm

run dev to go ahead and start our server

and it's running on port 3500 and so you

can see the route we're going to go to

is a post route it's localhost 3500

auth that we had previously set up to

log in with the password so in the body

we're sending wall 1 and password

and the password that we had in there

previously and this is in the users file

that i have if you haven't done this you

need to go ahead and either create this

in the file or use the register route

that we previously created and create a

new user and then this will work but

we're right now we're going to log in

with user walt 1

and this password using this route so

i'll go ahead and send

and you can see over here on the right

the response we get is a 200 and we get

this access token this access token will

only be good for 30 seconds though so

let's see if i'm fast enough to come

back here to our collections

open the employees api

and now let's look at this and i need to

go ahead and in auth i need to send a

new

access token now we can send

and we got our employees back but this

will expire and notice down here we also

got the console log statement i put in

here's bear

and then the space and then the token so

now if i send this again the token

should have expired

and now we get the 403 forbidden because

the access token that we sent was only

good for 30 seconds now let's look at

the employees.js file again and i will

go ahead and click the file tree so we

can see our files also we're only

applying this verify jwt middleware to

the get route right now

and this is a good way to do this if you

have select routes that you want to

protect or verify but not all of them

however if you know you want to protect

all of the routes in your api

there is an easier way to do this so

let's go ahead and remove this and we'll

pull this out of here as well

and i don't think we'll just retype it

in the server file because that's where

we're headed next so we've removed the

verify jwt from the employees js file

all together let's go to server js our

main file

and here

we can just pull this middleware in

so i'm going to do it right underneath

the error handler that we had middleware

for so we'll say

verify jwt

set this equal to require

and here we want to go into we don't

need to go up at all actually we just

want to go into dot slash

middleware slash

verify jwt

and now that we have that we can use

this just like we've used other

middleware in our file but we probably

don't want to use this verified jwt

middleware for all the routes probably

not the root route that we have here

definitely not to register a new user or

we'd never be able to register in the

first place and not even to auth because

they have to visit auth first to get the

token but we do want to put it before

the employees route so i'll put an extra

line there

and then

right here we'll say use

verify

jwt

and if you remember

this works like a waterfall so in this

order everything after this line will

use the verified jwt middleware so

any route we do not want to have

verified with the jwt we need to have

above this line right here so let's go

ahead and save this once again

and now we can go back

and let's log in again and get another

well we close up the api there there we

go here's our offline let's log in and

get another 30 second access token

here we are

okay now let's go back to the employees

and once again we can just use the get

route before it was forbidden because it

expired but now let's go to the auth tab

here in thunder client

select all delete that paste in the new

token and submit

and we've got our employees list once

again but if i continue to submit

it will expire

as soon as the 30 seconds is up and

there is our 403 and just to show that

this is on all routes now let's go back

to our employees api to the post route

for posting an employee

here in the body

we've got john doe so that looks like we

could go ahead and post to the employees

for john doe let's see if we can send

this

and we get unauthorized so our verify

jwt middleware is working on all routes

okay let's go back to the file tree we

can close the terminal once again we can

close out of thunderclient for now and

let's close up the middleware what we do

want is to go back to the controllers

and we're going to create a new

controller here called

refresh

token

controller.js because we're going to

have a refresh token route and before we

get started on our refresh token

controller because we're going to need

it let's go back to the server.js

quickly

and at the top of the server.js we

pulled in the verified jwt

we also need to go ahead and define

cookie parser the other package that we

had required at the beginning of the

tutorial

and let's require

cookie dash parser there we go but we'll

define it with cookie parser capital p

camel case right here so i can go ahead

and copy that

now much like where we used the

express.json and express.url

encoded that we use for form data and of

course

express.json is for json data we just

want to add

middleware

or cookies right here so we'll say

app.use

and now we'll pass in

cookie parser and we want to call that

into action right there

and save our server.js file now we're

ready to go right back to that refresh

token controller and we'll begin by

copying the auth controller

control c i'll just copy everything and

paste it in but we will make some

modifications

so we need the user's db we will not

need bcrypt because we are not doing

user password authentication there we do

need jwt

and dot env

but we won't need fs promises or the

path in this either so we can remove

those dependencies now instead of handle

login let's call this handle

refresh

token

and this does not need to be async so

we'll just have the request and response

here

after that we won't be looking for a

password

but we will be looking for a cookie so

let's say const

cookies and set this equal to request

dot cookies and so we will have a

similar if statement here at the

beginning

but we'll be checking for a couple of

things one is to make sure that we have

cookies but now let's use optional

chaining with a question mark and a dot

the optional chaining operator and put

jwt after it so we're checking to see

if we have cookies and then if we do

have the cookies we're also checking to

see if there is a jwt property and this

is saying of course if these do not

exist

then we're going to return something

here and we're going to return a 401 and

we do not need a json message after that

so i'll just eliminate that portion of

it

and save this it looks like i may need

to go ahead and press alt z to wrap any

lines that exceed

the edge of the screen so there we've

got a 401 if the cookies do not exist

and

maybe we have cookies but no jwt either

way that gets a 401 which is

unauthorized now let's go ahead after

we've confirmed that at least and let's

log to the console

cookies.jw

so when we run this you'll be able to

see what values we get from that and

likewise let's go ahead and define the

refresh token now that we've received

now that we know it exists within the

cookie and we'll set that equal to

cookies.jwt

and once again we do want to find a user

but now we're receiving a refresh token

and not a username or password for this

so we'll say person and there is a

refresh token that should be saved with

each user if they have created one

and so here we'll just match that to the

refresh token

that we have now defined here so this

would be our found user then if that

user exists and once again we can say if

we do not find a user let's now send the

status forbidden here and i'll just

highlight that

okay we're not evaluating a password

here we are evaluating a jwt though so

these lines will change as well so we

can get rid of the const match line

and instead well we can even get rid of

the if match here as well

and instead of that we'll type

jwt dot verify

and now we'll pass in

the refresh token that was received

now we'll say process dot env

dot

refresh token secret

and then we'll have

an anonymous function that once again

has error and decoded its callback

function

and before i type the rest i think i'm

just going to get rid of this because

it doesn't need to be there at this

point either so let's just go ahead and

clear it out now

and with that cleared out we can finish

our function here for the token

verification and

if we do not have a valid token we can

say if we have an error

or

we can also check the found user dot

username because we did have the

username encoded in the token

so if it's not equal to the decoded

dot username in other words maybe it was

tampered with again

then we can

return a response with a send status

and say 403 once again

otherwise everything is good and we're

ready to create a new access token

descend because the refresh token has

verified so we'll set this access token

equal to jwt dot sign

and then inside of the access token will

once again have a username

and this username will be the

dot username because it should be the

same username that was verified before

and after that we can say process dot

env

dot

access token secret

if we can find that access

token

secret there we go

and now we need to put an expires in

once again

let's put expires in

and let's set this to 30 seconds as well

however remember you might want to set

this longer in your production app this

is just for the demonstration of this

tutorial so i can show it expire and

then of course after we've created this

access token we need to go ahead and

send the access token

so we'll send this json down and it'll

say access

token

and once we've created that much all we

need to do is export it

so now instead of handle login we once

again have handle i believe it was

refresh token yep

and we should be able to save that

and i don't know why i put a semicolon

there it's not really needed so

once we have saved that we should be

good to go with our refresh token

controller and we can create the refresh

token route okay in our routes file now

we can open that up and we can look at

our auth route i'll just highlight all

and copy and we'll create a new route

called refresh

dot js

i'll go ahead and paste that in but

instead of the auth controller we need

the refresh token controller so we'll

spell all of that out

and instead of handle login we need

handle

refresh token and before we're finished

with our refresh route let's change the

http method from post

to git as well so this is now a get

route for refresh okay now we need to

insert this route into the server along

with the other routes so we'll go to the

server.js file and you can see we've got

root register auth and of course we want

this to also be before we verify the jwt

because the refresh route actually

issues a new access token and that's

what verified jwt verifies so what we

want to do now

is just copy a line down i pressed shift

alt and the down arrow in windows to do

that and i'm going to change off

to refresh

and now the refresh endpoint will

receive the cookie that has the refresh

token and then that will issue a new

access token once the access token has

expired so we'll save this and we should

be ready to try it out so i need to open

up the terminal window again and we can

see our server is running on port 3500

now let's open up thunder client

and we're ready to check out the refresh

route but first we need to go to the

auth route

and here it looks like the off path

i'll hide the tree over there and so now

we're going to localhost 3500 auth we're

once again going to authorize

walt here with his password so let's

send this

and we got a new access token but what

we also get from our auth route is a

cookie and this cookie has a refresh

token and here's the jwt name for the

cookie and here's the refresh token now

a cookie is sent every time we don't

need to paste it in in an auth area like

we did with our access token

the jwt cookie is sent every time we

make a request to the domain that it's

associated with so we'll go back over

here to thunder client we'll come down

to our refresh route and i'll hide that

tree now we're going to localhost 3500

refresh and you can see we don't need to

post anything in the body we don't need

to post anything in the auth because we

have the cookie that we're going to send

so let's send this cookie

and now we got a new access token and

you can see we also logged our

information as we set it up in our path

to log

the refresh token that we received from

the cookie down here so

we've got

a new access token and our refresh token

is used to do that so now every time we

hit this refresh route and we send our

cookie with the refresh token we should

get a new access token and you can see

every time we're getting a different

access token over there so that is what

refreshes our access and that's why it's

called a refresh token and so now we

have a new

limited time access token to use again

in production you might want to set it

to 5 minutes or 15 minutes instead of 30

seconds or something like that

but then our refresh token has the

longer duration that we store in an http

only cookie and that's because we don't

want it to be available via javascript

so it increases our security nothing's

100 perfect but it's the best way to go

i believe for that so we're sending the

http only cookie that has the refresh

token and that issues us the new access

token now that we've finished testing

the refresh route one extra measure of

security or one extra step we can take

is to offer a log out route and with the

log out route we could actually then

delete the refresh token and not let it

last for the full duration and that just

gives our users the opportunity to log

out and of course delete any existing

tokens and of course the access token

should also be erased on the front end

when the login or log out

link or button is clicked as well of

course we're working on the back end so

we won't be doing that today but let's

go ahead and add this new controller for

the logout so we'll have logout

controller.js

and now that we have that let's go ahead

and copy our refresh token controller

and we will just make some modifications

to handle the logout because we need the

same requirements at the top we've

pulling in the users so we can check our

database we've got the jwt requirement

and we've also got dot env i'm going to

close the terminal window

and now i said we had the same

requirements we don't quite have the

same requirements i'm sorry we don't

need the jwt or the dot emv

what we do need

is the fs promises that goes with

accessing our database because we're

just using a json file so we'll require

fs

dot

promises and we once again need path so

we'll require

the path

and again these are only to access the

current json file we're using for our

users database this is a mock database

this will be replaced of course

with or postgres or whichever

database technology we work on in a

tutorial in the future

so we've got this

down for the requirements and let's move

forward with the log out so instead of

handle refresh token now we're going to

handle the logout

and we'll have a request and response

and then let's just add a note here for

the front end if you're doing full stack

development like on

client

also

delete

the access

token

we can't do that here on the back end

you need to do that

in the memory of the client application

just

zero it out or set it to blank or

whatever when that log out button is

clicked what we can do though is take

care of the refresh token so here once

again we need to get the cookies as they

come in now let's erase our logs here we

were doing for the cookies and the

cookies jwt before if you wanted to see

those in the console

and we'll once again verify that we have

got cookies and then that we also have a

jwt in the cookies and if we don't

well that's okay because we were just

going to erase it anyway so let's send a

status 204 that means it's successful

and there's essentially

no

content to send back that's what that

status is so you've had a successful

request and we're not sending any

content

and this needs to be send status instead

of just status there we go response.send

status got that now let's go ahead and

define our refresh token and we'll do

that in the same way setting it equal to

cookies.jwt

now let's see if we have that refresh

token in the database so that's what

we're checking here

is

refresh token in db

so once again

we try to find a user that has this

token so setting this equal to the

refresh token just as we did

in the previous refresh token controller

is exactly what we need

and if we don't have a found user at

this point we can go ahead and clear the

cookie so we're going to do something

just a little different here and it

won't be forbidden either so we'll get

rid of that

and

let's go ahead and look at how we clear

the cookie first so if we don't have a

found user but we did have a cookie to

get to this point we can just go ahead

and erase the cookie that was sent

and that's going to be with response dot

clear

cookie

and then inside there we'll look for the

jwt cookie

and then you have to pass in the same

options that it was set with so once

again we'll say http only

set that to true

and that should be all we need to do

there except for sending the proper

status so once again we're going to

return

and send the status not a 403 but of 204

which once again means this was

successful but no content okay i'm going

to scroll up just a little bit and now

we can pretty much erase everything here

and we're going to create some new

content

below because if we've reached this

point that means

we did find the same refresh token in

the database so now we need to

delete the refresh

token in the database right here and

we're using file system of course for

that instead of or postgres at

this point but we will change that in

the future right now

let's define other users which would be

all of the other users that are not the

user that we found and set that equal to

users db

dot users

dot filter and we'll just filter this

out we'll pass in a person

and now the person dot

refresh token

is not equal to our

found user dot

refresh token as well there we go

okay so i'm going to press alt z to wrap

that line of code so we can see all of

it and that's all the other users so now

our current user

[Music]

is going to be equal to our found user

and then we're going to set the refresh

token to blank so

we'll leave the refresh token property

but now we're just erasing it from the

user and now we can update our users db

with our set users

and we'll go ahead and pass in our

other users

and then we'll pass in our found user

oh and i'm sorry that's not found user

that should be the current user that we

just defined there we go so found user

was before we erased the fresh token now

the current user has the updated refresh

token that is zeroed out or blank if you

will now let's just write this to the

file so we'll await fs

promises dot

write file

and now on a separate line here i'm

going to say path dot join

pass in the directory name

after that we'll need to come up one

folder

and then we'll say in the model folder

and then we'll name the

users.json file

okay then we need to go ahead and use

json.stringify

and write in the usersdb

dot users

and that should update our users file

and so after that we need to go ahead

and delete the cookie which we saw how

to do before as well so we use clear

cookie

and we reference a jwt

and we need to pass in the same options

as well

http only set to true now i will add in

production both when we send the cookie

and when we delete the cookie you also

want to add the flag

secure

true and that will make it only serve

so it only serves

on

https we're just using a dev server that

uses http but you want a secure

connection with

https so

we don't add this in development but we

would in production the option of secure

and set that to true

okay and after that we want to send our

status again which once again is a 204

all as well but we have no content to

send back

and after that we need to change our

export from handle refresh token

to handle logout and save okay with the

controller complete let's create our

route file

and we can just go here to the refresh

file we created

select all and copy

and now i'm going to create a new file

in the routes called logout.js

and now i'll just paste everything in

from the refresh

route and we'll change that so we need

express we need the router but instead

of refresh token controller we'll select

all three of those with control d

and i'll just type

log out

and this will be a get route again and

the export to router is correct but we

do not have handle refresh token here we

also have handle

logout as

the function for the controller and with

that complete now we can go to the

server and add that route as well we

won't need to verify a jwt to log out so

i will just once again shift alt and the

down arrow to copy a line down

and i'll change refresh

to log out and save now let's open a

terminal window again oh and we've got

an error so let's see what our error is

here in node

a weight is only valid in an async

function ah we did not do that in our

controller let's go back to the logout

controller and we used await when we

used fs promises so let's make the

handle logout an async function

and save and let's see if node restarts

and yes the server is running on 3500

all looks good there so now we can go to

thunder client

and we'll hit our auth route to make

sure everything is logged in we're going

to log in our user walt one

and we've got an access token

and we've got a cookie

so now let's go back to thunder client

and i have a log out route that is a get

route as well so we have get localhost

3500

log out you don't need to pass anything

in the body or the auth when we log out

but let's go ahead and do that

and we hit log out and everything seems

to be fine

we can see our cookie has now been

erased

so now if we go to any of the other

routes

like refresh that would use our refresh

token cookie

we don't have a cookie to refresh with

so now let's try localhost 3500 refresh

and it's a git route and see what we get

well we can see in the console we logged

or attempted to log a cookie but it

didn't exist here and we're not getting

a response so let's look at that i can

cancel this here in thunder client let's

go ahead and look at our

refresh controller

and see what's going on there so refresh

token controller

and here is where we're logging the

cookies we can get rid of these lines

actually now so we don't need those

but let's see if we can figure out what

is going on and yes here's the error i

said response dot status 401 it needs to

be response dot

send status 401

just like we had down here with send

status 403

so if i've typoed any of those others

throughout this code it looks like i had

send status everywhere else but just in

case you see that to actually send the

status it needs to be send status

instead of just status status is

chainable if we're sending a response

after that

but now this should work so let's once

again go back to thunderclient

and we'll hit our refresh token route

although we don't have a cookie

and we'll see what happens

ah we immediately got our 401

unauthorized because now it sends the

status so that's correct let's go back

and log in again with our auth route

localhost 3500 auth send that we have an

access token

we have a cookie and everything seems

good so all routes are working as

expected okay i thought i was at the end

of the tutorial but after playing around

with some front end code there were a

few things i thought i needed to go

ahead and clear up or include one is

here this is front end code by the way

this is not what we were working on in

express if you use fetch to access

what we had set up say our auth route

well you're going to need to include

a credentials option

again on the front end to have fetch

send the cookie now if you use axios i

believe there is a with credentials flag

that needs to be set as well

and we could do that in a future

tutorial but right now

just looking at credentials for use with

fetch so you have to set that to include

but that sets off a chain of events so

even though this is required here to

send the cookie

then what happens

is i'll pull up chrome here

we get a course error

and you will be blocked by cores because

the value of access control allow

credentials in the header

of the response

is blank

and it needs to be set to true

so cores will block this

if you don't have that set before you

reach the course check now what is

happening is a pre-flight options check

it's an options http method request but

then you also need to have the same

access control allow credentials

set to true when you do send the cookie

back as well because that's what's

expected with fetch

so there's a way to fix that of course

and now let's look at some of our back

end code

and let's start in the config folder

and i went to coors options first

and we did have what was called a white

list in here which

that's traditionally what it's called

and i've seen that in articles as well i

don't like the name so much either

just maybe in modern day it sounds a

little racist or something so we've

switched that to allowed origins which

is what it is it's a list of allowed

origins and i put it in its own file

because we're going to use it in

middleware also but i only want to

update it in one place so we have our

allowed origins

formerly called the white list in the

tutorial

and we're exporting allowed origins so

we import that into our cores options

and use it here but then we also create

middleware called credentials

and now this credentials middleware of

course has a request response and next

and we import allowed origins here also

all we're really doing is to say if

the origin that is sending the request

is in our allowed origins list so it's

just a little bit of extra security if

that is the case go ahead and set this

header on the response because that's

what cores is looking for

access control allow credentials and we

set that to true

so now that we have the middleware

created we go to the server file and we

pull that middleware in

and then you want to use the middleware

we're using credentials right here and

of course i'm importing it right up here

above

you want to use that before cores

because of course sees that that

response header is not set it throws

that error

so

that will fix that issue and i would

hope that would be the end of the issues

but no there was one other issue

and let's take a look at what that was

i'm going to open chrome again and i had

to do a screen capture now i was in the

dev tools in the network tab and i was

looking at the auth request and then i

could pull up the cookie

and then there was this little triangle

and the reason i had to do this screen

capture is because i had to mouse over

the triangle

for this message to pop up in this very

small print i'm zoomed in

quite a bit already just to see this and

it said the set cookie header didn't

specify a same site attribute so that

defaulted to same site equals lacks and

then it was blocked because it came from

a cross site response which means

our

front end application was not on the

same domain as our back end api and

that's often the case

so

there's nothing wrong with that it's

just that's why they blocked it says the

set cookie had to have been set with

same site equals none

to enable cross site usage so that tells

us something else another option

we need to go and put in our set cookie

response so let's look back at the back

end code here

and

then where did we set the cookies well

let's look at the controllers that's

where the cookies were being set

and i believe the auth controller is

what sets the cookie specifically and so

not only do we have http only true

but then we went ahead and set same site

to none as they request here

and then after you do that

they give you another message in the

same spot and that says secure must be

set to true

now previously i didn't have secure set

to true there

because i thought you could only use it

with https even during development but

no it's working in the dev server even

though we're just using http

then after that i went ahead i've got

the code wrapping by the way because

down here on the next line you still

have the max age option

now when you delete a cookie

you need to set the same options however

and i'll put a link to the documentation

in the description below however max age

actually does not need to be set

or in there when you delete the cookie

it's one of only a couple like the

expiration and max age are the only two

options that don't need to be identical

when you delete the cookie so when we go

to the log out controller

and we have our res.clear cookie we need

to have http only same site and secure

all set as before but max age does not

need to be in here and we've got that in

here a couple of times

in the log out controller as well so we

did make those changes but after you do

that

everything should work as intended so

it's just a couple of things i

discovered as i was working with this

front end code and of course it is good

to test it out with actual code and a

browser besides using an extension like

thunder client because thunder client

showed everything was working as we

expected it to but of course we ran into

a few issues with chrome and now

i've walked you through how to fix those

as well

since creating the last tutorial i

realized there's a lot of confusion

concerning the concepts of

authentication and authorization they're

often used interchangeably or simply

abbreviated as off but they are not the

same things

authentication refers to the process of

verifying who someone is

authorization is the process of

verifying what specific resources a user

has access to when we log in with the

username and password we are verifying

who we are and that is considered to be

authentication

after logging in our express api issues

users jwt tokens jwt stands for json web

tokens while it's true that the tokens

confirm the authentication process has

already taken place these tokens also

allow access to our api endpoints which

provide our api data

this is authorization a hint towards

this fact is that a jwt token uses the

authorization header today we will

expand the authorization process by

adding user roles with specific

permissions to our api authorization

process we're going to start with the

code repository from the last tutorial

but if you don't have it you should be

able to easily follow along without it

or you can download or clone the starter

source code from the link i've provided

in the description below we're going to

start by going to the config folder in

the file tree and creating a new file

and we'll call this file roles

underscore list dot js

in the roles list we're going to create

the user roles now this could be in a

data table in a database this is just

how we're going to do this and you'll

find that user permissions can be

constructed in an assortment of ways and

we're going to apply a fairly simple

structure today with three different

user roles so we'll start out with our

roles list constant

and we're going to set this equal to an

object

and the keys will actually be the names

of the roles so we'll have admin and

then we'll have a code that identifies

the role

and then after that let's create an

editor role and we'll call this 1984 and

then let's have just a user role and

we'll give that 2001. okay now that

we've created our roles list object all

we need to do here is

module.exports

and set that equal to roles underscore

list

okay we've saved that now we're ready to

go ahead and modify

our users model that we have in the

users.json

file

and you might find that

once it has been written

by the read and write file process that

we use in node we're using this user

jsons file it might all be in one line

but i believe if we go ahead and just

put a return and edit and then save in

visual studio code it should go ahead

and format that file for you so it's a

little easier to read now this is what

we had after the last tutorial we have a

username walt1 and a username walt2 they

all have their own passwords and of

course we're tracking the refresh tokens

i'm going to copy in the file i've

created it adds one more user and so you

can copy this file

out of the completed source code that

i'm going to link to there's a starter

source code link and then a completed

source code link or you can go ahead and

use the register route create your own

new user and you can see i've added dave

one as well as our walt one and walt ii

dave one just has the role of user while

walt 2 has the roles of user and editor

and walt 1

is not only a user but also an editor

and admin so you can see we're going to

support multiple roles i'll go ahead and

save this file once again you can copy

it from the completed source code or

just create your own third user if you

want to

and we'll just edit these manually now

there could be

a admin area

for whatever service you were creating

and that is where these additional roles

could be created but what we will do is

just ensure when everyone registers

they're given the user role and then of

course later on you'd think an admin

that was in charge could add the

additional roles if those roles were to

be granted to other users

so now we can collapse the model folder

and the config folder but let's look

inside the controller folder and let's

look at that register controller that we

have what we want to do

is add that role of user with the 2001

code

when any user registers you can see

we're creating our new user right here

on line 19 and we have the username and

the hashed password so let's just go

ahead and add this extra roll i'll break

this out on separate lines

and that way we can see

the new part that we add and what we

want to do is just in between username

and password

add roles let's keep that lowercase

and after that let's put this in an

object so then we have

user

and then we have the code 2001 and then

remember to put a comma after roles

so it goes before the password

and save now let's go to the auth

controller

and when we authorize and create the

access token

we will want to send this information in

the access token so we're going to

change our payload for the jwts

now first when we know we have a match

and we have verified our user so

everything is good we want to go ahead

and grab the roles that we put in our

users json file so let's go ahead and

define roles

and set this equal to object

dot values and then we can pass in the

found user that we have above

and we want found user dot

roles and so now we'll get those values

inside of roles and now let's change our

access token payload just a little bit

since we're not just going to send the

username let's create a new namespace

here with user

info and then this will be an object

and inside this object we'll have

username

let me go ahead and add the closing

curly brace for the object here so we'll

have the username

but then oh we don't need that closing

curly brace but then we also want to add

some more information here inside of the

user info object

and the next one will be

roles

with quote and we'll just pass

the rolls that we've created it looks

like i actually did need that extra

curly brace or at least we need to

indent here

and then we're going to need to close

out our payload that looks correct i

believe and if you want to break this

onto another line you can do that as

well

go ahead and save and there we go it

gets formatted a little bit better

already so we're using this user info as

a different name space and that's good

because this is considered to be a

private jwt claim because there are some

res

reserved abbreviations and words for

public jwt claims and you can find out

more about that at

jwt dot io i believe i'll confirm that

and leave a link in the description

below so you can check out more

information on the jwt claims if you're

interested now there is no reason to

send the roles in the refresh token and

ideally the access token will only be

stored in memory on the front end but we

don't have control over that so when we

do send the roles we're just sending the

codes and not actually the word admin or

editor or anything like that

so we just are kind of hiding what each

one is by using codes but at the same

time ideally that access token would

only be stored in memory anyway but

there is no need whatsoever to send the

roles in the refresh token refresh token

is only there to verify that you can get

a new access token

okay now speaking of the refresh token

we need to go to the refresh token

controller and add some of the same code

because that refresh token does issue

a new access token so

right underneath where we have verified

the or we've actually decoded the

refresh token here and we have the

decoded and now we have no error and

everything is good so we want to come

down to this line right before we create

the token and here once again let's

define roles and set equal to object

dot values and we'll pass in our found

user once again and the roles that are

associated with that user and now we can

use the name new namespace as well so

we'll use user info again

and then we'll create an object

and inside this object

we'll have the username which is the

decoded username

but then we'll also

want to put the roles once again so

now we'll have roles

and here we can just pass in roles once

again i need a comma it looks like and

now let's save and it will format a

little bit better and that looks correct

so we have user info with username

and roles now that we've updated our

tokens to include the roles our access

token specifically we're ready to go to

middleware because we're going to have

to create some new middleware to verify

those roles but first let's look at the

verified jwt file that we already have

i'd like to make a couple of quick

updates one is when we define the auth

header this works and especially when we

have control of the front end as well

and we know we would define

authorization with a lower case a

however it can also come in with an

upper case so instead of this let's go

ahead and just say

dot authorization which is essentially

the same thing that we had but then we

can also say or and then we could have

request dot headers

dot authorization with a capital a as

well just in case it comes in with a

capital now we know we're going to grab

it either way

after that let's go ahead and change our

if auth header as well

and let's look for

an optional chaining method here so we

say if we have or if we do not have the

auth header actually are saying

and also

starts

with

and here we want to have

bearer and

this is supposed to be a capital b by

the standard so we don't really have to

look for lowercase and uppercase like we

were here so we're verifying

that

first of all if we do have an off header

or if it starts with this and we're

actually looking to say if we don't have

an auth header and then this optional

chaining says okay well even if we do

have an auth header if it doesn't start

with bearer with a capital b and then

the space after bear then we're going to

return a 401 because it is not a

correctly formed

authorization header that starts with

bearer and then the token as it's

supposed to it looks like we left in a

console log from the last tutorial let's

go ahead and take that out where we were

just viewing the bearer token in the

console

and now after we decode

this token when we're verifying the jwt

we also want to set the roles here not

just the user on the request so let's

have request

dot roles and we'll set this equal to

decoded

and now we've got a different namespace

so it's dot

user info

dot roles and we need to make the same

change up here when we get the username

because now it's decoded dot user info

dot username

and now we've got the correct namespace

for both and we can save our verify jwt

middleware and now it's time to create

our new middleware i'm going to collapse

the open editors so we have a little

more room and in the same middleware

folder let's create a new file and let's

call this

verify roles.js

inside of verify roles we're going to

create middleware named verify roles

and it's going to accept

a lot of parameters if we want it to

it's however many roles we want to pass

in and the way we do that is with the

rest operator it looks just like the

spread operator but it lets us pass in

as many parameters as we wish and we're

just going to call them allowed

roles

now from there we need to go ahead and

have a middleware function and you know

that takes

a request response and next so what we

need to do and this allows us to pass in

the allowed roles by having this on the

outside but we need to return

a middleware function essentially an

anonymous function here with request

response

and next

and now inside of this function we'll

have everything that our middleware

would do so the first thing we need to

do is say if

we do not have a request which we should

because our verified jwt will come

before this

but let's go ahead and do that just to

be thorough and then let's use optional

chaining to say okay even if we do have

a request it needs to have roles

or

this should not be valid and if it's not

valid

we're just going to return a response

and send

the status

401 which is unauthorized now we need to

define a roles array let's keep that

lowercase camelcase actually rolls array

and set this equal to

the allowed roles that were passed in

now we're spreading those into a new

array here

now that we have this let's go ahead and

log this to the console these will be

the different roles that we're passing

in of course there will be the codes

associated with the roles but let's go

ahead and log roles array so when we go

ahead and test this we can see

everything that we expect to and we'll

be comparing this to the request dot

roles that we just set

inside of the verified jwt that will be

executed as middleware before the

verifies roles middleware

okay so we'll log both of those just so

we can see what's going on but now we

know

we have an array

of user roles that are coming from the

jwt

and then we have the roles that are

passed in that will be allowed and

that's what we're going to compare so

we're comparing arrays and i'm going to

define just a result here

and let's set this equal to request

dot

dot map which map creates a new array

and we'll have a role

and for each role essentially we'll

compare to the roles

array

and we'll see if the roles array

includes

the role that we're passing in and if it

does it will return true

that's what includes does and if not it

will return false it's a boolean so

we'll have a new array and we'll have a

true or false for every

thing that was in

the request role so

if we had three different roles here

we'll have possibly true true true or

true false true

who knows for sure but that's what we'll

have so we need to filter this array

and all we need is one true to know that

the role

can access

the route that we're

verifying so what we want to do then is

chain

find and we can just say for each value

the true and false in the new array that

was mapped

each value will check the value to see

if it's equal to true

and if it is

it will return if it finds a match it

will return the very first one it finds

or if it finds no matches then we won't

have a result and so that's how this

works i'm using two higher order

functions here essentially so we're

mapping over

the roles that are sent

from the jwt and they're assigned in the

verified jwt to request roles and we're

mapping those comparing them getting

true and false

results back to the roles array that

will be passed into this route so we'll

pass in

however many roles we want to this array

could possibly only have one role or it

might have three or four or however many

we're checking for or want to allow to

this route

so once we compare those and get all the

true false results we're just using find

to say hey find the first true

and if there is any truths it will be

good and if there's not it won't and

that's what we'll do next so we'll just

say if

there's no result

essentially we did not find a true

result we're going to return

and then we'll say res

send status

and again we'll send a 401 unauthorized

otherwise we'll just call next because

everything's good and we're ready to

move on and we're going to let the route

be accessed so let's save our middleware

and we'll know when it runs we'll see

the arrays that we're comparing

in the console and before i forget we

also need to add module dot exports

and set that equal to verify

roles and save

now let's collapse the middleware folder

and open up the routes folder and then

the api folder and let's go to our

employees.js that has the different

routes get post put and delete we have a

couple of imports to make here so

let's go ahead and define our

roles list

and set this equal to require

and now we need to go up

and up again and then we'll look in the

config folder and then we'll find our

roles list

and after that

we need to go ahead and define our

verify roles middleware

set this equal to

up a folder up another folder middleware

and now we're going to verify roles

and i'll save just because i've

completed the imports but now we need to

add this to the different routes now

let's just leave the get route open

because

any

one could access that or if we wanted to

put verify roles and at least verify

their user but they already have to have

the jwt because we required that ahead

of time so

they'll have to have the jwt to access

the git route so kind of the user is the

default but after that

in the post route let's put in

verify

roles

and now we can pass in

the different

roles list

values that we want to let access

this route so we'll type

roles underscore list and now dot

admin will work

remember

this is the key and then the code is the

value so admin is the key

and then we could also put in

roles underscore list dot

editor

and that makes sense because you could

have an editor that could post a new

value as well okay then i'm going to

copy the verify roles that we just added

here

and

it's like maybe i'll put a space here

and then input i'll do the same thing

and add the space but now in delete

let's say only

an admin can delete anything from our

database so we'll save that which gives

it just a little bit of a change so now

everyone can access the get route

but the post route should be limited to

any user that's an admin or an editor

the same for the put route but then the

delete route could only be used by an

admin i think we're ready to test this

out now so let's go ahead and open a new

terminal window you can do that from the

terminal menu or i'll just use control

and backtick i'm on windows and i'll

type npn

run

dev to get our dev server up and running

with our api

and then we'll test this out with

thunder client okay i'm going to drag

the terminal

window up just a little give it some

more room so we can see the console log

notices that we get and from there i'm

going to click on thunder client here on

the left if you don't have thunder

client installed you can get it through

the extension over here and then just

search for

under client

and there you see it

and now that you have it or once you

have it you'll be able to click on it

over here on the left circle with the

lightning bolt

and you can create collections and of

course we've done this in some previous

tutorials if you have followed along in

the series i've got an auth collection

here and the very first thing we'll need

to do is authenticate a user let's look

at which user we're going to

authenticate first let's just do dave

one remember

this user only has the user permissions

it does not have an editor

or an admin permission so i'll send

and i get the access token

i'll copy this access token

and now when i go to

the employees api and go to get

employees

i'll go to auth here

paste in the new access token and send

and everything is good but if i do this

for post if i'm in time within the 30

seconds it was given

and send i got a 401 unauthorized so

that means our verify rolls is working

as we look down here

we've got the two different arrays

logged to the console too so

this

is the array that has the roles that we

were looking for that we passed in 5150

is the admin 1984 is the editor but you

can see our user only had role 2001

which is just a user okay now let's go

back to my auth collection here and the

auth route and let's change

who we're getting a token for so now

this will be

walt 2 he is an editor

and

also a user but he is not an admin so we

can send this we get a new token i'll

copy the token

and now we can go back to the employees

api and we can post a new employee or we

should be able to we'll put in the new

token here

and send and yes we posted john doe so

he's now number three has the id of

three in the employees list but if we go

to the delete route

and go to auth i'll post in the same

token and attempt to delete

and oh we're out of time we got

forbidden so let me go ahead and try to

re-verify here

we once again got walt 2

we get a new token

and get that new token once again i

didn't copy it right the first time

there we go back to employees now we'll

attempt to delete i'll pass in the auth

token

and send and we got a 401 unauthorized

and that is because the role did not

verify now you can see you had to have

the 5150 code which is admin that was

passed into the route

but

walt 2 only had the 2001 and the 1984

code in his roles list okay once again

let's go back to the auth route now and

we will change to where we are

authorizing

walt one walt one should be an admin as

well as a user and an editor

and so we'll send that get a new token

and now we can go back to our employees

delete route that was just denied to

walt to

paste in this new token

and attempt to send the delete request

and employee id 3 is not found that's

because nodemon restarted i believe and

of course employee id 3 isn't in there

so let me go ahead and request another

token and we'll see if we can create id3

again quickly and then delete it on the

same so here's our new token for our

admin user

copy that go to the employees post route

paste in the auth and created now let's

go to delete

paste in the new auth and we deleted

with an okay so i just had to be quick

enough to beat the 30 seconds with that

token but here you can see the user

our walt one user had

2001 1984 and 5150 in his roles and

the api route needed the 5150 so when it

matched everything was good hey just a

quick note on testing with thunder

client and i want to point this out in

the controllers

and then under the auth controller but

when you're testing with thunder client

it honors the cookie setting for secure

true or not so if we were to set a

cookie and then use the refresh token

here you would need to remove

this or the cookie would not work with

thunder client however this is required

as i noted in a previous tutorial when

working with chrome so

just a note if you're testing the

refresh endpoint with a refresh cookie

you'll have to comment this part out or

at least take it out for testing

purposes with thunder client but then

when you work with chrome and in

production you both want that secure

true back in here when you create that

refresh token that is saved in a cookie

we did not use that today and the

refresh token does not store any

information about the user roles and it

shouldn't however just wanted to note

that for you in case you were testing

out that refresh token with thunder

client so there you have it we created

our verify roles middleware and you can

see

both of those that we've been logging to

the console i'll go ahead and delete

those now before i commit it to github

and get the console logs out of there

there's our verify roles middleware and

you of course saw how we applied it to

the routes in our api

for our employees and you can just pass

in

the different roles that you want to let

access

that given route

mongodb is the m in the mern stack it

represents the database in the stack the

front end application of the mirn stack

is handled by react along with nodejs

and express mongodb completes the

backend rest api

traditional sql databases are built in a

relational structure

related tables reference each other with

joins as data is queried these

relational tables also normalize the

data that means data is not duplicated

in the tables that's the dry principle

which stands for don't repeat yourself

and that's applied to the structure

however with no sql databases like

mongodb you can throw all of that out

mongodb stores data in collections the

individual records in the collections

are called documents the documents have

a key value structure and look a lot

like json a collection holds all of the

data about a user for example instead of

breaking it into related tables and

likewise duplicating and distributing

the data where deemed necessary in a

nosql structure is permitted

so why choose nosql databases and what

are the advantages of using mongodb

performance is key

the speed at which a collection is

queried is very fast

flexibility it's very easy to make

structural changes like adding a new

field without wreaking havoc in your

total structure it is much like adding a

new property to an object

scalability

nosql can support large databases with

high request rates at a very low latency

and finally usability as you'll see

today we can get up and running with

mongodb in the cloud very fast

let's get started by going to

mongodb.com

okay we're at

mongodb.com and i already have an

account so i'm going to choose sign in

if you don't have an account you'll want

to sign up for a free account so you can

just click try free i'm going to click

sign in

and then it will take me to a page that

probably uses my google id or allows me

to log in with an email address yes

there it is so you get those options i'm

going to log in with my google email

address or my google account

and then we'll meet back up after you

have your account or you've signed into

your account

okay i'm signed into my account and i'm

on the projects page where i can create

a new project and you see i already have

one project here now if you're not on

this page once you're signed in just

click the little leaf in the top left

and it says view the organization home

because that's where this is so once

you're there you'll want to create a new

project

and now you want to name the project i'm

just going to name this one

tuts short for tutorial and click next

and then it asks you to go ahead and set

permissions or members and it'll

probably assign that to your default

account to start out with as you can see

i have project owner right here so i'm

going to click create project with the

project created you can see i now have

tuts up here above database

deployments we need to build a database

and of course it gives you the big shiny

button right in the middle to do so so

please click that

and then it gives you choices and we're

just going to go with free today if you

want to get one that you pay for that's

fine i'm going to choose free over here

on the right

and then it will say create a shared

cluster

and right now i'm just going to keep all

the defaults so free shared it has aws

it has one of the usa

regions for me because i'm in the u.s

you may want to pick a different one if

you're not and maybe it already defaults

to something close to you

and then it just has these other default

settings and i'm going to go with all of

that even the default name here cluster

0 and click create cluster at the bottom

now it says new clusters take between 1

to 3 minutes to provision so i'll come

back when this is finished my cluster 0

has now been created and we're given

this screen so what we want to do is

click browse collections

we don't have any collections yet so we

get this and it says load a sample data

set or add my own data we're going to

choose add my own data

with that it asks for a database name

and a collection name so let's just call

this

company db

and then we can call the collection name

let's go with

employees and i'll just keep that all

lowercase companydb

is capital company and capitaldb at the

end and i'll click create

and with that has created our

companydb database and our empty

employees collection right here what we

should do now is concern ourselves with

database access so let's create a user

that can access

this new collection and database that we

have so create a database user we click

the big button that says add new

database user

and then it gives us password

certificate and all of that we'll just

stick with password

and it put in some old information for

me let's put in something different here

let me go with

tut once again

and then for a password

i'm just going to and we'll go ahead and

show whatever the password is i'll go

with

testing one two three kind of like a mic

check

okay so we've got tut testing two

testing123 i think we'll keep all of the

default options here and we want the

read and write to any database and of

course i'll come back later and

delete this user but for now

we'll use it for the tutorial and we'll

click add user

and once we have the user we need to go

back to our cluster so

let's click tuts

and that takes us back to our cluster

and it says we are deploying your

changes current action configuring

mongodb

so i'll give this just a second and then

we're going to click connect with the

configuration now complete let's go

ahead and click the connect button

it tells us we need to set up some

security this part is required and what

we're going to do is allow access from

anywhere we don't really know where

we're going to host our back end yet so

this is good for development right now

until we actually know what i p address

we had so let's just add in the zeros

and that means it's good from anywhere

we already created a user so now let's

click choose a connection method and

we're going to connect our application

this gives us a connection string and

this is what we want notice it's already

put in the tut user i created now

i'm going to have to put in the password

including getting rid of the

less than and greater than

around the password and then also i need

to replace my first database with the

companydb which was the name we gave the

database so i'm going to copy this

and we're ready to close out of this now

and open up visual studio code we're

going to start with the code repository

from the last tutorial in the nodejs and

express and now mongodb series but if

you don't have it you should be able to

easily follow along without it or you

can download or clone the starter source

code from the link that i'm providing in

the description below so let's get

started by going to our dot env file

and inside the dot env file it looks

like i need to go to the end of the line

and hit return so we have another line

i'm going to create

a database

underscore uri

and set it equal to our connection

string but now we just need to replace a

few things in the connection string and

i'm going to press alt z here i'm using

windows and it will wrap

the code in visual studio code it may be

different for you on mac or linux if you

have those okay so we're replacing the

password and if you remember i put in

testing lowercase

one two three

and then instead of my first database we

named the database

company

db

now we can save this file because we're

using the process.env

to pull this value out when we need it

to connect and speaking of dot e and v

we actually put it in about three

different files before and really we

could have just put it at the beginning

of the project it's not like when we

require other

things like the jwt here that need to go

in individual files as they're needed

this can just go at the beginning of the

server.js so i'm going to pull it out of

our middleware verify

dot jwt.js file and save that and i

believe it's in a couple of controllers

that we can remove it from as well but

in the server.js file i'm going to put

it at the very top you just want it in

there as soon as you can get it

and we'll save it and now i believe

let's check these controllers real quick

is it in the auth controller

yes it is we can remove that

and it's in one other controller if i

remember right

not

the logout controller

see if it's the refresh controller there

it is and we can remove it from that as

well and i think that will take care of

it so let's close out of the controllers

it didn't save the auth controller need

to do that too

okay close out of those and we're going

to do some work here in the server well

really before we do anything in the

server we need to go to package json

because we're going to install mongoose

and i'm going to press control and the

back tick you can also go to the

terminal window or menu to open a new

terminal window and here we need to

install the mongoose package so it's npm

i

mongoose and return now mongoose.js is a

library that makes working with

much easier kind of like you could

consider react makes working with

javascript easier than vanilla

javascript it's just a helpful library

so let's take a look at their page real

quick it's

mon goose there we go js.com

we bring up that page and you can see it

says an elegant mongodb object modeling

for node.js perfect exactly what we need

and it has some great documentation as

well so we can refer to this as we go

today we'll be working with a connection

let's go back to vs code and see if our

package installed it looks like it has

so let's check our dependencies and we

see mongoose listed right here on line

20 so we are ready to begin working with

mongoose so now let's go to the

server.js file and underneath

credentials let's go ahead and require

mongoose so we define const

mongoose and set it equal to

require and then we just bring in

mongoose

and save

now after that we need to go ahead and

create a connection configuration so as

you might guess we're going to do that

in our config folder that we have up

here so i'll highlight that and click

create new file and i'm going to call

this lowercase db and then uppercase

con so it's camelcase really db con

dot js now let's start this file by

requiring mongoose as well so we'll once

again bring in mongoose

and require

mongoose

and now we need to create a function

that we're going to export and let's

call it connect

db and set this equal to an async

function mongoose is async let's go try

and after try we'll have our catch

with an error block here

and we'll just

console.error and pass in the air

and then up above we need to go ahead

and try to connect a mongoose so how

we'll do that is a weight we've already

got a sink above and then we use

mongoose and we choose connect

and from there we need to bring in

that db uri that we defined back in our

dot env so we can just refer to process

dot

env dot

database underscore uri

and then there is an object

and what we need to do is pass in a

couple of options that will just prevent

warnings that we would get from mongodb

otherwise one is

use

unified if i spelled that right

topology and we set that to true

and the other one is use new

url parser and we'll set that to true as

well

and then we should be pretty much

finished except we once again need to do

module.exports as we have many times

before four functions we've created and

exported

and it is connect db and we can save the

file with our function created let's go

back to server.js now and we need to

import that so

say const connect db is going to equal

require

and then we need to go into config

and from there we need to pull in db con

and save and now let's go ahead and

connect to the db the very first thing

if it fails we don't want to listen for

any other connections anyway so this is

connect to mongodb and all we do is call

connect

db right here

and it's ready to connect however there

is one issue to address here so let's

scroll all the way down to where our app

listens for requests now we don't want

to listen for requests if we don't

connect and so

if our connection fails for whatever

reason we need to avoid doing this

and we can do that let's go back to the

documentation for mongoose and where we

had connections here in the

documentation we also have connection

events

and let's look we can listen for the

connected event

and there's also the open event which is

equivalent to connected so let's go back

to our code and use that

and we can do that with mongoose which

is why we required it for this file in

particular

and we'll have mongoose

dot

connection

and then we want wants instead of on

because we'll just listen for this event

one time

and we'll listen for the open event it's

a little shorter to type than connected

and now we'll have

an anonymous function and inside this we

can console log first

and inside there we'll just say

connected

to

mongodb

and after we've connected to mongodb

let's just go ahead and cut and paste in

our app listen

and we'll put it right there

and now we're only going to listen for

requests

if we have successfully connected

because that is when the open event will

be emitted by the connection and so then

our console will let us know we've

connected to mongodb

and we're listening for requests on

whatever port and of course here in

development we are defaulting to port

3500 as set at the top okay all of that

said i've left the terminal window open

let's go ahead and type npm

run dev

and i'll drag it up so we have a little

more room and let's see if we connect

and we're connected to mongodb

and the server is running on port 3500.

okay in the next tutorial we'll create

schemas and data models with mongoose

and relate that back to our mongodb

collections

in the previous tutorial we went over

what mongodb is and we used the mongoose

js library to connect our app to mongodb

today we're going to create mongoose

schemas and data models that will allow

us to perform crud operations on our

mongodb data collections we're going to

start with the code repository from the

last tutorial

but if you don't have it you can

download or clone the starter source

code from the link i've provided in the

description below let's get started

today at

mongoosejs.com and from there we're

going to click read the docs and it

instantly takes us to the schemas in the

docs and that is because as you see on

the page all highlighted it says

everything in mongoose starts with a

schema

each schema maps to a mongodb collection

and defines the shape of the documents

within that collection so you can see

why they're very important and here you

see an example schema they have a blog

schema and they're declaring data types

for the different fields inside of the

documents that will be created with the

data model

and they also have some options here

such as date they're not just saying

it's a string for the body they're also

saying it's going to be a date they can

have default data and there's other

options available as well and if we

scroll down just a little bit further

you can see the permitted schema types

and here we have string number date

buffer boolean and a few others object

id is an important one that will be

created automatically for us so we will

not have to specify an id as you don't

see one specified in their example

either so now let's go to visual studio

code and get started creating our

schemas for both our employees data and

our users data okay i'm in visual studio

code and i've got the source code from

the last tutorial it's linked to below

as the starter source code if you want

to download or clone that right now

we're going to go to the model folder

and we've got

employees.json and users.json because we

were just using the nodejs file system

to write to both of these files and

we're going to get rid of that

eventually here as we replace everything

with mongodb for now just keep those

files and we'll create

new files for our schemas and the first

one will be called employee

and i'll spell that with a capital e and

then just js and that's a naming

standard it won't really have an impact

if you don't use the capital e however

it's pretty much the consistent standard

that i've seen so first let's define

mongoose

and require that

there we go

and now that we've got mongoose pulled

in we also need

a schema with a capital s and that's

going to equal

mongoose dot

schema once again with a capital s

now that we have that we can define our

schema and let's call this

employee

schema and that can use camel case

we'll set this equal to a new

schema once again capital s on schema

and now we can map out our data and if

you remember our employee's data was

very simple it just had a first name and

a last name so that's what we'll declare

here now remember

uh we will automatically have an object

id created for us so we don't need an id

field here

and now we can say first name is type

string and then we can also say it's

required and that accepts a boolean so

we'll say true that is absolutely

required and then we'll do the same for

last name and know what we could just

copy this down

shift alt and the down arrow for me on

windows and visual studio code

and make that the last name

and let's get rid of the comma there and

that's basically our schema very simple

we've got two string fields first name

and last name now at the end of the file

we need module dot exports

and we're going to set this equal to

mongoose

dot model

now we're creating a data model right

here and we'll set this equal to

employee

and that is uppercase

first letter and then not plural once

again just like the name of the file

employee

and then we'll use the employee schema

now by default

mongoose when it creates this model

will set this to lowercase and plural so

it will look for an employee's

collection in mongodb

and the employees collection will be all

lower case and once again it will be

plural and we can see that if we go back

to the docs and we go to the models link

in the docs there we go

it says this in bold right here mongoose

automatically looks for the plural

lowercase version

of your model name so in the example

they give they have the word tank they

defined here for the model and they

passed in

the string tank with the capital t

but it says for the example above the

model tank is for the tanks collection

in the mongodb database and that's all

lowercase and plural all right back to

visual studio code let's save this file

and let's go ahead and create a user

schema as well now our user data had

just a little more to it so this will be

a little more interesting than just the

first name and last name that we had in

the employee schema i'm just going to

copy these imports here because we need

the exact same thing at the beginning of

basically every schema we create

and now i'm going to say user

schema camel case

this is equal to new schema capital s on

schema

and now we have a username in our data

and this is kind of like the first name

last name in the previous schema it's

type

string

and then required

is true

after the username

we have roles

now the roles data is a little bit

different so we had

user which was a possible role

and now let's specify

some data or some details about the user

role here inside of an object and now we

can set this to type

number

and we can put a default value so if not

specified

any user that's created will

automatically be assigned the value of

2001 and that was our basic user value

that we had previously

applied

and then the next role was editor

and that had a number

and then the next role was admin and

that had a number notice we're not

providing default values and we're not

even saying they're required not

everybody's an editor not everybody's an

admin so these will only be added to the

data that we decide to add them to as an

admin could make those decisions okay

now that we've defined the roles let's

put in the password field

this is much like we had before type

will be string

and required

will be true

and then after that if you remember

we also store a refresh token

and when a user is created they don't

have a refresh token but after they're

authenticated they get one so this is a

string

but it does not have a default value and

it's not required because it's not

always there

so now we've created our schema

for our users

and let's go ahead and export this

we'll say

module.exports

set it equal to

mongoose.model so we're creating a data

model

and this will be user singular and then

mongoose will once again look for users

all lowercase plural

but we'll match our file name so user

and then we'll use the user schema that

we just created

okay we've created two basic schemas for

our data user and employee and then we

created models to be associated with

those let's go ahead and implement the

user schema and model

and let's attach that to one of our

controllers

and let's do it with the register

controller first that makes sense where

we'd create a new user and now you'll

see how much easier mongoose makes

interacting with the mongodb collection

than it is to write all of this stuff

that we have been doing with the file

system module and interacting with json

files so let's simplify this file and

just switch it over to using mongodb so

we're going to get rid of the user db

that we had up here

and let's just bring in

the user model so i'll define user with

a capital u and set this equal to

require

and now we need to go up out of the

controller folder and into the model

folder

and then we need

the user model

after we do that whoa i lost something

there

user model

there we go after we do that we can

really get rid of the fs promises and

path we're not going to be right into a

file anymore or need that we do still

need to keep the bcrypt import and now

let's start making changes as we handle

the new user here

and it'll start out the same we need the

user and password to come in from the

request and if we don't have those we're

going to send the same information back

that's a bad request

but now when we check for duplicates

we're interacting with a different

database so now this will change just a

little

and we'll still define duplicate but how

we get the duplicate is completely

different

notice we already have handled a user as

an async function so right here we're

going to await

and then use our user model

and call

find one and now we'll pass in some

information here we're looking for a

username that matches

the user that we defined from our

request

and after that we need to call

exec here at the end now not every

mongoose method needs that on the data

model but this one in particular does

and that is because we could pass in a

callback afterwards like a error result

for example but if you don't do that and

you're using the async a weight

pattern here

then you need to put exec at the end of

find one and you can check that in the

documentation under find one to

reference

if you need that or when you use any

method that you're not sure of and

you're using async await you should

check that but this is going to return

any user that matches the user that was

passed in and of course we don't want a

duplicate so this is the same if there

is a duplicate we need to send this 409

conflict there

after that

we need to handle the password in the

same way but after the password is

created our code is going to get much

simpler let's go ahead and keep the new

user even though we will define this a

little bit differently

but we're not going to use this or the

fs promises we don't need that console

log there let's go ahead and keep the

status 201 though because that is what

we want to send when we create the new

user with mongoose we can create and

store so i'll put create and store the

new user all at once and so what we'll

do

instead of defining a new user here i'm

going to define

result

and i'm going to set result equal to

a weight

then our user model

dot

create

and now we are creating a new user and

let's look inside to see what we're

passing into the create to make sure we

have everything we want or we don't want

what we do want the username

and then we don't really need the roles

here because remember we have the

default data in our schema so it will be

added automatically so we can remove

that and then we pass the password and

an object id will be created

automatically also so this is all we

really need to send

through our data model

and the username and password

will be sent by us and then a role will

automatically be created a roll value

and an id

for the document will also be created

now result will return the record that

is created so we could go ahead and log

the result just to view the record in

the console and i'll save that i do want

to discuss a couple of other ways a

record could be created that you might

see somewhere i prefer to do it this way

because it happens all at once just the

user create and it is created and we get

the result back but you might also see

something like

const

new user equals and then a new user with

the model and then of course you could

set

new user dot i'm sorry user name there

we go and set that equal to whatever

data you had and use uh dot notation

that way to set the values and at the

end of all of that you would want to

save so then you would say const result

equals and then you would have your

await

new user

and you would call save and that would

also work however that's just a little

bit longer process

you might also see something like the

new user being created and then passing

that data in like we did inside of user

create so instead of using dot notation

you might see something like

new user

equals

well here we define new user but then

it's equal to a new user and you're

passing in the values inside of the

parentheses there and then you would

still need to have the result equals

await new user.save after you did this

and so this happens

all at once when i use user create and

if i do it this other way and create a

new user then you have to have another

line to actually save the new user so i

prefer the user.create

let's go ahead and save this

now we're ready to test our register

controller route

so let's open up a terminal you can do

that from the terminal menu or press

control back tick at least i can on

windows and now i'm going to type npm

run

dev

and that should start up nodemon and

start our api server here just on

localhost port 3500. we've got our

message connected to mongodb

server's running on port 3500. i'm going

to use thunderclient to test everything

out like i have in some previous

tutorials if you don't have it you can

install thunder client as an extension

and then it's right here after you have

on the left

i'll click that i've got some

collections and under auth i should have

a registration route to test and now i'm

going to hide the left-hand

menu over here because it looks much

better and it's easier to read when it's

the full screen so here's the register

route

see what we're sending in the body okay

i've got a user named steve1 to create

and then it's got a password and that's

really all we need to send let's see if

the register route works

new user steve one created and here's

our object in the console so now we can

see what we've got

username steve1 the role was created

with user 2001 we've got our encrypted

password and we've got a new object id

and then notice this other field as well

that's always added the two underscores

and the v and the zero you should always

see that as well if you're curious the v

is the version key and it keeps track of

this and we can also increment this

manually if we want to okay now that we

created steve one let's create another

user and i'm going to go back to my wall

one that was an admin previously so

let's create him as well

and now new user walt one was created

and if we look here in the console we

can also see

that

walt one was created down here and

here's his information now let's go to

mongodb

and inside of mongodb

we can check

our company db here and we should be

able to refresh

and now we have a user's collection as

well and you can see it has two

documents so let's look at the user's

collection all right we load the

documents up and here are the

two records or we could call them

documents really i'm used to saying

records with sql this is a nosql

database and it has collections instead

of tables and it has

documents instead of records so in

either one of these we can expand

the object and see our user 2001 that

was created so we want to make walt an

editor and an admin so inside of mongodb

here we're mongodb.com and logged back

into our account and we're looking at

our collection

inside of the companydb database that

was created and we'd created the

employees collection before

but we had not created users so when we

created the first user it also created

the users collection which is

interesting but after that

we want to edit walt here and we can do

that right inside of

mongodb.com so let's edit and now let's

go ahead and add

another role add field after user

and we'll put in editor and the value

for the editor

was 1984. okay now we've completed that

now let's add field after editor

and we'll add

admin

and the value for the admin was 51.50 if

i remember correctly

and so now we've gone ahead and changed

that information but we still need to

click update here

to

update the document now the document is

updated and walt

has all three roles in his document oh

but notice what happened here and you

want to catch this if you do it because

i certainly just made the mistake this

was entered as a string and this should

be numeric data so we want to get rid of

that we don't really need to remove that

we need to change the data type over

here on the right notice how

user 2001 is int 32 so we want to choose

that type here on the right

and make sure

we have the right data type as we make

changes here on mongodb.com to any given

document okay those changes have been

made now let's update and now we have

the correct data type in waltz roles

2001 1984 and 5150. okay going back to

vs code

and i'll close out of thunder client

and close out of the terminal as well

but let's go ahead and show the file

tree because

we have changes to make in the

controllers we need to go ahead and

implement our user model instead of the

json file we've been using in the

refresh token controller the logout

controller and the auth controller and

then we need to implement the employee

model in the employees controller and

change how some of this works just like

we did in the register controller and

that's what we'll be doing in the next

tutorial but my challenge to you is

before then go ahead and make the

changes on your own and then compare to

the tutorial that i release that makes

the same changes

today we're going to apply the user and

employee models to the remaining api

routes and update the asynchronous crud

operations accordingly and before we

finish i'll show you an easy way to

deploy your rest api to the web we're

going to start with the code from the

last tutorial if you don't have it i

have a link to the starter source code

in the description below let's get

started we're looking at the user schema

and then of course we create a model

here at the bottom that's where we're

starting and we applied it to the

register controller near the end of the

last tutorial

and you can see we imported in the user

model and this replaced what we had

previously in the tutorial series which

were

json files now we're using mongodb

and we're interacting with mongodb by

using the mongoose schemas and models

that we've created so now let's apply

our user model to the next route and

instead of register let's just move up

one and go to the refresh token

controller okay you saw i copied the

user model import from the register

controller file and i'm going to paste

that right over the user's db that we

had previously defined to interact with

the json file so now we're bringing in

the user model and now we can update the

handle refresh token function we'll

start out the same here where we define

the cookie

and of course get the jwt from the

cookie if it exists but then as far as

checking to find a user we have to do

that differently and let's go back to

that register controller for just a

second because we did a very similar

thing we used user dot find one and we

passed in the name of the user well this

time we won't have the username but

besides that it will be very similar so

let's highlight all of this where we

were finding the refresh token

inside of the json and let's paste in

our user find one but now instead of the

username we can just put refresh token

here and that's because

the property name and the value name or

the

variable name are the same so instead of

refresh token colon refresh token we can

just put refresh token there we still

need

the exec here to execute and that is

because we're using async a weight and

that means we need to put async up here

above which i almost forgot so let's put

async up here by handle refresh token

and make this an async function and

we'll use await here and then we search

for the refresh token

inside of a document within the user

collection after that everything

essentially remains the same because we

have defined the found user if we found

the refresh token or not and of course

if not it's a 403 forbidden but after

that we're using the same definitions as

before so there's nothing else to change

in the refresh token route so we can

save the file

and move on to the logout controller

okay we'll start the same in the logout

controller and we will not need the fs

promises or path either so we can just

highlight all of that and paste our

that's not the user model is it so let's

change that control z to undo that i'll

go back here to the register controller

where i copied

the user model import before i'll copy

that again

back to the log out controller

highlight all of that and paste because

that's what we need is the user model

imported after that we already have the

note here on client also delete the

access token again this is the log out

route and that's fine

the next three lines just as before

are fine and then we need to say is the

refresh token in the database well that

sounds familiar that's just like we used

in the refresh token controller so we

come back to the refresh token

controller i'll scroll up where we had

our await user find one and passed in

the refresh token

copy that come back to the logout this

is already an async function that's good

so now we can once again define the fine

found user

in the same way

and now after that this remains the same

but now this gets much simpler where we

delete the refresh token we're no longer

interacting with any of this json here

so let's just highlight all of this

and delete and we can make a few changes

we can say found user

dot refresh token

and we can erase it simply by setting it

to an empty string

and then we can set a result and we'll

set that equal to await

found user

dot save and that will save our changes

back to our mongodb document that is

stored in the user collection and after

we do that we could go ahead and log the

result if we'd like to see that because

that will return

the newly updated information

and that's just for our purposes there

you would of course delete that before

you put it in production and that's all

the changes so we can save that and

again

remember that found user this is a

document now that we have found if it

existed and therefore we're able to

update that document with the save okay

i'll scroll back up to the top and i'm

going to copy that user model import one

more time because we need it in the auth

controller

once again i'll highlight the user's db

that we previously had and paste in the

user model instead i'm going to go ahead

and delete this line between bcrypt and

jwt we need both of those but we can go

ahead and once again delete fs promises

and path which we should no longer need

these first two lines are the same we'll

keep both of them but then once again

with found user i think you see the

pattern now now we're back to looking at

a user name though so we can take this

and go back to the register controller

where we had the user name with find one

and copy that line go back to the auth

controller and then we can paste that in

as we find the user

and save because the next line is fine

as well and then

the password is evaluated and we're not

changing anything about that and really

we won't make any changes until we come

down here once again to where we were

interacting with the file

and we will be saving the refresh token

with the current user so once again we

can delete everything we had here down

to the response cookie

and let's leave a blank line in between

and then we can once again say found

user which is our document that we have

found

and set the refresh token

we're going to set that equal to

the refresh token that we now have here

in the auth controller

and then let's define result again

and let's set result equal to await

found user

dot save and that will update the

document back in mongodb and let's go

ahead and log that result again as well

so that should also look very familiar

and that completes the auth controller

so i know we tested the register

controller the register route in the

last tutorial but now we'll want to go

back and test all the rest of these so

we've got the refresh token route we've

got a logout route and of course we've

got the auth route as well so now let's

test those once again with thunderclient

if you don't have thunderclient

installed it's an extension for visual

studio code

and you get that right here under

extensions and search for thunder client

and then you'll have it on the left

and this is thunder client it allows you

to save collections which i've already

saved to match up to this but before we

can test it we actually need to start

our dev server i'm going to press

control back tick you could also go to

the terminal menu at the top and choose

a new terminal window that way then we

type npm run dev to launch our dev

server

and we should be running on 3500 and

connected to mongodb here in a second

when it gives us our information and

there we see both connected to mongodb

server running on port 3500 so it's now

ready to test so i've saved a collection

named auth and then here we have

different

routes if i can see which route we have

here looks like this is the register

route let's go ahead and try that i'm

going to click thunder client to hide

the left hand

side so we can see better and let's look

at the body to see what we're going to

register we're going to register a user

wall one with the password i believe

he's already registered so we should get

a 409 conflict back let's see what we

get

that's exactly right 409 conflicts so

let's change this

to tom one i don't believe i have tom

one in my collection of users so now

we'll send this

and 201 created so we have a new user

created our register route is working

now let's go back to thunder client and

look at the other routes that was the

register route now that we've registered

let's test the auth route now let's see

who we want to authorize well i believe

walt one was already created we

confirmed that so we can just send in

this information to authorize and we

send it in and we've got a new access

token back

and everything is okay he is authorized

and of course you see down here

we're logging these responses that we're

also getting back these console log

statements that had the result

and that's what we see here is the user

that we've pulled in is walt one okay

i'm going to pull this down and i'm

going to authorize again because if you

remember right

we only get an access token the way we

have it set that works for about 30

seconds but really i guess we're not

testing that so wait a minute when we're

not too worried about that because we're

going to test either the log out or

refresh token route let's test that

refresh token route that i have in a

separate collection

and so with the refresh token we're

sending a cookie it says no cookies

available but i think we have a cookie

let's try it out

401 unauthorized we did not get a cookie

i think we're running into our secure

site error where thunder client doesn't

let us test even though we need that

secure site option in there

for chrome so let's take this out

temporarily i'm in the auth controller

as we issue the refresh token

let's take this out and put it in a

comment near the end in production once

again you would want this back in there

however we can't test it with thunder

client with it in there so let's go

ahead and save now

and once we've got the server updated

let's go ahead and run the auth again

and then we should be able to test the

refresh and now we're up and running

connected to mongodb server running on

port 3500 let's try this again in

thunder client we'll go to the auth

first

hide this over here i'll go ahead and

log

and we've got a cookie let's go to the

refresh now

and come back before we were

unauthorized but let's see if this works

now and yes it does

our cookie works you just have to take

that secure out while testing with

thunder client so the refresh route is

working we have tested the register

route we have tested the auth route

we've tested the refresh route what is

left is the log out route so once again

we'll probably need a fresh login to

ensure we are logging out correctly so

let's go to the auth

and now let's see who we're logging in

it looks like walt won that's fine

we'll send that and now let's go to the

log out route

and

come over here in thunder client and it

looks like we actually don't need to

send anything it's just going to log out

the refresh token that's right

so we'll just send

and 204 no content that's fine we didn't

expect any content to come back but we

can see down here because we logged the

result

we logged out

there's the route we went ahead and

logged out and we logged out our user

walt 1 and we set the refresh token to

an empty string okay those updates using

the user model were not too bad at all

let's go back to the file and what we

want to do now is update the employees

controller

with the employee model and this will be

just a little bit more work than what we

had previously had but we'll start out

once again

by eliminating the json file and let's

go ahead and import our employee model

so we'll have const

employee and we'll set that equal to

require

and then we need to go up one folder

find the model folder and then employee

that is correct

and now let's look at our get all

employees route well before we just grab

the json and return that now this will

be just a little bit more

to do with

mongodb and of course this will be an

async operation so let's remove this

response json for now

and we'll define employees

and let's set this equal to

await

employee.find and by calling find like

this it will return all of the employees

then we can say if

there are no employees

we're going to return and then we'll

send a response

with a status 204 which is no content

and then

json and we'll send a message here

and in our json message we'll just say

it's a string no employees

found and after that we'll assume we do

have employees if we've made it this far

so we'll say response.json

and we'll send the employees and i can

see i've got an error i put brackets

instead of curly braces

go ahead and eliminate that bracket and

replace this one as well and we should

be good so let's go ahead and save this

now let's look at the create new

employee function which will also be

async so let's start here

and with that

we can probably go ahead and change

quite a few things that we have in here

so i'm just going to highlight all of

this

and remove it

and after that we'll start out with an

if statement but different than we have

below this will be if a request and now

we can use optional chaining to say as a

body

and then if it has a first name because

we need all of that

or

we can say the same thing

about the last name essentially we're

saying if there is no first name or last

name

and we would expect the request to have

a body but for some reason

if it doesn't we'll catch that as well

so if we don't have any of those

let's go ahead and send a response here

and we'll return

response dot status and this would be a

400 because it would be a bad request

there's json curly braces this time

message

and our message will be first

and last names

are required and you can see we had

something very similar below but it was

just a little different than that so now

let's eliminate that as well let's just

go ahead and delete these lines too and

we'll start over just a little bit and

put an extra line there and we'll do a

try catch block

and of course we have the catch after

there's our error and if we catch an

error let's just console

error the

error okay but in the try block

now let's define a result

and set this equal to

a weight

use our employee model and now we create

we'll create a record here

and we'll say

first name

is request.body.firstname

and lastname would be much the same

pattern

last request.body.lastname

and i'll put my semicolon here and save

but we still need to send a response so

we'll say response.json

oh let's put a status first

and the status here would be a 201 which

stands for created

and then we'll send the result back with

the record that we have created okay

let's scroll down now and look at the

update employee once again it will be an

async function

and after that we'll start out a little

differently so let's go ahead and delete

and

well we don't need to delete that line

let's just delete the top line to begin

with okay so we'll start out with if and

once again

request and let's use optional chaining

body and now we're looking for

an id

and if we don't have the id we'll

return response status

400

and after that we can just give a

message in json

and let's see if it's the same message

that we have below

not quite the same so here let's add a

little message different and we'll say

message

an id

parameter is required

okay so we've confirmed we now have an

id if we make it to the next spot

and here we can define our employee

so we'll say const

employee and set this equal to

a weight call our employee model and

we'll use find one here

and now remember mongodb uses an

underscore id it automatically generates

that and we're going to compare that to

request.body.id that is passed in as a

parameter

and after that we need to call the exec

at the end to call that function into

action now let's go ahead and delete the

next line here and we can say if there's

no employee

return status let's change this to a 204

because it's not really a bad request at

this point it just means that they

requested an id that doesn't exist they

might have

issued the request properly but now

let's say

something just a little different we'll

say no employee matches

and id and now let's get rid of this at

the end and get rid of the not found

part no employee matches whatever id was

passed in there

okay so we're sending our status 204

we'll save that much now let's look at

this if the request dot body and let's

go ahead and optionally chain

first name

and last name

and then we can say employee first name

equals the request.body first name and

last name is the same that's fine

so we're just optionally chaining that's

all we change there that's different

than we had before and now this gets

much simpler here we're not sorting any

json data or

creating new ids or anything there so

let's remove all of that and we'll just

say const

result equals

a weight

employee notice this is the employee

document we've created or we've found

actually we didn't create it's the

employee here not the employee model but

employee dot save

and now we've saved any changes we've

made to this employee document and then

instead of data employees

we'll just send the result we've defined

here

and save and that is our update employee

function okay let's scroll up and take a

look at delete employee which should

also get a little simpler but we're

going to start out much like we did

before so we'll say if there is no

request and will optionally chain

body and then we'll optionally chain the

id

and we're going to return response dot

status

400

and that should also be json

and here we'll have a message

and our json will say

employee

id required

and put the semicolon there and now we

need to define our employee again which

would be much the same as we had before

really it's the find one with the body

id so let's just scroll up here and copy

exactly what we had before

and come down

and here we have defined the employee id

again and so then our

employee not found will probably be the

same as well so we can copy that

and come down here as well and just copy

this over and paste

and then after that we will not be

filtering so let's just remove these

lines here once again

and we'll say const

result

equals

await employee dot delete one now

instead of find one

and here once again this will be

underscore id and then it will be the

request dot body dot id that was passed

in

we do not need an exec after delete one

and then we will put in

the result and if you're wondering why

we don't need the exec here it's just

all based on the documents so once again

look at mongoosejs.com

and those docs and you'll see which

different methods you need to put that

after and which ones you don't and

finally let's check the get employee

route as well and we need to put in a

check as we had before with the others

let's check the request if there's no

request

dot

params this time and then of course

we're looking for an id once again

and we have a similar message at the end

so let's just copy this over

and paste it in because that is required

and now we need to find an employee

again so we can copy the same line as

we've defined the employee before

and we'll come back down here and set

employee equal to the find one statement

if we don't find the employee well

that's a repeat of this i'll just copy

this return line here and paste it in

here

and then we're already set because we

just want to return the employee as we

were before as this is the get employee

route or handler just for the one

employee and of course we're expecting

that id parameter to be sent in so let's

save that and we have completed

our async

functions let's put async with that as

well and if we didn't with the others it

looks like i also forgot to do that with

the delete employee let me check the

rest

we need to have all of these functions

as async functions and they complete the

different crud operations create read

update and delete

for the employees collection before we

test the routes there is one error to

fix notice i was using params as we're

using a git route to pull that in but i

put request body dot id

in the function and this needs to be

[Music]

params.id

to access that value that we get from

the url in the route okay so now that we

have fixed this and we're now using

params let's test the routes and we need

a jwt to be authorized so let's go ahead

and use the auth route you might want to

change your code to timeout or for a

longer timeout duration than 30 seconds

mine is set to 30 seconds so i've got to

be a little fast to test these reps but

let's go ahead and get authorized

now we've got a new access token

we can jump back over here i'll open the

employees routes i want to get all

employees

and now for the authorization i need to

paste in the new token and we get our

one employee walt walters

i'm going to copy his id

open the terminal window

and just paste his id down there because

i'm going to need it to test the

individual get employee route

so we'll come back now and get

authorized once again

collapse the employees api

routes and check the authorization get a

new access token

once we've got the new access token

go back to the employees api go to the

get an employee route an individual

employee

and

paste that token in here and i need the

id to put in the url

i'll paste that in and send

and we get walt walters back once again

now that we're using the

request.params.id for this route because

the user id is read directly from the

url as it is a get request okay let's

get authorized once again and then we'll

come back and test the post

here is the auth route again we'll send

get a new token

back to thunder client open the

employees apis

look at the posted employee

here's the new

auth paste that in look at the body

we've already got walt walters let's

change this to dave

walters is good now we have dave walters

as an employee that was created a status

201 which is created

one more authorization to go so we can

test the put i guess two more and then

the delete as well

so let's go here and authorize once

again

new access token

come back to the put route

and let's see what we need here let's

put in the access token

and in the body oh we need to specify

the id once again well let's and we

change a first name to david

let's go back and i believe in the get

employee route i still have that id that

we used before

oh and it's still down here in the node

terminal as well so we can pull it out

of there so let's reauthorize

new access token

we will come back to the employees

use put

and for put we need to put in the new

access token

and then in the body we need the

employee id so i'm going to paste that

in here and

change walt to david

and now we have david walters and of

course there's already a dave walters as

well

so the put route works and now we want

to delete and of course we'll delete

this same user that we still have the id

handy for

so let's reauthorize one more time

get a new access token

we have the new access token

copy that go to the employees routes

delete an employee

paste in our new access token and in the

body we once again need the employee id

we paste in that id

and

we get returned the employee that was

deleted so david walters is no longer in

our collection but it was returned

by the delete route

as a confirmation that this employee was

deleted okay so from here what you

should do

is go ahead and

create a users js in the routes

and then api folder and allow some user

information to be requested maybe get

all users and maybe delete users and set

that up so it can be accessed in the

route by admin only such as

roleslist.admin because that's the users

and i'll let you do that on your own but

i will put it in the completed

repository that i will post the link

below so there'll be a link to the

starter code and then a link to the

completed code

as well but before i go

i want to show you how you can easily

launch a repository

and if that repository create or has a

node application like this rest api

it will easily be deployed okay there

are several places on the web where you

can host your node project and even a

rest api using express in like

we've created i'm going to show you one

of the easiest ways to deploy

a project like this and we're going to

deploy to glitch.com so i'm going to put

in another bold statement here and say

well not start let's just say

deploy by

clicking the

button

above

okay now that we've put that in i'm

going to copy and paste some code but

i'm going to just change which project

it was for so

this code will put a button on the

readme of the repository that i share to

glit or not to glitch to github

and then when the button is clicked it

will launch

on glitch so here we have to put in the

name of the current project and so i'm

put

async crud i believe i named this

project

and i'll save

and we can verify here by i'll go back

and let's see i named this async

crud that is correct

so

i'll open up the terminal window and

i'll push my changes to github that i've

already initialized repository so i'll

add the file

and i'll commit

messages updated

readme

and i'll push to

github and i need

a passphrase set up with mine and there

we go i've pushed that to github and so

now if we go back

and look at the readme

for this repository there should be a

button that's available and it says

remix this

and that will allow you to go ahead and

launch this application on glitch so

let's go ahead and do that i'll just

click the button it takes just a minute

to load the project

and it will be up and running except for

one thing and that one thing

is the values that we

have decided to put in our dot env

remember the dot e and v file should be

listed in your git ignore so it is not

here and notice the remix button is much

larger once it gets to glitch that's

interesting

okay so

once again looking at the get ignore you

should have your enb file here so the

secrets that you have stored in the dot

enb

need to go in the dot e and b that is

provided here at glitch

and you can of course click this to

learn how to use environment variables

we've already talked about that so you

can add a variable and here is where you

would type like

access

token

secret i believe is what we named one of

ours and then you would paste in your

value for that you would do the same for

the refresh token secret and you would

also want to do the same

for the

string you put in the connection string

that we used for mongoose and mongodb

but this is just an example to show you

how you can go ahead and launch that so

what i'm going to do is leave that

button

in the readme and i'll put a little

extra note in the readme saying remember

to add your own values in the dot env

because you can click that button

right there in my repository

and from there you can bring back up

this project

in glitch and if you create an account a

glitch you can save it there as well so

that will help you launch any future

node application you might create

and this would allow you to put a button

in your repositories and launch them as

well and i think you'll like working

with glitch also i use it for several

things and i should add that once you're

on glitch and you have your project

launched

it will give it a name like this and

then you'll have your live project you

can click change url here and you'll see

the url for your project so that would

be the url for your api

so that is what you would want to go to

for your api and then the

end points would go of course after this

if you're trying to pull up any specific

endpoint so we have covered a lot in

this series and of course there is much

more depth you could go into as you dive

into the docs but i feel like we've

covered the create read update and

delete

for and mongodb we've built a full

rest api

with node and express and we have added

user authentication we have talked about

authorization and

json web tokens as well to protect those

routes so if we talk about next steps

you would want to take what we have

built

and what we have built here on the back

end using express and node could

be combined with react

for the mern stack so if you haven't

learned react you want to check out my

nine hour beginners tutorial for that

and you can combine that knowledge with

this back end course knowledge to

complete the mern stack however you

could also

add whichever front-end technology you

wanted to this back end with

express and node for whatever

application you wanted to create

remember to keep striving for progress

over perfection and a little progress

every day will go a very long way please

give this video a like if it's helped

you and thank you for watching and

subscribing you're helping my channel

grow have a great day and let's write

more code together very soon

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.