After logging in, a client holds a token. On every later request it sends the token back in the Authorization header, written as the word Bearer, a space, then the token. The shop looks the token up in the tokens table to find out who is calling.
Many routes will need that answer, so the lookup goes in a helper method that any route can call. Two tools help: request.getHeader gives null for a missing header, and Objects.requireNonNullElse swaps that null for a default; a JOIN goes from a row in one table to the row it points to in another. Both on a made-up example:
String lang = Objects.requireNonNullElse(request.getHeader("Accept-Language"), ""); // "" when the header is missing
String shortLang = lang.replace("-US", ""); // "en-US" becomes "en"
List<Map<String, Object>> rows = db.queryForList("SELECT products.name FROM orders JOIN products ON products.id = orders.product_id WHERE orders.id = ?", 5);
GET /me answers the logged-in user's id and email. With no token, or a token the shop never gave out, it answers 401. Below, <token> and <token2> stand for the random tokens the logins answered:
POST /register {"email": "ana@example.com", "password": "secret123"} → 201 {"email": "ana@example.com", "id": 1}
POST /register {"email": "ben@example.com", "password": "tea4two"} → 201 {"email": "ben@example.com", "id": 2}
POST /login {"email": "ana@example.com", "password": "secret123"} → 200 {"token": "<token>"}
POST /login {"email": "ben@example.com", "password": "tea4two"} → 200 {"token": "<token2>"}
GET /me Authorization: Bearer <token> → 200 {"email": "ana@example.com", "id": 1}
GET /me Authorization: Bearer <token2> → 200 {"email": "ben@example.com", "id": 2}
GET /me (no header) → 401 {"error": "Login required"}
GET /me Authorization: Bearer 0123456789abcdef0123456789abcdef → 401 {"error": "Login required"}Your task: write a helper currentUser(request) that reads the token from the Authorization header and returns its user's id and email as a Map, or null. Then add GET /me: answer {"error": "Login required"} with 401 when there is no user, otherwise the user as JSON.
Assignment
Follow the Coding Tutorial to write the currentUser helper and the /me route that uses it.
Hint
The default "" keeps header a String, so .replace works even when the header is missing. An empty or unknown token matches no row: queryForList gives an empty list, and the helper returns null. That is the 401 case.
Free plan: 30 tutor messages. PRO is unlimited.
