CSE 154

Lecture 17: More Node, POST

Today's Agenda

POST & Middleware in Node

Q&A

Exploration Seminars

Optional talks (~1 hour) led by our TAs on topics outside of core class curriculum

First one is coming up next week, will be led by Tal talking about creating browser extensions.

Each seminar will offer a (minimal) amount of extra credit for participating.

If you really want to hear about something, let us know!

Full-Stack Q&A

Add your questions, vote on what questions you want answered, and we'll tackle them towards the latter half of lecture.

Either on your phone or computer, go to PollEv.com/robcse

Handling POST Requests on the server-side

We've seen how to handle GET requests with app.get

But what about POST requests that we send with FormData?

GET vs. POST

Consider a Cafe site with three pages - index.html, admin.html, and contact.html

The backend might support a few GET endpoints: /menu, /menu/:category/, /categories, /images

What are examples of POST requests we might want to add?

Implementing a /contact POST endpoint

Let's implement an a POST endpoint to process a contact message sent from the contact page form.

Contact form view

To add a POST endpoint, use app.post instead of app.get

app.post("/contact", (req, res) => {
  ...
});

JS

POST Parameters

With GET endpoints, we've used req.params and req.query to get endpoint parameters passed in the request URL.

But remember that POST requests send parameters in the Request body, not in the URL.

app.post("/contact", (req, res) => {
  let name = req.params.name; // this doesn't work!
  ...
});

JS

What is a disadvantage of sending parameters in a URL?

  • Not secure, limit to the length of data we can send in a URL

So, how can we get POST parameters sent by a client?

Handling Different POST Requests

POST requests can be sent with different data types:

  • application/x-www-form-urlencoded
  • application/json
  • multipart/form-data

In Express, we have to use middleware to extract the POST parameters from the req.body. For the first two, there is built-in middleware - we don't need middleware for text/plain.

With forms and fetch, we use the FormData object to send POST parameters, which is always sent as multipart/form-data.

There is no built-in middleware to access the req.body params for multipart content.

Another module!

Middleware

Request flow with express and node.js

The multer Module

A module for extracting POST parameter values sent through multipart POST requests like those sent with FormData

Has a lot of functionality to support file uploading, but we will just use it to access the body of a POST request sent through FormData, which we can't get with just req.body.

To use, we'll need to set an option to ignore upload features with multer().none()

const multer = require("multer");

app.use(multer().none());

JS

Remember to run npm install multer in any project that uses it.

Supporting all POST requests

We often don't want to make assumptions about what method a client uses to POST data. It's best to support all three with the appropriate middleware.

// other required modules ...
const multer = require("multer");

// for application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true })) // built-in middleware
// for application/json
app.use(express.json()); // built-in middleware
// for multipart/form-data (required with FormData)
app.use(multer().none()); // requires the "multer" module

...
app.post("/contact", (req, res) => {
  let name = req.body.name;
  let email = req.body.email;
  let message = req.body.message;
  let timestamp = new Date.toUTCString();
  // validate parameters, then update message.json file with new data
  ...
});

JS

Summary of Handling a POST Request

  1. Use app.post instead of app.get
  2. Use req.body.paramname instead of req.params.paramname/req.query.paramname
  3. Require the multer (non-core) module with the rest of your modules
  4. Use the three middleware functions to support the three different types of POST requests from different possible clients
  5. Test your POST requests with Postman or with fetch and FormData in client-side JS (similar to HW3) - remember you can't test POST requests in the URL!

Choosing Error Codes

Use 400 (Invalid Requests) for client-specific errors.

  • Invalid parameter format (e.g. "Seattle" instead of a required 5-digit zipcode)
  • Missing a required query parameter
  • Requesting an item that doesn't exist

Use 500 (Server error) status codes for errors that are independent of any client input.

  • Errors caught in Node modules that are not related to any request parameters
  • SQL Database connection errors (next week!)
  • Other mysterious server errors...

More questions from this lecture?

Especially if you're watching a recording, write your question on PollEverywhere and I'll answer them at the start of next lecture.

Either on your phone or computer, go to PollEv.com/robcse