hapijs / hapijs/nes

Listener does not correctly handle optional & wildcard routes.

Open
#336 4 comments 0 reactions 1 assignee Claimed by @damusix View on GitHub
bug
Dominant language
JavaScript
Stars
502
Forks
86
PR merge metrics
No merged PRs in 30d

Description

### Runtime

node.js

### Runtime version

20.14.0

### Module version

14.0.0

### Last module version without issue

_No response_

### Used with

Hapi

### Any other relevant information

when adding subscriptions to the listener, wildcard paths are not handled correctly in `internals.Subscribers.prototype.add` . This leads to `internals.Listener.prototype._publish` incorrectly determining which subscribers to send the message to, due to only checking for length, and not number of parameters as wildcard parameters appear in the paramsArray as a single string and must be manually split.

This means that you can't have a greedy listener, or optional params as they won't match when going backwards, since they originally have 0 parameters provided or has multiple parameters merged within the last value of match.paramArray

potential solution:

On seeing a wildcard route, the last value of the `paramsArray` should be split on `/` and flattened into the paramsArray.

### What are you trying to achieve or the steps to reproduce?

I am trying to use a wildcard parameter to publish changes in real time from a broad view to then be filtered to more specific ones. similar to the REST spec.

An example:

model of `products`. there are two parameters:
```{
actions?: 'insert' | 'delete' | 'update'
id?: number
}
```

the route would be `/products/changes/{params*2}` or just `/products/changes/{params*}`

this route should result in this table:

| users | absolute path | desired result |
| -------- | -------- | ------- |
| 1 |/products/changes/ |should get every message send back to the route |
| 2 | /product/changes/insert | should get every `insert` message |
| 3 | /products/changes/update | should get every `update` message |
| 4 | products/changes/update/5 | should only get `update` messages for product id 5|

if you attempt to use a wildcard for multiple parameters, or an optional parameter, on a route, it still needs to be published as the full path to match the more specific filters.

### What was the result you got?

Only the fully defined path `/products/changes/updates/5` gets the message, rather than every listener leading up to that point.

### What result did you expect?

the lookup going backwards fails because it must be published to `/products/changes/update/5` to support the other conditions, and thus, only user `4` gets the message. instead of user 1, 3 and 4 even though they all matched the route.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.