Build a Custom URL Shortener Service #matchurl

Build a Custom URL Shortener Service #matchurl

08.Jun.2021


this video is sponsored by dev Mountain
if you're interested in learning web
development iOS or UX design dev
Mountain is a 12-week design and
development boot camp intended to get
you a full-time position in the industry
to learn more visit dev mountain comm or
click the link in the description below
hey what's going on guys so in this
project we're gonna be building a URL
shortener service so I'm sure that most
of you have heard of bitly and some of
these other URL shorteners where we can
take a very long link such as this 
amazon link right here and if we put
this in here and click shorten it gives
us a much much shorter link that has
this the domain part of it and then it
has this code and if I click it it goes
to that same page so what we're gonna do
is build a service that does this we're
not going to build the user interface or
anything like that I'm actually saving
that for a course possibly might view
j/s course we'll have the UI we'll have
users that can log in and create short
links but in this video we're gonna
build the the API basically so that we
can get this functionality we can send a
long URL and get back a short URL that
will actually work and we're going to be
using a database because we need to
store the the long URL the short URL and
the code which is basically this part
here ok so I'm using MongoDB for that
we're gonna use MongoDB Atlas which is
the cloud version but if you want to use
a local MongoDB instance you can do that
as well so I'm just going to log into
MongoDB right here
I think that's it no it's not it okay so
basically if you're new to MongoDB you
can lock you can create an account for
free you can log in and it allows you to
create a cluster you need to add a user
I already have a user you can see if I
click connect and I click connect to
your application I get this string right
here that has my username and then I
just need to put my password in so we
can use this in our application to
connect to our database all right so
that's all set for now so I'm going to
jump into a terminal and we're just I'm
starting this from absolute scratch I
just have an empty folder here and I'm
gonna go ahead and just open up vs code
okay so I just have a folder called URL
shortener service and I'm going to I'm
gonna use my my standard terminal here
as opposed to my integrated terminal so
let's do an NPM NIT and just add on -
why and that's gonna create a package
Jason and I know a lot of you guys know
some of this stuff but I'm still gonna
explain it for people that don't
so package Jason is just manifest with
some information here it also holds any
dependencies or any packages that we
install and there's quite a few we need
to install so I'm gonna clear this up
here and let's do a NPM install Express
okay so expresses the web framework
we'll be using to create our routes and
stuff we're going to use node config or
config which is just a package that
allows us to have global variables we're
gonna be using Mongoose which is an
abstract basically like an abstraction
for our database so that we can easily
interact with MongoDB we're gonna use a
package called short ID to generate the
URL code and we're going to use valid -
URL to validate the URLs that are sent
that are sent to the API okay so those
are the regular dependencies and now I'm
just going to go ahead and npm install
with a - uppercase D so I'm
installing a dev dependency and I want
to install node Mon which will
constantly monitor our applications so
that we don't have to keep reloading it
every time we make a change all right so
you can see all that stuff was added to
the package dot Jason now as far as
scripts I'm just gonna add a start
script here so basically if we do NPM
start I just want it to run node and
then index which is gonna be our our
entry point file and then we'll create a
dev script that will run node mon-sol
node montt index and we'll save that we
should be all set for our package Jason
so now let's create the entry point I'm
gonna call it index J s and let's just
set up a basic Express server so I'll
say Express so we want to require
Express and let's initialize our app
with Express and we're gonna be
accepting data from you know when we
make the post request to create the URL
or to create a short URL so we need to
add a piece of middleware hair so we use
app dot use and we can just do Express
dot jason and pass in this extended
value and set that to false so basically
what this does is it allows us to accept
JSON data into our API then we're going
to create a port variable which I'm
going to use 5,000 and then let's say
app dot listen which will listen on a
port so we'll put our variable in there
and then we can have a callback and I'm
just gonna do a console log and we'll
just say server running on ports and
then we'll put in our variable of port
all right so just doing that the server
should run if I go to my terminal and I
run npm run dev there we go so node mon
is now running and it's watching on
port 5000 all right so now that we have
that let's let's start to connect to our
database so I'm going to create a folder
called config and inside here I'm going
to create a default dot JSON file so
when we use that config package that I
installed this right here basically it
looks at this default dot JSON for any
global variables and if you go into
production if you deploy and you're in a
production environment you want to
create a production dot JSON for your
variables so this takes in just a JSON
object and we need our URI and I
can grab that from Atlas so if I go to
connect connect your application and
just copy this string right here and
paste that in and you just need to add
your password so mine is Brad T one two
three four and then we also want to put
base URL here so this is basically going
to be your domain and in this case it's
just going to be localhost port 3000 but
if you deploy this and you get a domain
you can use that all right so let's save
this close it up and now inside config
we're gonna create another file called D
bjs and this is where we want to connect
to our database and if you took my myrn
stat course we're doing pretty much the
same thing as far as connecting so we're
using Mongoose so require Mongoose and
we also want to bring in that config
package because we want to be able to
want to be able to grab that URI I
can't spell today
okay so we'll create another variable
called DB and said that's a config in
the way that we grab those global
variables is just with config get and
I'm gonna grab URI okay so this is
gonna grab this right here whatever this
value is so underneath that let's create
a function to connect to our database so
I'll call this connect DB and we're
gonna label this a sync because we're
gonna use a sink of weight here because
Mongoose when you use Mongoose methods
it returns a promise so instead of using
dot then I'm gonna I'm gonna use a sink
away okay and we want to wrap this in a
try-catch and inside the try we're gonna
await Mongoose dot connect and this
takes in the string the connection
string which we put in DB variable and
then some options and we're gonna add
here use New york-new URL parser and set
that to true otherwise we're gonna get
some warnings okay and then once we
connect I'm just gonna its console.log
and we'll just say MongoDB connected
okay and then down here if something
goes wrong we'll do a console error of
error dot message that should give us
that should print out the message and
then we'll exit will say process exit we
want to exit with failure so we're gonna
put in a one okay and then we're just
going to module dot exports the connect
DB function so that we can run that in
the index file and connect so let's save
this and let's go to index j s and let's
see we want to bring in connect DB i
want to bring in that function we just
created so we're gonna require and we
want to go into the config and then DB
and then let's go right
yeah I guess we'll go right here say
connect to database and all you have to
do is run connect dB all right so I'm
gonna save that and if we go back to our
terminal now now you see this DB
connected okay if I were to mess this
the string up somehow which I'll go to
default Jason and if I mess up the
password and we take a look you can see
that the app has crashed and we get this
bad authentication failed message so I'm
just gonna fix that and we should be all
set good so we can close that up we can
close that up we're connected to our
database so the next thing I'm gonna do
is create our model so let's create a
folder called models if you haven't used
Mongoose before you basically create a
schema for each resource we only have
one resource which is our URL so I'm
gonna create a model called URL dot Jas
and let's see we're gonna bring in
Mongoose and then we want to create a
schema so we're gonna call this URL
schema and we set this to a new Mongoose
dot schema and then this takes in an
object with all the fields we want so
the first thing is a URL code and that's
gonna be string we also want a long URL
so that's you know the long version or
the original URL and then a short URL
which we're going to construct which
will also be a string and then let's
also have the date for the date I'm
gonna set type string the reason I'm
doing it this way is because I also want
to do a default and let's make that date
dot now that way that the current date
and time will be inserted and then we
just want a module dot exports so we
want to export the model so we say
Mongoose dot model and name of the model
is URL and then we need to pass in the
schema
okay and that's it let's save that so
that's our model now we need to start to
deal with our routes so we're gonna have
a folder called routes basically just
gonna have two routes but I'm gonna have
two separate files one is gonna be index
dot JSON is gonna be whether that's use
me URL dot J s so URL j s is basically
where we're gonna have our post route to
be able to create a URL and insert it
into the database index J s is gonna
have the basically all the short URLs
recreate we need to have them work so
basically we need to have them redirect
to the long URLs that's what's going to
go in here so before we do anything here
let's go to our main index J s and we
need to basically define our routes so
let's go right here and say app dot use
so we just want to set slash to require
dot slash routes slash index I'll copy
that down and then we also want slash
API slash URL to pertain to that URL
routes file alright so we'll save that
what's this okay so it's just telling us
we haven't used a router yet so we need
to go to both of these and set up our
Express router so the way we do that is
we bring in Express
and then to create a router will say
const router equals express dots
uppercase our router and then at the
bottom we're gonna module dot exports
equals router and we want to do the same
thing in our URL j s and that should
clear up that error yeah alright so
we're gonna start off in the URL j s
this is where we we actually create our
short URL that's gonna have that route
so we're gonna bring in a couple things
here so we're gonna bring in our valid
URL method that's comes from that valid
URL package that I installed so it's
valid
- URL let's see let's also bring in our
short ID so it's shorts ID like that
short ID and then let's also bring in do
we need config yeah because we need the
base URL so let's bring in config and
then we want to bring in our model our
URL model so I'm gonna go right here and
just say Const URL equals require dot
dot slash so up one level into models
and into URL
alright so let's create our route so I'm
just gonna give this kind of a signature
here let's say route and this is gonna
be a I'm sorry it's gonna be a post
request not a poet a post request to
slash API slash URL slash shorten okay
that's going to be the endpoint to
create a short URL and let's just give
this a description
I'll say create shorts URL okay so let's
go ahead and take our router and let's a
router dot post because this is a post
request and then in here we just put
shorten okay we don't have to put this
API URL because we already connected
that right here to this file
alright so it'll be this route when we
hit that and then we have request
response and we're gonna get inside this
request dot body we're gonna send some
data and I'm gonna pull out that data
using destructuring so we're just
basically gonna send a long URL that's
it that's all we're gonna send with the
request and for our base URL let's set a
variable of base URL and let's get that
from our config file so config dot get
and we want to get base URL which is
gonna be in our case localhost oh wait a
minute I put 3000 didn't I should be
5,000 because that's what I'm running it
on whatever port you're running it on
it's what you want to use alright so
let's see let's make sure that URL is
valid so to put an if statement here and
we're going to use valid URL which has a
method called is URI okay so basically
it'll just make sure it's a valid URI or
URL and we want to check the base URL
first and wait a minute if it's valid
no let's let's check to see if it's not
valid and if it's not valid then we're
going to return a res dot status of 401
and we'll add a jason message here and
we'll just say invalid base URL okay so
now we want to generate the code pi so
if we look at the bitly website the link
that was generated this right here is
the code okay and we're gonna use that
short ID package to do that so let's say
create URL code so we'll say Const
URL code and all we have to do is say
shorts ID dot generates and that will
create it for us now what we want to do
is check the long URL that's sent in
from the client and make sure that
that's an actual URLs let's say check
long URL actually put a comment here
all right so same thing we're gonna do
an if and let's say if valid URL dot is
URI and we're gonna pass in our long URL
which remember comes in from the client
and if that's valid then we're gonna
want to look in our database to see if
that URL is already there so I'm gonna
do a try-catch here and let's see I also
want to mark this async this route
callback he sink because I'm using a
sink of wait for Mongoose so let's do
I'm gonna use let here and create a
variable called URL and set this to a
wait and then we're gonna take our model
so with Mongoose we have a bunch of
different methods one of them is find
one which will find one record from your
database and we want to find it by long
URL and this is the same as doing this
okay now we want to see if there's a URL
found so let's say if there's a URL then
we want to just return that or you know
respond with that so we can just do res
dot jason which will give a 200 response
and we'll send the URL which will have
all the database fields the long the
short the code and the date alright now
if there's not a URL found then let's
see we're gonna construct our short URL
so let's say Const short URL and we'll
set this to our base URL and then we
want to just add on let's say slash and
then we're gonna add on the URL code
okay so the URL code was right here was
constructed with that short ID package
with the generate method so it'll be
localhost 3000 slash and then some
random code okay now down here let's
take URL okay which we initialized here
if it was found then you know it'll just
return the response if not then we're
gonna set that to a new URL to insert
into the database and this takes in an
object whoops what did I do here forgot
the equals so in here we're gonna have
the long URL we want that inserted we
also want the short URL that we just
created and we also want the URL code
and then remember we also have the date
so I'll just set that to whatever the
didn't then date is okay and then we
need to save it because just saying new
URL doesn't actually save it it just
creates the instance to save it we need
to call URL dot save which returns a
promise so we need to put a wait in
front of it but we don't need to store
it store it in a variable and then let's
just do our res dot jason and then we'll
return URL which will include all this
stuff all right hopefully that makes
sense now down here and the catch so if
something goes wrong it's most likely
some kind of server error so I'm going
to first of all just console error
whatever the error is and then as far as
response from the server let's do a 500
status and we'll just say Jason and
we'll do server error
okay now this else is it pertains to
this right here if long URL is not valid
so if it's not valid then let's just do
a res dot status 401 and Jason let's
invalid long URL and I think that should
be good so I'm gonna save that now just
to kind of reiterate in case any of this
doesn't make sense we brought in
everything including our model we have a
post request to this endpoint right here
we are pulling the long URL out from the
body which is sent from the client we're
pulling the base URL from our default
dot JSON file which is localhost 5,000
and then we're checking the base URL
making sure that's valid then we're
generating our URL code for the short
URL we're checking the long URL to make
sure that's valid this is what's sent in
from the client then we're looking to
see if that URL is in there like if
there's a URL for google.com that's
already in the database then we're just
going to return whatever that is
whatever's there else then we're gonna
construct the new short URL we're going
to instant our instantiate a new URL
object with the long short the code and
the date we're gonna save it to the
database and then respond with it okay
down here something goes wrong we'll
send a server error 500 if the if the
URL is invalid the long one then we'll
send this status all right so that's
what's going on here so I guess yeah I
guess we can go ahead and try this out
now like I said you can use whatever you
want to to make this post request I'm
gonna use something called rest client
which is a vs code extension which is
this right here alright so in order to
use this within my file structure I'm
going
create a folder called requests and I'm
going to create a file called API dot
HTTP and in order to make a request this
is actually pretty easy we can just say
post and the URL is HTTP localhost 5,000
and we want to go slash API well yes
that's what we want but let's get rid of
that so API URL shortened and then we
have to have a content type and you can
see we get these little dropdowns
content is application slash Jason and
then we want to send the data which is
gonna be long URL this actually has to
be jason long URL ok so let's grab a
long URL I'll go ahead and grab that
Amazon link and let's go ahead and paste
that in and now we should be able to
make our request so I'm gonna click this
send request invalid protocol Oh alright
let's try that connection is being
rejected the service isn't running
because it says three thousand five
thousand try it again and there we go so
you can see with our response we have
them the ID which MongoDB creates on its
own we have the long URL which is the
original Amazon link and then we have
the short URL which is localhost 5,000
slash and then a code ok we also have
the code itself and we have the date and
time now when if you deploy this you you
probably want to register like a short
domain and then you know so this is
really really short localhost 5000 is
kind of long but let's check our
database if we go to MongoDB or Atlas
and we go to collections you can see
there it is so it got stored now this
link is not going to work right if I go
and copy this and I paste this in it's
it's looking for this route so what we
need to do now is create another
endpoint for the codes and that's going
to go on the index J I so let's head
over to that we can go ahead and close
that up you know I guess I guess we'll
save that request all right so we can
close up URL dot J s now let's go into
our routes folder and then index J ass
because that's what we're gonna put this
so we need to bring in our model and
this is this is gonna be pretty easy so
dot dot slash models /url and then let's
create our route so let's say oops let's
say route so it's a get request and it's
gonna be to just slash and then whatever
the code is and let's do description so
the description we're going to redirect
to the long or original URL okay so it's
gonna be a get request so we'll say
router dot get and we're just gonna say
in here / : code because obviously this
is this is a parameter this is a
placeholder so we want this : here we're
not actually going to slash code and
then let's do a sync and request
response
and we'll do a try-catch here
okay so inside the try let's create a
variable called URL and we're gonna use
find one again from Mongoose which
returns a promise so we want to do a
wait URL dot find one we want to find it
by the code okay so we're gonna say URL
code and we can get whatever's passed
into this right here we can get with
request dot params dot code okay so we
want to match that code we want to find
that URL so then we're gonna say if if
URL so basically if it's there then we
want to return a res dot redirect okay
because we're actually gonna redirect to
that to the long URL so we'll take that
URL object and we want the long URL
property
okay well that's so that's what we're
redirecting to else then let's just
return a res dot status of 400 actually
I guess we could do a 404 and say dot
jason and say no URL found okay and then
in the catch here we'll just do a
console error and just log whatever is
in error and then we'll do a res dot
status 500 and we'll just say server
error alright and that's it so just to
kind of reiterate we're gonna try to do
our you know whatever slash code
whatever the code is we're gonna check
to see if there's a URL with that code
if there is we're gonna redirect to it
or though we're gonna redirect to the
long version if not then we're just
going to say that the URL isn't found if
you want to do a standard redirect er I
mean you can handle it in a different
way if you want to but I think that this
is fine
so now let's let's once again cop
be the short URL here and let's open up
a new tab and let's go to it and there
we go so our service is working we can
now generate short URLs and they work
and just to kind of try it one more time
let's let's let's get a different URL
grab this right here so grab that and if
we go back to our API HTTP I'm just
gonna replace this and let's go ahead
and send that okay so we get the
response back that should have added a
new row in our database let's check it
out yep so there it is which one is it
this one so now both of these should
work okay that's the end that's the
PlayStation let's try this one and
that's the charger thing okay so that's
working good now I just want to show you
if we were to insert the same URL so if
I were to insert this again let's just
send the request it just gives us the
data back and it's not gonna add it more
than once so if we look in our database
and I reload we're still gonna have two
rows okay because there's no sense in
having the same short URL I'm sorry the
same long URL with a different short URL
okay unless you have it where different
users are creating their own short URLs
and things like that all right so I
think that's it guys we have our service
created like I said I'm probably gonna
add on to this for a course where we
create a UI and a front-end and all that
if you want to create your own front-end
with react or view or something like
that feel free to do so I'll have the
code for this
in the link in the description but
that's it thanks for watching if you
like this please leave a like and I'll
see you next time