# Lektion 13 — Øvelser

Man lærer routes bedst ved at omskrive serveren og kalde den uden browseren.
Detaljerne, der ikke står på slidesne, står her.

Hvis du ikke nåede [forberedelsen](forberedelse.md), så læs Express-lectures
og kør `my-app`, før du rører gruppens `server.js`.

| Øvelse | Hvornår | Tid |
|---|---|---|
| **1** Fra `http.createServer` til Express | Efter gennemgangen af Express i `server.js` | ~35 min |
| **2** Én patient via `:cpr` | Efter quizzen om routes og `:cpr` | ~15 min |
| **3** POST fra `api.http` | Efter quizzen om POST | ~30 min |
| **4** Tabellen mod jeres server | Efter øvelse 3 | ~25 min |

---

## Øvelse 1 — Fra `http.createServer` til Express

**Mål:** `server.js` kører med Express. `GET /api/patients` og 404 opfører sig
som i lektion 11, og tabellen henter stadig JSON fra `localhost:3000`.

Arbejd i gruppens projekt. Behold filnavnet `server.js`.

### Det skal du lave

1. `npm init -y` og `npm install express` i projektmappen. Opret en
   `.gitignore` med linjen `node_modules/`, hvis I ikke har en.
2. Erstat `http.createServer` med Express som på slidesne: `require`,
   `app.use` til CORS, `express.json()`, `patients`-array.
3. `app.get("/api/patients", …)` svarer med `res.json(patients)`.
4. Sidste middleware, under alle routes: `404` og `{ error: "not found" }`.
5. `app.listen(3000)`. Start med `node server.js`.
6. Tjek `http://localhost:3000/api/patients`, og at `/` giver 404 JSON.
7. Bekræft at tabellen viser de samme navne som før omskrivningen.

### Udgangspunkt

`server.js` fra lektion 11 — mindst to patienter med `cpr` og `navn`.

### Tjekliste

- [ ] `http.createServer` og `writeHead` er væk fra `server.js`
- [ ] `package.json` og `package-lock.json` findes; `node_modules/` er ikke
  committet
- [ ] `GET /api/patients` giver 200 med listen
- [ ] `GET /` og andre ukendte stier giver 404 JSON
- [ ] CORS-headeren er sat, så `fetch` fra en lokal HTML-side virker
- [ ] Tabellen og browser-JSON viser samme data

### Øvelsen er i hus når…

du kan stoppe processen, starte igen og vise JSON plus tabelrækker uden
at ændre `fetch`-URL'en.

### Hvis du sidder fast

- `Cannot find module 'express'`: kør `npm install express` i mappen, hvor
  `server.js` ligger.
- `require is not defined in ES module scope`: jeres `package.json` har
  `"type": "module"` (fx fra Vite). Kør `npm init -y` i mappen med
  `server.js`, så den får sin egen `package.json`.
- `EADDRINUSE: address already in use :::3000`: en anden proces kører
  stadig — fx `my-app` eller jeres gamle server. Find terminalen og tryk
  Ctrl+C.
- 404 på `/api/patients`: kører den gamle proces stadig? Stop den med
  Ctrl+C og start `node server.js` igen. Tjek også stavningen af stien, og
  at 404-handleren står under routen.
- Tom tabel, JSON OK: CORS eller forkert `fetch`-URL.

### Hvis du har ekstra tid

Tilføj en tredje patient i arrayet i filen. Genstart og tjek tabellen.
Skriv ikke `POST` endnu — det er øvelse 3.

---

## Øvelse 2 — Én patient via `:cpr`

**Mål:** `GET /api/patients/:cpr` henter én patient fra samme array. En ukendt
CPR giver 404.

### Det skal du lave

1. Tilføj `app.get("/api/patients/:cpr", …)` som på slidesne, **over**
   404-handleren.
2. Genstart `node server.js`.
3. Åbn `http://localhost:3000/api/patients/` plus en CPR fra jeres liste.
4. Prøv en CPR, der ikke står i listen.

### Tjekliste

- [ ] En kendt CPR giver 200 og den ene patient — ikke en liste
- [ ] Ukendt CPR giver 404 JSON, ikke en tom liste
- [ ] `GET /api/patients` virker stadig som før

### Øvelsen er i hus når…

du kan vise begge svar i browseren og pege på `req.params.cpr` i koden.

### Hvis du sidder fast

- 404 på en CPR, du ved er i listen: `:cpr`-routen står under catch-all.
  Flyt den op. Eller CPR står som tal i arrayet — den skal stå som tekst
  (`"2512489996"`), fordi `req.params.cpr` altid er en streng.
- Du får hele listen: du kalder `res.json(patients)` i stedet for
  `res.json(patient)`.

### Hvis du har ekstra tid

Åbn DevTools → Network, hent en kendt og en ukendt CPR, og find
statuskoden for hver.

---

## Øvelse 3 — POST fra `api.http`

**Mål:** `POST /api/patients` tilføjer en patient til listen i hukommelsen. Du
kan bevise det fra en `.http`-fil i VS Code uden at åbne DevTools.

