fix: implement 'login' event for net.ClientRequest (#21096)

This commit is contained in:
Jeremy Apthorp 2019-11-14 10:01:18 -08:00 committed by GitHub
parent 878ab916d2
commit 4f1536479e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 445 additions and 38 deletions

View file

@ -1,5 +1,5 @@
import { expect } from 'chai'
import { net as originalNet, session, ClientRequest } from 'electron'
import { net as originalNet, session, ClientRequest, BrowserWindow } from 'electron'
import * as http from 'http'
import * as url from 'url'
import { AddressInfo } from 'net'
@ -206,6 +206,135 @@ describe('net module', () => {
urlRequest.end()
})
})
it('should emit the login event when 401', async () => {
const [user, pass] = ['user', 'pass']
const serverUrl = await respondOnce.toSingleURL((request, response) => {
if (!request.headers.authorization) {
return response.writeHead(401, { 'WWW-Authenticate': 'Basic realm="Foo"' }).end()
}
response.writeHead(200).end('ok')
})
let loginAuthInfo: any
await new Promise((resolve, reject) => {
const request = net.request({ method: 'GET', url: serverUrl })
request.on('response', (response) => {
response.on('error', reject)
response.on('data', () => {})
response.on('end', () => resolve())
})
request.on('login', (authInfo, cb) => {
loginAuthInfo = authInfo
cb(user, pass)
})
request.on('error', reject)
request.end()
})
expect(loginAuthInfo.realm).to.equal('Foo')
expect(loginAuthInfo.scheme).to.equal('basic')
})
it('should produce an error on the response object when cancelling authentication', async () => {
const serverUrl = await respondOnce.toSingleURL((request, response) => {
if (!request.headers.authorization) {
return response.writeHead(401, { 'WWW-Authenticate': 'Basic realm="Foo"' }).end()
}
response.writeHead(200).end('ok')
})
await expect(new Promise((resolve, reject) => {
const request = net.request({ method: 'GET', url: serverUrl })
request.on('response', (response) => {
response.on('error', reject)
response.on('data', () => {})
response.on('end', () => resolve())
})
request.on('login', (authInfo, cb) => {
cb()
})
request.on('error', reject)
request.end()
})).to.eventually.be.rejectedWith('net::ERR_HTTP_RESPONSE_CODE_FAILURE')
})
it('should share credentials with WebContents', async () => {
const [user, pass] = ['user', 'pass']
const serverUrl = await new Promise<string>((resolve) => {
const server = http.createServer((request, response) => {
if (!request.headers.authorization) {
return response.writeHead(401, { 'WWW-Authenticate': 'Basic realm="Foo"' }).end()
}
return response.writeHead(200).end('ok')
})
server.listen(0, '127.0.0.1', () => {
resolve(`http://127.0.0.1:${(server.address() as AddressInfo).port}`)
})
after(() => { server.close() })
})
const bw = new BrowserWindow({ show: false })
const loaded = bw.loadURL(serverUrl)
bw.webContents.on('login', (event, details, authInfo, cb) => {
event.preventDefault()
cb(user, pass)
})
await loaded
bw.close()
await new Promise((resolve, reject) => {
const request = net.request({ method: 'GET', url: serverUrl })
request.on('response', (response) => {
response.on('error', reject)
response.on('data', () => {})
response.on('end', () => resolve())
})
request.on('login', () => {
// we shouldn't receive a login event, because the credentials should
// be cached.
reject(new Error('unexpected login event'))
})
request.on('error', reject)
request.end()
})
})
it('should share proxy credentials with WebContents', async () => {
const [user, pass] = ['user', 'pass']
const proxyPort = await new Promise<number>((resolve) => {
const server = http.createServer((request, response) => {
if (!request.headers['proxy-authorization']) {
return response.writeHead(407, { 'Proxy-Authenticate': 'Basic realm="Foo"' }).end()
}
return response.writeHead(200).end('ok')
})
server.listen(0, '127.0.0.1', () => {
resolve((server.address() as AddressInfo).port)
})
after(() => { server.close() })
})
const customSession = session.fromPartition(`net-proxy-test-${Math.random()}`)
await customSession.setProxy({ proxyRules: `127.0.0.1:${proxyPort}`, proxyBypassRules: '<-loopback>' })
const bw = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
const loaded = bw.loadURL('http://127.0.0.1:9999')
bw.webContents.on('login', (event, details, authInfo, cb) => {
event.preventDefault()
cb(user, pass)
})
await loaded
bw.close()
await new Promise((resolve, reject) => {
const request = net.request({ method: 'GET', url: 'http://127.0.0.1:9999', session: customSession })
request.on('response', (response) => {
response.on('error', reject)
response.on('data', () => {})
response.on('end', () => resolve())
})
request.on('login', () => {
// we shouldn't receive a login event, because the credentials should
// be cached.
reject(new Error('unexpected login event'))
})
request.on('error', reject)
request.end()
})
})
})
describe('ClientRequest API', () => {