Skip to content

Commit

Permalink
adds support for HTTP basic authentication (#220)
Browse files Browse the repository at this point in the history
* adds support for HTTP basic authentication

* adds end-to-end test for basic authentication
  • Loading branch information
gillesdemey authored and mcollina committed Nov 2, 2019
1 parent e3d4183 commit ff89f98
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/httpClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function Client (opts) {
this.timeout = (this.opts.timeout || 10) * 1000
this.ipc = !!this.opts.socketPath
this.secure = this.opts.protocol === 'https:'
this.auth = this.opts.auth || null

if (this.secure && this.opts.port === 80) {
this.opts.port = 443
Expand Down
5 changes: 5 additions & 0 deletions lib/httpRequestBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ function requestBuilder (defaults) {
host = hostname + ':' + port
}

if (reqData.auth) {
const encodedAuth = Buffer.from(reqData.auth).toString('base64')
headers.Authorization = `Basic ${encodedAuth}`
}

if (methods.indexOf(method) < 0) {
throw new Error(`${method} HTTP method is not supported`)
}
Expand Down
54 changes: 54 additions & 0 deletions test/basic-auth.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict'

const t = require('tap')
const split = require('split2')
const path = require('path')
const childProcess = require('child_process')
const helper = require('./helper')

const lines = [
/Running 1s test @ .*$/,
/10 connections.*$/,
/$/,
/.*/,
/Stat.*2\.5%.*50%.*97\.5%.*99%.*Avg.*Stdev.*Max.*$/,
/.*/,
/Latency.*$/,
/$/,
/.*/,
/Stat.*1%.*2\.5%.*50%.*97\.5%.*Avg.*Stdev.*Min.*$/,
/.*/,
/Req\/Sec.*$/,
/.*/,
/Bytes\/Sec.*$/,
/.*/,
/$/,
/Req\/Bytes counts sampled once per second.*$/,
/$/,
/.* requests in ([0-9]|\.)+s, .* read/
]

t.plan(lines.length * 2)

const server = helper.startBasicAuthServer()
const url = 'http://foo:bar@localhost:' + server.address().port

const child = childProcess.spawn(process.execPath, [path.join(__dirname, '..'), '-d', '1', url], {
cwd: __dirname,
env: process.env,
stdio: ['ignore', 'pipe', 'pipe'],
detached: false
})

t.tearDown(() => {
child.kill()
})

child
.stderr
.pipe(split())
.on('data', (line) => {
const regexp = lines.shift()
t.ok(regexp, 'we are expecting this line')
t.ok(regexp.test(line), 'line matches ' + regexp)
})
21 changes: 21 additions & 0 deletions test/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,32 @@ function startTlsServer () {
return server
}

function startBasicAuthServer () {
const server = http.createServer(handle)

function handle (req, res) {
if (!req.headers.authorization || req.headers.authorization.indexOf('Basic ') === -1) {
res.writeHead(401)
return res.end()
}

res.writeHead(200)
res.end('hello world')
}

server.listen(0)

server.unref()

return server
}

module.exports.startServer = startServer
module.exports.startTimeoutServer = startTimeoutServer
module.exports.startSocketDestroyingServer = startSocketDestroyingServer
module.exports.startHttpsServer = startHttpsServer
module.exports.startTrailerServer = startTrailerServer
module.exports.startTlsServer = startTlsServer
module.exports.startBasicAuthServer = startBasicAuthServer

function noop () {}
17 changes: 17 additions & 0 deletions test/httpClient.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -487,3 +487,20 @@ test('client should have 2 different requests it iterates over', (t) => {
}
})
})

test('client supports http basic authentication', (t) => {
t.plan(2)

const opts = server.address()
opts.auth = 'username:password'
const client = new Client(opts)

server.once('request', (req, res) => {
t.equal(req.headers.authorization, 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=', 'authorization header matches')
})

client.on('response', (statusCode, length) => {
t.equal(statusCode, 200, 'status code matches')
client.destroy()
})
})
14 changes: 14 additions & 0 deletions test/httpRequestBuilder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,17 @@ test('request builder should add a Content-Length header with value "[<contentLe
Buffer.from(`POST / HTTP/1.1\r\nHost: localhost:${server.address().port}\r\nConnection: keep-alive\r\nContent-Length: 33\r\n\r\n[<id>]\r\n`),
'request is okay')
})

test('request builder should allow http basic authentication', (t) => {
t.plan(1)

const opts = server.address()
opts.auth = 'username:password'

const build = RequestBuilder(opts)

const result = build()
t.same(result,
Buffer.from(`GET / HTTP/1.1\r\nHost: localhost:${server.address().port}\r\nConnection: keep-alive\r\nAuthorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=\r\n\r\n`),
'request is okay')
})

0 comments on commit ff89f98

Please sign in to comment.