Serveren skal køre, mens du sender requests.

### Det skal du lave

1. Installér extension **REST Client** (Huachao Mao) i VS Code under
   Extensions.
2. Tilføj `app.post("/api/patients", …)` **over** 404-handleren.
3. Læs `cpr` og `navn` fra `req.body ?? {}`. Svar `400`, hvis et felt mangler.
4. `push` til `patients`. Svar `201` og den nye patient som JSON.
5. Genstart `node server.js`.
6. Lav `api.http` i projektmappen med de tre requests nedenfor.
7. Klik **Send Request** over `POST`-requestet med body. Tjek, at svaret er
   `201`.
8. Send `GET` og find den nye patient. Åbn samme URL i browseren og
   sammenlign.
9. Send `POST` uden body. Svaret skal være `400`, ikke `500`.

```http
### Hele listen
GET http://localhost:3000/api/patients

### Opret patient
POST http://localhost:3000/api/patients
Content-Type: application/json

{"cpr":"0201029994","navn":"Ny Test Person"}

### Uden body — skal give 400
POST http://localhost:3000/api/patients
```

`###` skiller requests ad. Den tomme linje skiller headers fra body — som i
selve HTTP-beskeden. Commit `api.http`; I bruger den igen i lektion 17.

### Tjekliste

- [ ] `express.json()` står **før** POST-routen
- [ ] `POST` uden body eller uden `cpr`/`navn` giver `400` — ikke `500`
- [ ] Vellykket `POST` giver `201`
- [ ] `GET` efter `POST` viser den nye patient
- [ ] Genstart af processen fjerner den oprettede patient igen (listen var
  kun i RAM)

### Øvelsen er i hus når…

du kan vise svaret fra `POST` og derefter `GET` i `api.http`, hvor den nye
CPR står i arrayet.

### Hvis du sidder fast

- Ingen **Send Request** over requestet: filen skal ende på `.http`, og REST
  Client skal være installeret.
- `req.body` er `undefined`: mangler `express.json()`, `Content-Type`-linjen
  eller den tomme linje før body.
- `500` med `Cannot destructure property 'cpr'`: skriv `req.body ?? {}`.
- `POST` giver 404: routen er registreret efter catch-all — flyt `app.post`
  op.
- `400` med `Expected property name` eller `Unexpected token`: JSON'en er
  ugyldig. Tjek anførselstegn og kommaer i body.
- `connect ECONNREFUSED`: serveren kører ikke. Start `node server.js`.

### Hvis du har ekstra tid

Send `POST` med samme CPR to gange. Beslut i gruppen, om det er OK i
mockuppet — I behøver ikke løse dubletter endnu. Notér det til lektion 15.

Samme request kan sendes fra terminalen med curl. Det er nyttigt, når der
ikke er en editor — fx mod en server i skyen:

```bash
curl.exe -i http://localhost:3000/api/patients
```

Skriv `curl.exe` på Windows — i PowerShell er `curl` et alias for
`Invoke-WebRequest`.

---

## Øvelse 4 — Tabellen mod jeres server

**Mål:** Gruppens patienttabel viser data fra jeres Express-server, også
efter I har tilføjet en patient fra `api.http`.

### Det skal I nå

1. Åbn mockuppet lokalt (HTML-fil eller dev-server), mens `node server.js`
   kører. `fetch` kører i browseren, så `localhost` betyder den maskine,
   browseren kører på. Åbner en anden jeres Vercel-side, peger `localhost` på
   deres maskine — ikke jeres server.
2. Bekræft at `fetch` peger på `http://localhost:3000/api/patients`.
3. Send `POST` fra `api.http` for en patient, I kan genkende i jeres domæne (navn
   fra jeres testcase — ikke rigtige CPR).
4. Genindlæs siden eller kør den funktion, der henter listen igen. Den nye
   række skal vises.
5. Skriv tre korte bullets til jeres projektlog: hvad ligger i browseren nu,
   hvad ligger på serveren, og hvad kommer i PostgreSQL i lektion 15.

### Tjekliste

- [ ] Tabellen og `GET` i `api.http` viser samme antal patienter
- [ ] I kan forklare, hvorfor en anden, der åbner jeres Vercel-side, ikke
  ser patienterne fra jeres laptop
- [ ] Gruppen ved, at genstart af serveren sletter de oprettede patienter

### Øvelsen er i hus når…

en anden i gruppen kan demo: `POST` fra `api.http`, refresh af tabellen, og forklaring
af hvor listen bor.

### Hvis I sidder fast

Samme fejlsøgning som lektion 11: JSON i browseren på `localhost:3000`, men
tom tabel peger på URL eller CORS — ikke på Express syntaks.

### Hvis I har ekstra tid

Tegn sekvensdiagram: bruger, browser, Express — med `GET` efter `POST`.
Databasen som livlinje med note «lektion 15».

Prøver I at `POST`'e med `fetch` fra siden i stedet for `api.http`, fejler det på
CORS. Browseren sender først et `OPTIONS`-request (preflight), som jeres
server svarer 404 på. Det er ikke en del af dagens øvelse.
