Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Checking what a user types (validation)

After this lesson: I can check what a user types into a form.

50 min lesson7 commandsPostgreSQL and PostgREST lab: a database and a REST API in the browser

An age of "ten" on a sign-up form

A college coding club puts a sign-up form online. Within a day the list has a person with no name, an email with no @ sign, and an age of "ten".

Nobody was being clever. People make typing mistakes, and nothing checked. Today you see where those checks go, and write one yourself.

By the end of this lesson

Note

I can check what a user types into a form.

Key words

WordWhat it meansExample
Formthe part of a page where you type answers and send them
Fieldone box on a formemail
Validationchecking that what was typed follows the rules
Client sidedone in the user's browser
Server sidedone on the server, after the data arrives
Constrainta rule the database itself refuses to breakage between 16 and 18

The cells students fill in are left blank in this preview.

The browser can check a field

A web page builds a form out of fields. HTML can give each field a rule. required means it cannot be empty. type="email" wants an address with an @ sign. min and max set the smallest and biggest number.

These are client side checks: the browser does them before anything is sent.

Try the browser's own checks

Code: web
<h1>Coding club sign-up</h1>
<form>
  <p><label>Name <input name="name" required></label></p>
  <p><label>Email <input name="email" type="email" required></label></p>
  <p><label>Age <input name="age" type="number" min="16" max="18" required></label></p>
  <p><button>Send</button></p>
</form>
<p id="result"></p>

The browser's checks can be skipped

The browser's checks only run on that page. Anybody can skip the page and send a request straight to the server, as curl does.

So the server has to check again: server side. In the lab the rules go into the database as constraints. The database refuses any row that breaks one, whoever sent it.

Before you start the Runs

Note

Press Start the lab and wait until it says it is running. Press the Runs in order. The first four make a signups table with three rules. The name and email cannot be empty. The email needs an @ sign, and the age is 16 to 18.

Give psql the password

Command
export PGPASSWORD=shop

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Start with a clean table

Command
psql -h db -U shop -c "drop table if exists signups"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Make a table with rules

Command
psql -h db -U shop -c "create table signups (id serial primary key, name text not null, email text not null check (email like '%@%'), age int not null check (age between 16 and 18))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Tell the API to look again

Command
psql -h db -U shop -c "notify pgrst, 'reload schema'"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Send a sign-up that keeps every rule

Command
curl -s -w "\n%{http_code}\n" -X POST -H "Content-Type: application/json" -d '{"name":"Maya","email":"[email protected]","age":17}' "http://api:3000/signups"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Reading a refusal

The last line of each Run is the status code. 201 means the row was stored.

A refusal is 400, which means the request was wrong. Above it the API sends JSON that says why. Look for "code" and "message": the message names the rule that was broken.

Send a sign-up with no name

Command
curl -s -w "\n%{http_code}\n" -X POST -H "Content-Type: application/json" -d '{"email":"[email protected]","age":16}' "http://api:3000/signups"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Send an age of 25

Command
curl -s -w "\n%{http_code}\n" -X POST -H "Content-Type: application/json" -d '{"name":"Ivy","email":"[email protected]","age":25}' "http://api:3000/signups"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A common mistake

Warning

Many people think the browser's checks are enough. They only help honest users fix a typing mistake. Your Runs skipped the page completely. So every rule is checked again on the server, and the browser's checks are only a help.

A check written in Python

Code: python
def check_age(text):
    # A form always sends text, even for a number.
    if not text.isdigit():
        return "age must be a whole number"
    age = int(text)
    if age < 16 or age > 18:
        return "age must be 16 to 18"
    return "ok"


# Change "17" to "ten", then to "25", and press Run each time.
print(check_age("17"))

Going further: a weak email rule

Send leo.example.com as an email in the lab: copy the good Run, change the name and the email, and press Enter. The database refuses it.

Now think about @, a single @ sign on its own. Would the lab's rule accept it? What would a better rule check?

About this lab and its source: PostgreSQL and PostgREST lab: a database and a REST API in the browser

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.