Node.js Form Handling

Forms collect information from visitors, such as names, emails, and messages. Express receives that information, reads it, and responds. This lesson shows the full path from the form to the server.

How a Form Travels

A form works like a paper slip dropped into a mailbox. The visitor fills the slip, the browser carries it, and the server reads it.

 +-----------+   submit   +-----------------+   read   +----------+
 | HTML form | ---------> | Express route   | -------> | req.body |
 +-----------+   POST     +-----------------+          +----------+
                                  |
                                  v
                           Response or redirect

GET and POST

  • GET places form data in the address bar. Use it for searches.
  • POST hides form data inside the request body. Use it for logins, sign-ups, and messages.

Build the HTML Form

Save this file as public/contact.html.

<form action="/contact" method="POST">
  <label>Name</label>
  <input type="text" name="fullName" required>

  <label>Email</label>
  <input type="email" name="email" required>

  <label>Message</label>
  <textarea name="message"></textarea>

  <button type="submit">Send</button>
</form>

The name attribute of each field becomes the key on the server. A field without a name never reaches Express.

Read the Form Data

Express needs a helper called middleware to decode form data. The express.urlencoded helper handles standard HTML forms.

const express = require("express");
const app = express();

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

app.post("/contact", (req, res) => {
  const { fullName, email, message } = req.body;
  console.log(fullName, email, message);
  res.send("Thanks, " + fullName + "!");
});

app.listen(3000);

The object req.body holds one key per form field.

Form field name    -->   req.body key
fullName           -->   req.body.fullName
email              -->   req.body.email
message            -->   req.body.message

Read JSON Data

Mobile apps and JavaScript code often send JSON instead of form data. Add the JSON helper for those requests.

app.use(express.json());

Check the Data

Never trust data from a visitor. Check each field before you use it.

app.post("/contact", (req, res) => {
  const { fullName, email, message } = req.body;

  if (!fullName || !email) {
    return res.status(400).send("Name and email are required.");
  }
  if (!email.includes("@")) {
    return res.status(400).send("Enter a valid email.");
  }
  if (message && message.length > 500) {
    return res.status(400).send("Message is too long.");
  }

  res.send("Message received.");
});

Status code 400 tells the browser that the request has a problem.

Redirect After Success

A page that answers a POST request can show the form again when the visitor refreshes, which resends the data. A redirect prevents that problem. This pattern is called Post, Redirect, Get.

app.post("/contact", (req, res) => {
  // save the data here
  res.redirect("/thanks.html");
});
Browser --POST--> Server
Browser <--redirect-- Server
Browser --GET /thanks.html--> Server

Handle a Search Form with GET

<form action="/search" method="GET">
  <input type="text" name="q">
  <button>Search</button>
</form>
app.get("/search", (req, res) => {
  const term = req.query.q || "";
  res.send("You searched for: " + term);
});

GET data arrives in req.query, not in req.body.

Protect Output

Visitors can type HTML tags into a form. Printing that text straight onto a page lets harmful scripts run. Template engines escape text automatically. Escape manual output yourself.

function escapeHtml(text) {
  return text
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;");
}

Common Problems

req.body Is Undefined

The parsing helper is missing, or it sits below your route. Place app.use lines above the routes.

Fields Arrive Empty

Check the name attribute on each input.

Practice Tasks

  • Build a sign-up form with name, email, and age fields.
  • Reject an age below 18 with a clear message.
  • Redirect to a thank-you page after a valid submission.