5. RESTful Routes

RESTful Routes

GET

  • Retrieve information
  • Data is limited and sent via query string (visible)

POST

  • Post data to the server
  • Data can be any type (json) and is sent via request body (hidden)
<body>
    <h2>GET</h2>
    <form action="http://localhost:3000/tacos" method="GET">
        <input type="text" name="meat">
        <input type="number" name="qty">
        <button>Submit</button>
    </form>
    <h2>POST</h2>
    <form action="http://localhost:3000/tacos" method="POST">
        <input type="text" name="meat">
        <input type="number" name="qty">
        <button>Submit</button>
    </form>
</body>
const express = require('express')
const app = express()

app.use(express.urlencoded({extended: true}));

app.get('/tacos', (req, res) => {
    res.send("GET /tacos response");
})

app.post('/tacos', (req, res) => {
    const {meat, qty} = req.body;
    console.log(`meat: ${meat}\nquantity: ${qty}`);
    res.send("POST /tacos reponse")
})

app.listen(3000, ()=>{
    console.log("listening on port 3000");
})

REST

  • Set of guidlines for how server and client should commuincate.
  • CRUD: create (post), read (get), update (patch), destroy (delete) NAME VERB PATH Index GET /comments list all comments New GET /comments/new form to create new comment Create POST /comments create a new comment Show GET /comments/:id get one comment Edit GET /comments/:id get one comment Update PATCH /comments/:id update one comment Destroy DELETE /comments/:id delete one comment

GET and POST

We need 2 routes becasue the form needs to send the data somwehere (as POST request)

  1. Route that displays the form
app.get('/comments/new', (req, res)=>{
    res.render('comments/new');
})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>New Comment</title>
</head>
<body>
    <h1>Make a new comment</h1>
    <form action="/comments" method="post">
        <section>
        <label for="username">Enter username:</label>
        <input type="text" placeholder="username" name='username'>
        </section>
        <section>
        <label for="comment">Comment Text</label>
        <br>
        <textarea name="comment" cols="30" rows="5"></textarea>
        </section>
        <button>Submit</button>
    </form>
</body>
</html>
  1. Route that receive the form data
app.post('/comments',(req, res)=>{
    console.log(req.body);
    res.send("IT WORKS");
})

Use express.urlencoded() A method inbuilt in express to recognize the incoming Request Object as strings or arrays. This method is called as a middleware app.use(express.urlencoded({extended: true}));

Extract the data from the body request

app.post('/comments',(req, res)=>{
    const {username, comment} = req.body;
    comments.push({username, comment});
    res.send("IT WORKS");
})
  1. redirect the user to the comments view instead of res.send: res.redirect('/commets')

SHOW route

Each resource should have an unique identifier i.e. /comments/:id req.params takes the values after :

app.get('/comments/me/:id&:tag', (req, res)=>{
    console.log(req.params);
    res.send("Done");
})

or

app.get('/comments/:id', (req, res)=>{
    const {id} = req.params;
    const comment = comments.find(c => c.id === parseInt(id));
    res.render('comments/show', {comment})
})
        <% for (let comment of comments){ %>
            <li><%= comment.comment %> - <b> <a href="\comments\<%= comment.id %>"><%= comment.username %></a></b></li>
        <% } %>     

UUID Unique Identifier

  • Install npm i uuid
  • Load and rename from v4 to uuidv4 const {v4: uuidv4} = require('uuid');
  • Give each item an unique id when submitted:
    const id = uuidv4();
    comments.push({id, username, comment});

UPDATE route (Patch)

app.patch('/comments/:id', (req, res)=>{
    const {id} = req.params;
    const newCommentText = req.body.comment;
    const foundComment = comments.find(c => c.id === id);
    foundComment.comment = newCommentText;
    res.redirect('/comments');
})
  • does not follow the immutability pattern

Express method override

  • html form can only send GET and POST requests
  • install method-override package
const methodOverride = require('method-override')
//specify query string
app.use(methodOverride('_method'));

Use a form to edit the comment

app.get('/comments/:id/edit', (req, res)=>{
    const {id} = req.params;
    const comment = comments.find(c => c.id === id);
    res.render('comments/edit', {comment});
})
<body>
    <h1>Edit</h1>
    <form method="POST" action="/comments/<%= comment.id%>?_method=PATCH">
        <textarea name="comment" id="" cols="30" rows="10">
            <%= comment.comment %>
        </textarea>
        <button>Save</button>
    </form>
    <a href="/comments">Go back</a>
</body>

This will call app.patch created before

DELETE

app.delete('/comments/:id', (req, res)=>{
    const {id} = req.params;
    //better to create a new array than mutating an existing one
    comments = comments.filter(c=>c.id !== id)
    res.redirect('/comments');
})
<form method="POST" action="/comments/<=% comment.id %>/_method=DELETE">
    <button>Delete</button>
</form>
Written on August 17, 2021