Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

find-my-way

Package Overview
Dependencies
Maintainers
2
Versions
112
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

find-my-way - npm Package Compare versions

Comparing version 6.0.0 to 6.1.0

test/issue-240.test.js

2

index.d.ts

@@ -77,2 +77,4 @@ import { IncomingMessage, ServerResponse } from 'http';

ignoreDuplicateSlashes?: boolean;
allowUnsafeRegex?: boolean;

@@ -79,0 +81,0 @@

44

index.js

@@ -86,2 +86,3 @@ 'use strict'

this.ignoreTrailingSlash = opts.ignoreTrailingSlash || false
this.ignoreDuplicateSlashes = opts.ignoreDuplicateSlashes || false
this.maxParamLength = opts.maxParamLength || 100

@@ -125,2 +126,6 @@ this.allowUnsafeRegex = opts.allowUnsafeRegex || false

if (this.ignoreDuplicateSlashes) {
path = removeDuplicateSlashes(path)
}
if (this.ignoreTrailingSlash) {

@@ -304,2 +309,6 @@ path = trimLastSlash(path)

if (this.ignoreDuplicateSlashes) {
path = removeDuplicateSlashes(path)
}
if (this.ignoreTrailingSlash) {

@@ -347,4 +356,12 @@ path = trimLastSlash(path)

// This must be run before sanitizeUrl as the resulting function
// .sliceParameter must be constructed with same URL string used
// throughout the rest of this function.
if (this.ignoreDuplicateSlashes) {
path = removeDuplicateSlashes(path)
}
let sanitizedUrl
let querystring
let shouldDecodeParam

@@ -355,2 +372,3 @@ try {

querystring = sanitizedUrl.querystring
shouldDecodeParam = sanitizedUrl.shouldDecodeParam
} catch (error) {

@@ -456,6 +474,4 @@ return this._onBadUrl(path)

let param = originPath.slice(pathIndex)
const firstPercentIndex = param.indexOf('%')
if (firstPercentIndex !== -1) {
param = safeDecodeURIComponent(param, firstPercentIndex)
if (shouldDecodeParam) {
param = safeDecodeURIComponent(param)
}

@@ -473,16 +489,10 @@

if (currentNode.kind === NODE_TYPES.PARAMETRIC) {
let paramEndIndex = pathIndex
let firstPercentIndex = -1
for (; paramEndIndex < pathLen; paramEndIndex++) {
const charCode = path.charCodeAt(paramEndIndex)
if (charCode === 47) {
break
} else if (firstPercentIndex === -1 && charCode === 37) {
firstPercentIndex = paramEndIndex - pathIndex
}
let paramEndIndex = originPath.indexOf('/', pathIndex)
if (paramEndIndex === -1) {
paramEndIndex = pathLen
}
let param = originPath.slice(pathIndex, paramEndIndex)
if (firstPercentIndex !== -1) {
param = safeDecodeURIComponent(param, firstPercentIndex)
if (shouldDecodeParam) {
param = safeDecodeURIComponent(param)
}

@@ -590,2 +600,6 @@

function removeDuplicateSlashes (path) {
return path.replace(/\/\/+/g, '/')
}
function trimLastSlash (path) {

@@ -592,0 +606,0 @@ if (path.length > 1 && path.charCodeAt(path.length - 1) === 47) {

@@ -39,2 +39,4 @@ 'use strict'

let shouldDecode = false
let shouldDecodeParam = false
let querystring = ''

@@ -52,2 +54,3 @@

} else {
shouldDecodeParam = true
// %25 - encoded % char. We need to encode one more time to prevent double decoding

@@ -71,6 +74,9 @@ if (highCharCode === 50 && lowCharCode === 53) {

const decodedPath = shouldDecode ? decodeURI(path) : path
return { path: decodedPath, querystring }
return { path: decodedPath, querystring, shouldDecodeParam }
}
function safeDecodeURIComponent (uriComponent, startIndex) {
function safeDecodeURIComponent (uriComponent) {
const startIndex = uriComponent.indexOf('%')
if (startIndex === -1) return uriComponent
let decoded = ''

@@ -77,0 +83,0 @@ let lastIndex = startIndex

{
"name": "find-my-way",
"version": "6.0.0",
"version": "6.1.0",
"description": "Crazy fast http radix based router",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -73,2 +73,16 @@ # find-my-way

Duplicate slashes can be ignored by supplying the `ignoreDuplicateSlashes` option:
```js
const router = require('find-my-way')({
ignoreDuplicateSlashes: true
})
function handler (req, res, params) {
res.end('foo')
}
// maps "/foo", "//foo", "///foo", etc to `handler`
router.on('GET', '////foo', handler)
```
Note that when `ignoreTrailingSlash` and `ignoreDuplicateSlashes` are both set to true, duplicate slashes will first be removed and then trailing slashes will, meaning `//a//b//c//` will be converted to `/a/b/c`.
You can set a custom length for parameters in parametric *(standard, regex and multi)* routes by using `maxParamLength` option, the default value is 100 characters.<br/>

@@ -75,0 +89,0 @@ *If the maximum length limit is reached, the default route will be invoked.*

@@ -31,2 +31,14 @@ 'use strict'

test('Method should be a string [ignoreDuplicateSlashes=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
try {
findMyWay.on(0, '/test', () => {})
t.fail('method shoukd be a string')
} catch (e) {
t.equal(e.message, 'Method should be a string')
}
})
test('Method should be a string (array)', t => {

@@ -56,2 +68,14 @@ t.plan(1)

test('Method should be a string (array) [ignoreDuplicateSlashes=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
try {
findMyWay.on(['GET', 0], '/test', () => {})
t.fail('method shoukd be a string')
} catch (e) {
t.equal(e.message, 'Method should be a string')
}
})
test('Path should be a string', t => {

@@ -81,2 +105,14 @@ t.plan(1)

test('Path should be a string [ignoreDuplicateSlashes=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
try {
findMyWay.on('GET', 0, () => {})
t.fail('path should be a string')
} catch (e) {
t.equal(e.message, 'Path should be a string')
}
})
test('The path could not be empty', t => {

@@ -106,2 +142,14 @@ t.plan(1)

test('The path could not be empty [ignoreDuplicateSlashes=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
try {
findMyWay.on('GET', '', () => {})
t.fail('The path could not be empty')
} catch (e) {
t.equal(e.message, 'The path could not be empty')
}
})
test('The first character of a path should be `/` or `*`', t => {

@@ -131,2 +179,14 @@ t.plan(1)

test('The first character of a path should be `/` or `*` [ignoreDuplicateSlashes=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
try {
findMyWay.on('GET', 'a', () => {})
t.fail('The first character of a path should be `/` or `*`')
} catch (e) {
t.equal(e.message, 'The first character of a path should be `/` or `*`')
}
})
test('Handler should be a function', t => {

@@ -239,2 +299,48 @@ t.plan(1)

test('Method already declared [ignoreDuplicateSlashes=true]', t => {
t.plan(2)
t.test('without duplicate slashes', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
findMyWay.on('GET', '/test', () => {})
try {
findMyWay.on('GET', '/test', () => {})
t.fail('method already declared')
} catch (e) {
t.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '//test', () => {})
t.fail('method already declared')
} catch (e) {
t.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
})
t.test('with duplicate slashes', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
findMyWay.on('GET', '//test', () => {})
try {
findMyWay.on('GET', '/test', () => {})
t.fail('method already declared')
} catch (e) {
t.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '//test', () => {})
t.fail('method already declared')
} catch (e) {
t.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
})
})
test('Method already declared nested route', t => {

@@ -318,1 +424,51 @@ t.plan(1)

})
test('Method already declared nested route [ignoreDuplicateSlashes=true]', t => {
t.plan(2)
t.test('without duplicate slashes', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/test/world', () => {})
try {
findMyWay.on('GET', '/test/hello', () => {})
t.fail('method already declared')
} catch (e) {
t.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '/test//hello', () => {})
t.fail('method already declared')
} catch (e) {
t.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
})
t.test('with duplicate slashes', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
findMyWay.on('GET', '/test/', () => {})
findMyWay.on('GET', '/test//hello', () => {})
findMyWay.on('GET', '/test//world', () => {})
try {
findMyWay.on('GET', '/test/hello', () => {})
t.fail('method already declared')
} catch (e) {
t.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '/test//hello', () => {})
t.fail('method already declared')
} catch (e) {
t.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
})
})

@@ -171,2 +171,29 @@ 'use strict'

test('off removes all routes when ignoreDuplicateSlashes is true', t => {
t.plan(6)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: true
})
findMyWay.on('GET', '//test1', () => {})
t.equal(findMyWay.routes.length, 1)
findMyWay.on('GET', '/test2', () => {})
t.equal(findMyWay.routes.length, 2)
findMyWay.off('GET', '/test1')
t.equal(findMyWay.routes.length, 1)
t.equal(
findMyWay.routes.filter((r) => r.path === '/test2').length,
1
)
t.equal(
findMyWay.routes.filter((r) => r.path === '//test2').length,
0
)
findMyWay.off('GET', '//test2')
t.equal(findMyWay.routes.length, 0)
})
test('deregister a route without children', t => {

@@ -173,0 +200,0 @@ t.plan(2)

@@ -128,5 +128,6 @@ 'use strict'

test('derigister a route with optional param', (t) => {
test('Optional Parameter with ignoreDuplicateSlashes = true', (t) => {
t.plan(4)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: true,
defaultRoute: (req, res) => {

@@ -137,2 +138,53 @@ t.fail('Should not be defaultRoute')

findMyWay.on('GET', '/test/hello/:optional?', (req, res, params) => {
if (params.optional) {
t.equal(params.optional, 'foo')
} else {
t.equal(params.optional, undefined)
}
})
findMyWay.lookup({ method: 'GET', url: '/test//hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello/foo', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test//hello//foo', headers: {} }, null)
})
test('Optional Parameter with ignoreDuplicateSlashes = false', (t) => {
t.plan(4)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: false,
defaultRoute: (req, res) => {
if (req.url === '/test//hello') {
t.same(req.params, undefined)
} else if (req.url === '/test//hello/foo') {
t.same(req.params, undefined)
}
}
})
findMyWay.on('GET', '/test/hello/:optional?', (req, res, params) => {
if (req.url === '/test/hello/') {
t.same(params, { optional: '' })
} else if (req.url === '/test/hello') {
t.same(params, {})
} else if (req.url === '/test/hello/foo') {
t.same(params, { optional: 'foo' })
}
})
findMyWay.lookup({ method: 'GET', url: '/test//hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello/foo', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test//hello/foo', headers: {} }, null)
})
test('deregister a route with optional param', (t) => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:param/b/:optional?', (req, res, params) => {})

@@ -139,0 +191,0 @@

@@ -7,5 +7,5 @@ 'use strict'

t.test('path params match', (t) => {
t.plan(12)
t.plan(24)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
const findMyWay = FindMyWay({ ignoreTrailingSlash: true, ignoreDuplicateSlashes: true })

@@ -24,8 +24,16 @@ const b1Path = function b1StaticPath () {}

t.equal(findMyWay.find('GET', '/ab1/').handler, b1Path)
t.equal(findMyWay.find('GET', '//ab1').handler, b1Path)
t.equal(findMyWay.find('GET', '//ab1//').handler, b1Path)
t.equal(findMyWay.find('GET', '/ab2').handler, b2Path)
t.equal(findMyWay.find('GET', '/ab2/').handler, b2Path)
t.equal(findMyWay.find('GET', '//ab2').handler, b2Path)
t.equal(findMyWay.find('GET', '//ab2//').handler, b2Path)
t.equal(findMyWay.find('GET', '/ac').handler, cPath)
t.equal(findMyWay.find('GET', '/ac/').handler, cPath)
t.equal(findMyWay.find('GET', '//ac').handler, cPath)
t.equal(findMyWay.find('GET', '//ac//').handler, cPath)
t.equal(findMyWay.find('GET', '/foo').handler, paramPath)
t.equal(findMyWay.find('GET', '/foo/').handler, paramPath)
t.equal(findMyWay.find('GET', '//foo').handler, paramPath)
t.equal(findMyWay.find('GET', '//foo//').handler, paramPath)

@@ -39,2 +47,10 @@ const noTrailingSlashRet = findMyWay.find('GET', '/abcdef')

t.same(trailingSlashRet.params, { pam: 'abcdef' })
const noDuplicateSlashRet = findMyWay.find('GET', '/abcdef')
t.equal(noDuplicateSlashRet.handler, paramPath)
t.same(noDuplicateSlashRet.params, { pam: 'abcdef' })
const duplicateSlashRet = findMyWay.find('GET', '//abcdef')
t.equal(duplicateSlashRet.handler, paramPath)
t.same(duplicateSlashRet.params, { pam: 'abcdef' })
})

@@ -251,2 +251,151 @@ 'use strict'

test('maps two routes when duplicate slashes should be trimmed', t => {
t.plan(21)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: true
})
findMyWay.on('GET', '//test', (req, res, params) => {
t.ok(req)
t.ok(res)
t.ok(params)
res.end('test')
})
findMyWay.on('GET', '/othertest', (req, res, params) => {
t.ok(req)
t.ok(res)
t.ok(params)
res.end('othertest')
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, err => {
t.error(err)
server.unref()
const baseURL = 'http://localhost:' + server.address().port
http.get(baseURL + '//test', async (res) => {
let body = ''
for await (const chunk of res) {
body += chunk
}
t.equal(res.statusCode, 200)
t.same(body, 'test')
})
http.get(baseURL + '/test', async (res) => {
let body = ''
for await (const chunk of res) {
body += chunk
}
t.equal(res.statusCode, 200)
t.same(body, 'test')
})
http.get(baseURL + '/othertest', async (res) => {
let body = ''
for await (const chunk of res) {
body += chunk
}
t.equal(res.statusCode, 200)
t.same(body, 'othertest')
})
http.get(baseURL + '//othertest', async (res) => {
let body = ''
for await (const chunk of res) {
body += chunk
}
t.equal(res.statusCode, 200)
t.same(body, 'othertest')
})
})
})
test('does not trim duplicate slashes when ignoreDuplicateSlashes is false', t => {
t.plan(7)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: false
})
findMyWay.on('GET', '//test', (req, res, params) => {
t.ok(req)
t.ok(res)
t.ok(params)
res.end('test')
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, err => {
t.error(err)
server.unref()
const baseURL = 'http://localhost:' + server.address().port
http.get(baseURL + '//test', async (res) => {
let body = ''
for await (const chunk of res) {
body += chunk
}
t.equal(res.statusCode, 200)
t.same(body, 'test')
})
http.get(baseURL + '/test', async (res) => {
t.equal(res.statusCode, 404)
})
})
})
test('does map // when ignoreDuplicateSlashes is true', t => {
t.plan(11)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: true
})
findMyWay.on('GET', '/', (req, res, params) => {
t.ok(req)
t.ok(res)
t.ok(params)
res.end('test')
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, err => {
t.error(err)
server.unref()
const baseURL = 'http://localhost:' + server.address().port
http.get(baseURL + '/', async (res) => {
let body = ''
for await (const chunk of res) {
body += chunk
}
t.equal(res.statusCode, 200)
t.same(body, 'test')
})
http.get(baseURL + '//', async (res) => {
let body = ''
for await (const chunk of res) {
body += chunk
}
t.equal(res.statusCode, 200)
t.same(body, 'test')
})
})
})
test('versioned routes', t => {

@@ -253,0 +402,0 @@ t.plan(3)

@@ -16,2 +16,3 @@ import { expectType } from 'tsd'

ignoreTrailingSlash: true,
ignoreDuplicateSlashes: true,
allowUnsafeRegex: false,

@@ -90,2 +91,3 @@ caseSensitive: false,

ignoreTrailingSlash: true,
ignoreDuplicateSlashes: true,
allowUnsafeRegex: false,

@@ -92,0 +94,0 @@ caseSensitive: false,

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc