From 073975db86e82308389b42961065d3df40ffdd97 Mon Sep 17 00:00:00 2001 From: Vano Devium Date: Thu, 24 Oct 2019 15:22:29 +0300 Subject: [PATCH] Added support for path parameters --- README.md | 12 +++++++++++- example/index.ts | 2 ++ mod.ts | 33 +++++++++++++++++++++++++++++++-- serve_test.ts | 21 +++++++++++++++++++++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8d3754f..72ec152 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ import { app( get('/hello', () => 'hello'), + get('/hello/:id', ({ params }) => params.id), + get('/hello/:id/and/:name', ({ params }) => `:id is ${params.id}, :name is ${params.name}`), get('/error', () => [500, 'an error has occured']), get('/callName', ({ params }) => `Hi, ${params.name}!`), post('/callName', ({ params }) => `Hi, ${params.name}!`), @@ -39,6 +41,14 @@ curl http://localhost:8080/hello # status: 200 # body: hello +curl http://localhost:8080/hello/1 +# status: 200 +# body: 1 + +curl http://localhost:8080/hello/1/and/John +# status: 200 +# body: :id is 1, :name is John + curl http://localhost:8080/error # status: 500 # body: an error has occured @@ -160,7 +170,7 @@ interface HTTPResponse { ### Request Params - [x] URL query params (for GET) -- [ ] route params (like: `/users/:user_id/posts`) +- [x] route params (like: `/users/:user_id/posts`) - [x] x-www-form-urlencoded - [x] application/json diff --git a/example/index.ts b/example/index.ts index f8b95f5..1479106 100644 --- a/example/index.ts +++ b/example/index.ts @@ -2,6 +2,8 @@ import { app, get, post, contentType } from '../mod.ts'; app( get('/hello', () => 'hello'), + get('/hello/:id', ({ params }) => params.id), + get('/hello/:id/and/:name', ({ params }) => `:id is ${params.id}, :name is ${params.name}`), get('/error', () => [500, 'an error has occured']), get('/callName', ({ params }) => `Hi, ${params.name}!`), post('/callName', ({ params }) => `Hi, ${params.name}!`), diff --git a/mod.ts b/mod.ts index 8d6e52c..2d69072 100644 --- a/mod.ts +++ b/mod.ts @@ -87,12 +87,41 @@ export class App { return null; } - const handler = map.get(path); + const params: Params = {}; + + let handler; + + const REGEX_URI_MATCHES = /(:[^/]+)/g; + const REGEX_URI_REPLACEMENT = "([^/]+)"; + const URI_PARAM_MARKER = ':'; + + Array.from(map.keys()).forEach((endpoint) => { + if (endpoint.indexOf(URI_PARAM_MARKER) !== -1) { + const matcher = endpoint.replace(REGEX_URI_MATCHES, REGEX_URI_REPLACEMENT); + const matches = path.match(`^${matcher}$`); + + if (matches === null) { + return + } + + const names = endpoint.match(REGEX_URI_MATCHES).map(name => name.replace(URI_PARAM_MARKER, '')); + + matches.slice(1).forEach((m, i) => { + params[names[i]] = m + }); + + handler = map.get(endpoint) + } + }); + + if (!handler) { + handler = map.get(path) + } + if (!handler) { return null; } - const params: Params = {}; if (method === Method.GET) { if (search) { Object.assign(params, parseURLSearchParams(search)); diff --git a/serve_test.ts b/serve_test.ts index cecf17c..b8acb61 100644 --- a/serve_test.ts +++ b/serve_test.ts @@ -35,6 +35,27 @@ const testCases: Array = [ method: Method.GET, expected: 'basic', }, + { + name: 'valid basic handler with path parameter', + registered: get('/parameters/:param', ({ params }) => params.param), + path: 'parameters/p', + method: Method.GET, + expected: 'p', + }, + { + name: 'valid basic handler with path parameters', + registered: get('/parameters/:param1/:param2', ({ params }) => `${params.param1} ${params.param2}`), + path: 'parameters/p1/p2', + method: Method.GET, + expected: 'p1 p2', + }, + { + name: 'valid basic handler with path parameter at start', + registered: get('/:param', ({ params }) => params.param), + path: 'basic', + method: Method.GET, + expected: 'basic', + }, { name: 'valid async handler', registered: get('/async', async () => 'async'),