Skip to content

Commit

Permalink
Update hasConstraintStrategy method
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-tymoshenko committed May 18, 2022
1 parent c2b4e75 commit 2ac52b5
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 36 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ Constraints can be combined, and route handlers will only match if __all__ of th
<a name="custom-constraint-strategies"></a>
### Custom Constraint Strategies

Custom constraining strategies can be added and are matched against incoming requests while trying to maintain `find-my-way`'s high performance. To register a new type of constraint, you must add a new constraint strategy that knows how to match values to handlers, and that knows how to get the constraint value from a request. Register strategies when constructing a router or use the addCustomConstraintStrategy method.
Custom constraining strategies can be added and are matched against incoming requests while trying to maintain `find-my-way`'s high performance. To register a new type of constraint, you must add a new constraint strategy that knows how to match values to handlers, and that knows how to get the constraint value from a request. Register strategies when constructing a router or use the addConstraintStrategy method.

Add a custom constrain strategy when constructing a router:

Expand All @@ -192,7 +192,7 @@ const customResponseTypeStrategy = {
const router = FindMyWay({ constraints: { accept: customResponseTypeStrategy } });
```

Add a custom constraint strategy using the addCustomConstraintStrategy method:
Add a custom constraint strategy using the addConstraintStrategy method:

```js
const customResponseTypeStrategy = {
Expand All @@ -215,7 +215,7 @@ const customResponseTypeStrategy = {
}

const router = FindMyWay();
router.addCustomConstraintStrategy(customResponseTypeStrategy);
router.addConstraintStrategy(customResponseTypeStrategy);
```

Once a custom constraint strategy is registered, routes can be added that are constrained using it:
Expand Down
4 changes: 2 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ declare namespace Router {
prettyPrint(): string;
prettyPrint(opts: { commonPrefix?: boolean, includeMeta?: boolean | (string | symbol)[] }): string;

hasCustomConstraintStrategy(strategyName: string): boolean;
addCustomConstraintStrategy(constraintStrategy: ConstraintStrategy<V>): void;
hasConstraintStrategy(strategyName: string): boolean;
addConstraintStrategy(constraintStrategy: ConstraintStrategy<V>): void;

all: ShortHandRoute<V>;

Expand Down
8 changes: 4 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,12 +266,12 @@ Router.prototype._on = function _on (method, path, opts, handler, store) {
currentNode.handlerStorage.addHandler(handler, params, store, this.constrainer, constraints)
}

Router.prototype.hasCustomConstraintStrategy = function (strategyName) {
return this.constrainer.hasCustomConstraintStrategy(strategyName)
Router.prototype.hasConstraintStrategy = function (strategyName) {
return this.constrainer.hasConstraintStrategy(strategyName)
}

Router.prototype.addCustomConstraintStrategy = function (constraints) {
this.constrainer.addCustomConstraintStrategy(constraints)
Router.prototype.addConstraintStrategy = function (constraints) {
this.constrainer.addConstraintStrategy(constraints)
this._rebuild(this.routes)
}

Expand Down
13 changes: 8 additions & 5 deletions lib/constrainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,25 @@ class Constrainer {
// validate and optimize prototypes of given custom strategies
if (customStrategies) {
for (const strategy of Object.values(customStrategies)) {
this.addCustomConstraintStrategy(strategy)
this.addConstraintStrategy(strategy)
}
}
}

hasCustomConstraintStrategy (strategyName) {
hasConstraintStrategy (strategyName) {
const customConstraintStrategy = this.strategies[strategyName]
return customConstraintStrategy !== undefined && customConstraintStrategy.isCustom === true
if (customConstraintStrategy !== undefined) {
return customConstraintStrategy.isCustom || this.strategiesInUse.has(strategyName)
}
return false
}

addCustomConstraintStrategy (strategy) {
addConstraintStrategy (strategy) {
assert(typeof strategy.name === 'string' && strategy.name !== '', 'strategy.name is required.')
assert(strategy.storage && typeof strategy.storage === 'function', 'strategy.storage function is required.')
assert(strategy.deriveConstraint && typeof strategy.deriveConstraint === 'function', 'strategy.deriveConstraint function is required.')

if (this.hasCustomConstraintStrategy(strategy.name)) {
if (this.strategies[strategy.name] && this.strategies[strategy.name].isCustom) {
throw new Error(`There is already exists a custom constraint with the name ${strategy.name}.`)
}

Expand Down
20 changes: 16 additions & 4 deletions test/constraint.custom-versioning.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ test('A route could support multiple versions (find) / 1 (add strategy outside c

const findMyWay = FindMyWay()

findMyWay.addCustomConstraintStrategy(customVersioning)
findMyWay.addConstraintStrategy(customVersioning)

findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=2' } }, noop)
findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=3' } }, noop)
Expand Down Expand Up @@ -84,7 +84,7 @@ test('Overriding default strategies uses the custom deriveConstraint function (a

const findMyWay = FindMyWay()

findMyWay.addCustomConstraintStrategy(customVersioning)
findMyWay.addConstraintStrategy(customVersioning)

findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=2' } }, (req, res, params) => {
t.equal(req.headers.accept, 'application/vnd.example.api+json;version=2')
Expand All @@ -111,9 +111,21 @@ test('Overriding custom strategies throws as error (add strategy outside constru

const findMyWay = FindMyWay()

findMyWay.addCustomConstraintStrategy(customVersioning)
findMyWay.addConstraintStrategy(customVersioning)

t.throws(() => findMyWay.addCustomConstraintStrategy(customVersioning),
t.throws(() => findMyWay.addConstraintStrategy(customVersioning),
'There is already exists a custom constraint with the name version.'
)
})

test('Overriding default strategies after defining a route with constraint', t => {
t.plan(1)

const findMyWay = FindMyWay()

findMyWay.on('GET', '/', { constraints: { host: 'fastify.io', version: '1.0.0' } }, () => {})

t.throws(() => findMyWay.addConstraintStrategy(customVersioning),
'There is already exists a route with version constraint.'
)
})
25 changes: 11 additions & 14 deletions test/constraint.custom.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ test('A route could support a custom constraint strategy (add strategy outside c

const findMyWay = FindMyWay()

findMyWay.addCustomConstraintStrategy(customHeaderConstraint)
findMyWay.addConstraintStrategy(customHeaderConstraint)

findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl' } }, alpha)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'wget' } }, beta)
Expand Down Expand Up @@ -79,7 +79,7 @@ test('A route could support a custom constraint strategy while versioned (add st

const findMyWay = FindMyWay()

findMyWay.addCustomConstraintStrategy(customHeaderConstraint)
findMyWay.addConstraintStrategy(customHeaderConstraint)

findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '1.0.0' } }, alpha)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '2.0.0' } }, beta)
Expand Down Expand Up @@ -124,7 +124,7 @@ test('A route could support a custom constraint strategy while versioned and hos

const findMyWay = FindMyWay()

findMyWay.addCustomConstraintStrategy(customHeaderConstraint)
findMyWay.addConstraintStrategy(customHeaderConstraint)

findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '1.0.0', host: 'fastify.io' } }, alpha)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '2.0.0', host: 'fastify.io' } }, beta)
Expand Down Expand Up @@ -171,7 +171,7 @@ test('Custom constraint strategies can set mustMatchWhenDerived flag to true whi
}
})

findMyWay.addCustomConstraintStrategy({
findMyWay.addConstraintStrategy({
...customHeaderConstraint,
mustMatchWhenDerived: true
})
Expand Down Expand Up @@ -212,7 +212,7 @@ test('Custom constraint strategies can set mustMatchWhenDerived flag to true whi
}
})

findMyWay.addCustomConstraintStrategy({
findMyWay.addConstraintStrategy({
...customHeaderConstraint,
mustMatchWhenDerived: true
})
Expand Down Expand Up @@ -253,7 +253,7 @@ test('Custom constraint strategies can set mustMatchWhenDerived flag to false wh
}
})

findMyWay.addCustomConstraintStrategy({
findMyWay.addConstraintStrategy({
...customHeaderConstraint,
mustMatchWhenDerived: true
})
Expand All @@ -264,14 +264,11 @@ test('Custom constraint strategies can set mustMatchWhenDerived flag to false wh
})

test('Has constraint strategy method test', t => {
t.plan(1)
t.plan(2)

const findMyWay = FindMyWay({
defaultRoute (req, res) {
t.pass()
}
})
const findMyWay = FindMyWay()

findMyWay.addCustomConstraintStrategy(customHeaderConstraint)
t.same(findMyWay.hasCustomConstraintStrategy(customHeaderConstraint.name), true)
t.same(findMyWay.hasConstraintStrategy(customHeaderConstraint.name), false)
findMyWay.addConstraintStrategy(customHeaderConstraint)
t.same(findMyWay.hasConstraintStrategy(customHeaderConstraint.name), true)
})
16 changes: 13 additions & 3 deletions test/constraints.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,20 @@ test('Routes with multiple constraints are matched before routes with one constr
})

test('Has constraint strategy method test', t => {
t.plan(2)
t.plan(6)

const findMyWay = FindMyWay()

t.same(findMyWay.hasCustomConstraintStrategy('version'), false)
t.same(findMyWay.hasCustomConstraintStrategy('host'), false)
t.same(findMyWay.hasConstraintStrategy('version'), false)
t.same(findMyWay.hasConstraintStrategy('host'), false)

findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, () => {})

t.same(findMyWay.hasConstraintStrategy('version'), false)
t.same(findMyWay.hasConstraintStrategy('host'), true)

findMyWay.on('GET', '/', { constraints: { host: 'fastify.io', version: '1.0.0' } }, () => {})

t.same(findMyWay.hasConstraintStrategy('version'), true)
t.same(findMyWay.hasConstraintStrategy('host'), true)
})
2 changes: 1 addition & 1 deletion test/types/router.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ let http2Res!: Http2ServerResponse;
expectType<void>(router.on('GET', '/', () => {}, {}))
expectType<void>(router.on('GET', '/', { constraints: { version: '1.0.0' }}, () => {}, {}))

expectType<void>(router.addCustomConstraintStrategy(constraints.foo))
expectType<void>(router.addConstraintStrategy(constraints.foo))

expectType<void>(router.get('/', () => {}))
expectType<void>(router.get('/', { constraints: { version: '1.0.0' }}, () => {}))
Expand Down

0 comments on commit 2ac52b5

Please sign in to comment.