kwhitley / itty-router

A little router.
MIT License
1.75k stars 78 forks source link

route regex matches path but router params are not parsed correctly #46

Closed zaidoon1 closed 3 years ago

zaidoon1 commented 3 years ago

I seem to have encountered a bug with the param parsing logic for routes. This is what I have observed:

route regex:

/users/:user_id([0-9]+)/hello

url path:

/users/12345/hello

expected Request.params value:

{
  "user_id": "12345"
}

actual Request.params value:

{
  "user_id": "1234"
}

Based on my testing, it is always missing the last digit

kwhitley commented 3 years ago

Hey! Hate to be the bearer of bad news, but that's not technically a bug, as itty doesn't claim true regex support (and zero regex support within the param itself, like you've tried). In the effort of keeping itty absurdly tiny, we had to make some tough decisions - and one of those was to handle most of the cases for most* of the people, leaving all else to be covered by individual users or other, more feature-rich libraries (that are much bigger).

What the library is doing in your test case is matching the final 5 to your regex and passing the rest to the param ;)

If you wanted to stick with itty with what you're trying, I'd just recommend a middleware to check for validation:

import { Router} from 'itty-router'
import { error, missing, json } from 'itty-router-extras' 

// just for example
const USERS = {
  '1234': {
    name: 'Mittens',
    type: 'cat',
  }
}

// we create a simple middleware for validation
const withUser = req => {
  const { user_id } = req.params

  // return a 400 if fails regex match
  if (!user_id.match(/^\d+$/)) {
    return error(400, 'User ID must be numeric.')
  }

  // embed the found user in the request for future handlers
  req.user = USERS[user_id]

  // return a 404 if the lookup was unsuccessful
  if (!req.user) {
    return missing(`User ${user_id} was not found.`)
  }
}

// create a router
const router = Router()

// and add our route with middleware
router.get('/user/:user_id/hello', withUser, 
  ({ user }) => json(user)
)

// GET /user/foo/hello --> 400 "User ID must be numeric."
// GET /user/4567/hello --> 404 "User 4567 was not found."
// GET / user/1234/hello --> { name: "Mittens", type: "cat" }

Hope this helps!

zaidoon1 commented 3 years ago

ah I see. Thank you @kwhitley.