Skip to content

Commit

Permalink
Merge pull request from GHSA-8qr4-xgw6-wmr3
Browse files Browse the repository at this point in the history
  • Loading branch information
RafaelGSS committed Aug 9, 2022
1 parent aef314c commit 124f7eb
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 4 deletions.
7 changes: 6 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ function makeDispatcher (fn) {
throw new InvalidArgumentError('invalid opts.path')
}

url = new URL(opts.path, util.parseOrigin(url))
let path = opts.path
if (!opts.path.startsWith('/')) {
path = `/${path}`
}

url = new URL(util.parseOrigin(url).origin + path)
} else {
if (!opts) {
opts = typeof url === 'object' ? url : {}
Expand Down
17 changes: 14 additions & 3 deletions lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,25 @@ function parseURL (url) {
const port = url.port != null
? url.port
: (url.protocol === 'https:' ? 443 : 80)
const origin = url.origin != null
let origin = url.origin != null
? url.origin
: `${url.protocol}//${url.hostname}:${port}`
const path = url.path != null
let path = url.path != null
? url.path
: `${url.pathname || ''}${url.search || ''}`

url = new URL(path, origin)
if (origin.endsWith('/')) {
origin = origin.substring(0, origin.length - 1)
}

if (path && !path.startsWith('/')) {
path = `/${path}`
}
// new URL(path, origin) is unsafe when `path` contains an absolute URL
// From https://developer.mozilla.org/en-US/docs/Web/API/URL/URL:
// If first parameter is a relative URL, second param is required, and will be used as the base URL.
// If first parameter is an absolute URL, a given second param will be ignored.
url = new URL(origin + path)
}

return url
Expand Down
151 changes: 151 additions & 0 deletions test/request.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
'use strict'

const { createServer } = require('http')
const { test } = require('tap')
const { request } = require('..')

test('no-slash/one-slash pathname should be included in req.path', async (t) => {
const pathServer = createServer((req, res) => {
t.fail('it shouldn\'t be called')
res.statusCode = 200
res.end('hello')
})

const requestedServer = createServer((req, res) => {
t.equal(`/localhost:${pathServer.address().port}`, req.url)
t.equal('GET', req.method)
t.equal(`localhost:${requestedServer.address().port}`, req.headers.host)
res.statusCode = 200
res.end('hello')
})

t.teardown(requestedServer.close.bind(requestedServer))
t.teardown(pathServer.close.bind(pathServer))

await Promise.all([
requestedServer.listen(0),
pathServer.listen(0)
])

const noSlashPathname = await request({
method: 'GET',
origin: `http://localhost:${requestedServer.address().port}`,
pathname: `localhost:${pathServer.address().port}`
})
t.equal(noSlashPathname.statusCode, 200)
const noSlashPath = await request({
method: 'GET',
origin: `http://localhost:${requestedServer.address().port}`,
path: `localhost:${pathServer.address().port}`
})
t.equal(noSlashPath.statusCode, 200)
const noSlashPath2Arg = await request(
`http://localhost:${requestedServer.address().port}`,
{ path: `localhost:${pathServer.address().port}` }
)
t.equal(noSlashPath2Arg.statusCode, 200)
const oneSlashPathname = await request({
method: 'GET',
origin: `http://localhost:${requestedServer.address().port}`,
pathname: `/localhost:${pathServer.address().port}`
})
t.equal(oneSlashPathname.statusCode, 200)
const oneSlashPath = await request({
method: 'GET',
origin: `http://localhost:${requestedServer.address().port}`,
path: `/localhost:${pathServer.address().port}`
})
t.equal(oneSlashPath.statusCode, 200)
const oneSlashPath2Arg = await request(
`http://localhost:${requestedServer.address().port}`,
{ path: `/localhost:${pathServer.address().port}` }
)
t.equal(oneSlashPath2Arg.statusCode, 200)
t.end()
})

test('protocol-relative URL as pathname should be included in req.path', async (t) => {
const pathServer = createServer((req, res) => {
t.fail('it shouldn\'t be called')
res.statusCode = 200
res.end('hello')
})

const requestedServer = createServer((req, res) => {
t.equal(`//localhost:${pathServer.address().port}`, req.url)
t.equal('GET', req.method)
t.equal(`localhost:${requestedServer.address().port}`, req.headers.host)
res.statusCode = 200
res.end('hello')
})

t.teardown(requestedServer.close.bind(requestedServer))
t.teardown(pathServer.close.bind(pathServer))

await Promise.all([
requestedServer.listen(0),
pathServer.listen(0)
])

const noSlashPathname = await request({
method: 'GET',
origin: `http://localhost:${requestedServer.address().port}`,
pathname: `//localhost:${pathServer.address().port}`
})
t.equal(noSlashPathname.statusCode, 200)
const noSlashPath = await request({
method: 'GET',
origin: `http://localhost:${requestedServer.address().port}`,
path: `//localhost:${pathServer.address().port}`
})
t.equal(noSlashPath.statusCode, 200)
const noSlashPath2Arg = await request(
`http://localhost:${requestedServer.address().port}`,
{ path: `//localhost:${pathServer.address().port}` }
)
t.equal(noSlashPath2Arg.statusCode, 200)
t.end()
})

test('Absolute URL as pathname should be included in req.path', async (t) => {
const pathServer = createServer((req, res) => {
t.fail('it shouldn\'t be called')
res.statusCode = 200
res.end('hello')
})

const requestedServer = createServer((req, res) => {
t.equal(`/http://localhost:${pathServer.address().port}`, req.url)
t.equal('GET', req.method)
t.equal(`localhost:${requestedServer.address().port}`, req.headers.host)
res.statusCode = 200
res.end('hello')
})

t.teardown(requestedServer.close.bind(requestedServer))
t.teardown(pathServer.close.bind(pathServer))

await Promise.all([
requestedServer.listen(0),
pathServer.listen(0)
])

const noSlashPathname = await request({
method: 'GET',
origin: `http://localhost:${requestedServer.address().port}`,
pathname: `http://localhost:${pathServer.address().port}`
})
t.equal(noSlashPathname.statusCode, 200)
const noSlashPath = await request({
method: 'GET',
origin: `http://localhost:${requestedServer.address().port}`,
path: `http://localhost:${pathServer.address().port}`
})
t.equal(noSlashPath.statusCode, 200)
const noSlashPath2Arg = await request(
`http://localhost:${requestedServer.address().port}`,
{ path: `http://localhost:${pathServer.address().port}` }
)
t.equal(noSlashPath2Arg.statusCode, 200)
t.end()
})

0 comments on commit 124f7eb

Please sign in to comment.