Skip to content

Beginner · APIs and request handling · topic 10 of 54 · 25 min

Validating input

Explanation

Validation means checking every piece of data that reaches your server before you use it. Anyone can send any request, so never trust input: check that required fields exist, have the right type and length, and follow the right format, like a 10-digit Indian mobile number. Return all the problems at once with a 400 or 422 status.

Never trust input

Input is any data that comes from outside your server: the body, the query, path params, headers and cookies. Your own app may check the form, but people can send requests with tools like curl or Postman, or change the app. So the backend must check everything again.

Think of it like this: Think of a bank counter. You fill a deposit slip at the table, and you may check it yourself. But the clerk still checks the account number, the amount in words and figures, and your signature before accepting it. The backend is that clerk.

Four kinds of checks

CheckQuestionExample
RequiredIs it there?name must be present
TypeIs it the right kind of value?price must be a number, not "100"
Length or rangeIs it too short, too long, too big?name 2 to 50 letters; qty 1 to 10
FormatDoes it have the right shape?mobile, PIN code, email

Checking formats with regular expressions

A regular expression (regex) is a short pattern that describes the shape of some text. ^ means "start", $ means "end", [6-9] means "one digit from 6 to 9", and {9} means "exactly 9 times". The test method says whether some text fits the pattern.

javascript
const mobile = /^[6-9][0-9]{9}$/;   // 10 digits, first is 6, 7, 8 or 9
const pin = /^[1-9][0-9]{5}$/;      // 6 digits, first is not 0
const email = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; // something@something.something

console.log(mobile.test('9876543210')); // true
console.log(mobile.test('5876543210')); // false: starts with 5
console.log(pin.test('560001'));        // true (Bengaluru)
console.log(pin.test('56001'));         // false: only 5 digits
console.log(email.test('asha@example.in')); // true
console.log(email.test('asha@example'));    // false: no dot after @
Three common Indian checks. ^ and $ make sure the whole text matches, not just a part.
Careful: Without ^ and $, the pattern /[6-9][0-9]{9}/ also matches "abc9876543210xyz", because it only looks for the digits somewhere inside. Always anchor format checks at both ends.

Collect every error

Do not stop at the first problem. Check every field and collect the problems in a list, each with the field name and a clear message. Then the app can mark all the wrong boxes at once, and the user fixes everything in one go.

javascript
function validateProduct(body) {
  const errors = [];
  if (typeof body.name !== 'string' || body.name.trim().length < 2) {
    errors.push({ field: 'name', message: 'Name must have at least 2 letters' });
  }
  if (typeof body.price !== 'number' || body.price <= 0) {
    errors.push({ field: 'price', message: 'Price must be a number above 0' });
  }
  return errors;
}

console.log(validateProduct({ name: 'Tea', price: 140 })); // []
console.log(validateProduct({ name: ' ', price: '140' })); // two errors
An empty list means the data is fine. Otherwise each error names its field.

400 or 422?

Use 400 Bad Request when the request itself is broken: the body is not valid JSON, or it is not an object at all. Use 422 Unprocessable Content when the JSON is fine but a value breaks a rule, like a mobile number with 8 digits. Many teams use 400 for both. What matters most is that you choose one style and use it everywhere.

Tip: Trim spaces from text before checking it. " " (only spaces) should count as empty, and " Ravi " should be saved as "Ravi".

Watch the lesson

Validating input · 1/6

Never trust input

Rule number one of backends: never trust input. Anyone can send any request to your server.

Prefer a video by a teacher? Find free videos on “backend input validation best practices tutorial” on YouTube ↗

In real life: A job portal sign-up form

A job portal asks for name, email, mobile and PIN code. The phone app checks the form, but the backend checks again, because a bot could post directly to /v1/signup. When a user sends mobile 12345 and PIN 0110, the server answers 422 with two errors, one for mobile and one for pin, and the app marks both boxes in red with the messages.

json
{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Some fields are not valid",
    "fields": [
      { "field": "mobile", "message": "Enter a 10-digit mobile number starting with 6, 7, 8 or 9" },
      { "field": "pin", "message": "Enter a 6-digit PIN code" }
    ]
  }
}
A 422 response body listing every problem.

Practice (0/3 done)

Task 1 · Code · Javascript

Write a function isIndianMobile(value) that returns true only when value is a string of exactly 10 digits whose first digit is 6, 7, 8 or 9.

Task 2 · Code · Javascript

Write a function isPinCode(value) that returns true when value is a string of exactly 6 digits that does not start with 0.

Task 3 · Code · Javascript

Write validateSignup(body) that returns an array of errors, each { field, message }, in this order: "name" if name is not a string of 2 to 50 characters after trimming; "email" if email is not a string shaped like a@b.c; "mobile" if it is not a valid Indian mobile; "pin" if it is not a valid PIN code. Return [] when all is fine. body may be null.

Quick quiz

Question 1

1.The app already checks the form. Why must the backend check again?

Question 2

2.Which value passes /^[6-9][0-9]{9}$/?

Question 3

3.What do ^ and $ do in a regex?

Question 4

4.The JSON is fine, but age is -4. Which status fits best?

Question 5

5.Why return a list of all errors instead of only the first one?

Read more (free)

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

← Previous: Handling requests: a full CRUD API