electron/spec/api-net-spec.js

1266 lines
39 KiB
JavaScript
Raw Normal View History

2016-10-05 13:06:35 +00:00
const assert = require('assert')
2016-10-06 12:32:20 +00:00
const {remote} = require('electron')
const {ipcRenderer} = require('electron')
const http = require('http')
const url = require('url')
2016-10-06 12:32:20 +00:00
const {net} = remote
const {session} = remote
2016-10-05 13:06:35 +00:00
2016-10-12 10:29:25 +00:00
function randomBuffer (size, start, end) {
2016-10-07 14:34:36 +00:00
start = start || 0
end = end || 255
let range = 1 + end - start
const buffer = Buffer.allocUnsafe(size)
for (let i = 0; i < size; ++i) {
2016-10-12 10:29:25 +00:00
buffer[i] = start + Math.floor(Math.random() * range)
2016-10-07 14:34:36 +00:00
}
2016-10-12 10:29:25 +00:00
return buffer
2016-10-07 14:34:36 +00:00
}
2016-10-12 10:29:25 +00:00
function randomString (length) {
2016-10-07 14:34:36 +00:00
let buffer = randomBuffer(length, '0'.charCodeAt(0), 'z'.charCodeAt(0))
2016-10-12 10:29:25 +00:00
return buffer.toString()
2016-10-07 14:34:36 +00:00
}
const kOneKiloByte = 1024
const kOneMegaByte = kOneKiloByte * kOneKiloByte
2016-10-12 10:29:25 +00:00
describe('net module', function () {
// this.timeout(0)
2016-10-12 10:29:25 +00:00
describe('HTTP basics', function () {
let server
beforeEach(function (done) {
server = http.createServer()
server.listen(0, '127.0.0.1', function () {
server.url = 'http://127.0.0.1:' + server.address().port
done()
})
})
afterEach(function () {
2016-10-12 10:29:25 +00:00
server.close(function () {
})
server = null
})
2016-10-12 10:29:25 +00:00
it('should be able to issue a basic GET request', function (done) {
const requestUrl = '/requestUrl'
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert.equal(request.method, 'GET')
2016-10-12 10:29:25 +00:00
response.end()
break
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
const urlRequest = net.request(`${server.url}${requestUrl}`)
urlRequest.on('response', function (response) {
assert.equal(response.statusCode, 200)
2016-10-07 14:34:36 +00:00
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
response.on('end', function () {
done()
})
2016-10-07 14:34:36 +00:00
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should be able to issue a basic POST request', function (done) {
const requestUrl = '/requestUrl'
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert.equal(request.method, 'POST')
2016-10-12 10:29:25 +00:00
response.end()
break
default:
assert(false)
}
})
const urlRequest = net.request({
method: 'POST',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
assert.equal(response.statusCode, 200)
2016-10-07 14:34:36 +00:00
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
response.on('end', function () {
done()
})
2016-10-07 14:34:36 +00:00
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should fetch correct data in a GET request', function (done) {
const requestUrl = '/requestUrl'
const bodyData = 'Hello World!'
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert.equal(request.method, 'GET')
2016-10-12 10:29:25 +00:00
response.write(bodyData)
response.end()
break
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
const urlRequest = net.request(`${server.url}${requestUrl}`)
urlRequest.on('response', function (response) {
let expectedBodyData = ''
assert.equal(response.statusCode, 200)
2016-10-07 14:34:36 +00:00
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
expectedBodyData += chunk.toString()
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
response.on('end', function () {
assert.equal(expectedBodyData, bodyData)
done()
})
2016-10-07 14:34:36 +00:00
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should post the correct data in a POST request', function (done) {
const requestUrl = '/requestUrl'
const bodyData = 'Hello World!'
server.on('request', function (request, response) {
let postedBodyData = ''
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert.equal(request.method, 'POST')
2016-10-12 10:29:25 +00:00
request.on('data', function (chunk) {
postedBodyData += chunk.toString()
})
2016-10-12 10:29:25 +00:00
request.on('end', function () {
assert.equal(postedBodyData, bodyData)
response.end()
})
2016-10-12 10:29:25 +00:00
break
default:
assert(false)
}
})
const urlRequest = net.request({
method: 'POST',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
assert.equal(response.statusCode, 200)
2016-10-07 14:34:36 +00:00
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
response.on('end', function () {
done()
})
2016-10-07 14:34:36 +00:00
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.write(bodyData)
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should support chunked encoding', function (done) {
const requestUrl = '/requestUrl'
server.on('request', function (request, response) {
2016-10-07 14:34:36 +00:00
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
2016-10-07 14:34:36 +00:00
response.statusCode = 200
response.statusMessage = 'OK'
response.chunkedEncoding = true
assert.equal(request.method, 'POST')
assert.equal(request.headers['transfer-encoding'], 'chunked')
assert(!request.headers['content-length'])
2016-10-12 10:29:25 +00:00
request.on('data', function (chunk) {
2016-10-07 14:34:36 +00:00
response.write(chunk)
})
2016-10-12 10:29:25 +00:00
request.on('end', function (chunk) {
response.end(chunk)
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
break
2016-10-07 14:34:36 +00:00
default:
assert(false)
2016-10-07 14:34:36 +00:00
}
})
const urlRequest = net.request({
method: 'POST',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
let chunkIndex = 0
let chunkCount = 100
let sentChunks = []
let receivedChunks = []
urlRequest.on('response', function (response) {
2016-10-07 14:34:36 +00:00
assert.equal(response.statusCode, 200)
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
receivedChunks.push(chunk)
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
response.on('end', function () {
let sentData = Buffer.concat(sentChunks)
let receivedData = Buffer.concat(receivedChunks)
assert.equal(sentData.toString(), receivedData.toString())
assert.equal(chunkIndex, chunkCount)
2016-10-07 14:34:36 +00:00
done()
})
response.resume()
})
urlRequest.chunkedEncoding = true
2016-10-12 10:29:25 +00:00
while (chunkIndex < chunkCount) {
++chunkIndex
2016-10-07 14:34:36 +00:00
let chunk = randomBuffer(kOneKiloByte)
2016-10-12 10:29:25 +00:00
sentChunks.push(chunk)
2016-10-07 14:34:36 +00:00
assert(urlRequest.write(chunk))
}
2016-10-12 10:29:25 +00:00
urlRequest.end()
2016-10-07 14:34:36 +00:00
})
})
2016-10-07 14:34:36 +00:00
2016-10-12 10:29:25 +00:00
describe('ClientRequest API', function () {
2016-10-07 14:34:36 +00:00
let server
beforeEach(function (done) {
server = http.createServer()
server.listen(0, '127.0.0.1', function () {
server.url = 'http://127.0.0.1:' + server.address().port
done()
})
})
afterEach(function () {
2016-10-12 10:29:25 +00:00
server.close(function () {
2016-10-07 14:34:36 +00:00
})
server = null
2016-10-11 17:16:23 +00:00
session.defaultSession.webRequest.onBeforeRequest(null)
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
it('request/response objects should emit expected events', function (done) {
const requestUrl = '/requestUrl'
let bodyData = randomString(kOneMegaByte)
server.on('request', function (request, response) {
2016-10-07 14:34:36 +00:00
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
2016-10-07 14:34:36 +00:00
response.statusCode = 200
response.statusMessage = 'OK'
2016-10-12 10:29:25 +00:00
response.write(bodyData)
response.end()
break
2016-10-07 14:34:36 +00:00
default:
assert(false)
2016-10-07 14:34:36 +00:00
}
})
2016-10-12 10:29:25 +00:00
let requestResponseEventEmitted = false
let requestFinishEventEmitted = false
let requestCloseEventEmitted = false
let responseDataEventEmitted = false
let responseEndEventEmitted = false
2016-10-07 14:34:36 +00:00
2016-10-12 10:29:25 +00:00
function maybeDone (done) {
if (!requestCloseEventEmitted || !responseEndEventEmitted) {
2016-10-07 14:34:36 +00:00
return
}
2016-10-12 10:29:25 +00:00
assert(requestResponseEventEmitted)
assert(requestFinishEventEmitted)
assert(requestCloseEventEmitted)
assert(responseDataEventEmitted)
assert(responseEndEventEmitted)
2016-10-07 14:34:36 +00:00
done()
}
2016-10-05 13:06:35 +00:00
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
2016-10-07 14:34:36 +00:00
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
requestResponseEventEmitted = true
2016-10-05 13:06:35 +00:00
const statusCode = response.statusCode
assert.equal(statusCode, 200)
2016-10-12 10:29:25 +00:00
let buffers = []
response.pause()
response.on('data', function (chunk) {
2016-10-07 14:34:36 +00:00
buffers.push(chunk)
2016-10-12 10:29:25 +00:00
responseDataEventEmitted = true
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
response.on('end', function () {
let receivedBodyData = Buffer.concat(buffers)
assert(receivedBodyData.toString() === bodyData)
responseEndEventEmitted = true
2016-10-07 14:34:36 +00:00
maybeDone(done)
})
2016-10-12 10:29:25 +00:00
response.resume()
response.on('error', function (error) {
assert.ifError(error)
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
response.on('aborted', function () {
2016-10-07 14:34:36 +00:00
assert(false)
})
})
2016-10-12 10:29:25 +00:00
urlRequest.on('finish', function () {
requestFinishEventEmitted = true
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
urlRequest.on('error', function (error) {
assert.ifError(error)
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
urlRequest.on('abort', function () {
assert(false)
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
urlRequest.on('close', function () {
requestCloseEventEmitted = true
2016-10-07 14:34:36 +00:00
maybeDone(done)
})
2016-10-12 10:29:25 +00:00
urlRequest.end()
2016-10-07 14:34:36 +00:00
})
2016-10-12 10:29:25 +00:00
it('should be able to set a custom HTTP request header before first write', function (done) {
const requestUrl = '/requestUrl'
const customHeaderName = 'Some-Custom-Header-Name'
const customHeaderValue = 'Some-Customer-Header-Value'
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert.equal(request.headers[customHeaderName.toLowerCase()],
customHeaderValue)
response.statusCode = 200
response.statusMessage = 'OK'
2016-10-12 10:29:25 +00:00
response.end()
break
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
const statusCode = response.statusCode
assert.equal(statusCode, 200)
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
})
response.on('end', function () {
done()
})
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.setHeader(customHeaderName, customHeaderValue)
assert.equal(urlRequest.getHeader(customHeaderName),
customHeaderValue)
assert.equal(urlRequest.getHeader(customHeaderName.toLowerCase()),
customHeaderValue)
urlRequest.write('')
assert.equal(urlRequest.getHeader(customHeaderName),
customHeaderValue)
assert.equal(urlRequest.getHeader(customHeaderName.toLowerCase()),
customHeaderValue)
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should not be able to set a custom HTTP request header after first write', function (done) {
const requestUrl = '/requestUrl'
const customHeaderName = 'Some-Custom-Header-Name'
const customHeaderValue = 'Some-Customer-Header-Value'
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert(!request.headers[customHeaderName.toLowerCase()])
response.statusCode = 200
response.statusMessage = 'OK'
2016-10-12 10:29:25 +00:00
response.end()
break
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
const statusCode = response.statusCode
assert.equal(statusCode, 200)
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
})
response.on('end', function () {
done()
})
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.write('')
assert.throws(() => {
urlRequest.setHeader(customHeaderName, customHeaderValue)
})
2016-10-12 10:29:25 +00:00
assert(!urlRequest.getHeader(customHeaderName))
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should be able to remove a custom HTTP request header before first write', function (done) {
const requestUrl = '/requestUrl'
const customHeaderName = 'Some-Custom-Header-Name'
const customHeaderValue = 'Some-Customer-Header-Value'
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert(!request.headers[customHeaderName.toLowerCase()])
response.statusCode = 200
response.statusMessage = 'OK'
2016-10-12 10:29:25 +00:00
response.end()
break
default:
2016-10-12 10:29:25 +00:00
assert(false)
}
})
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
const statusCode = response.statusCode
assert.equal(statusCode, 200)
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
})
response.on('end', function () {
done()
})
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.setHeader(customHeaderName, customHeaderValue)
assert.equal(urlRequest.getHeader(customHeaderName),
customHeaderValue)
urlRequest.removeHeader(customHeaderName)
assert(!urlRequest.getHeader(customHeaderName))
urlRequest.write('')
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should not be able to remove a custom HTTP request header after first write', function (done) {
const requestUrl = '/requestUrl'
const customHeaderName = 'Some-Custom-Header-Name'
const customHeaderValue = 'Some-Customer-Header-Value'
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert.equal(request.headers[customHeaderName.toLowerCase()],
customHeaderValue)
response.statusCode = 200
response.statusMessage = 'OK'
2016-10-12 10:29:25 +00:00
response.end()
break
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
const statusCode = response.statusCode
assert.equal(statusCode, 200)
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
})
response.on('end', function () {
done()
})
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.setHeader(customHeaderName, customHeaderValue)
assert.equal(urlRequest.getHeader(customHeaderName),
customHeaderValue)
urlRequest.write('')
assert.throws(function () {
urlRequest.removeHeader(customHeaderName)
})
2016-10-12 10:29:25 +00:00
assert.equal(urlRequest.getHeader(customHeaderName),
customHeaderValue)
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should be able to abort an HTTP request before first write', function (done) {
const requestUrl = '/requestUrl'
server.on('request', function (request, response) {
assert(false)
})
2016-10-12 10:29:25 +00:00
let requestAbortEventEmitted = false
let requestCloseEventEmitted = false
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
assert(false)
})
2016-10-12 10:29:25 +00:00
urlRequest.on('finish', function () {
assert(false)
})
2016-10-12 10:29:25 +00:00
urlRequest.on('error', function () {
assert(false)
})
2016-10-12 10:29:25 +00:00
urlRequest.on('abort', function () {
requestAbortEventEmitted = true
})
2016-10-12 10:29:25 +00:00
urlRequest.on('close', function () {
requestCloseEventEmitted = true
assert(requestAbortEventEmitted)
assert(requestCloseEventEmitted)
done()
})
urlRequest.abort()
assert(!urlRequest.write(''))
2016-10-12 10:29:25 +00:00
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('it should be able to abort an HTTP request before request end', function (done) {
const requestUrl = '/requestUrl'
let requestReceivedByServer = false
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
requestReceivedByServer = true
cancelRequest()
break
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
let requestAbortEventEmitted = false
let requestCloseEventEmitted = false
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
assert(false)
})
2016-10-12 10:29:25 +00:00
urlRequest.on('finish', function () {
assert(false)
})
2016-10-12 10:29:25 +00:00
urlRequest.on('error', function () {
assert(false)
})
2016-10-12 10:29:25 +00:00
urlRequest.on('abort', function () {
requestAbortEventEmitted = true
})
2016-10-12 10:29:25 +00:00
urlRequest.on('close', function () {
requestCloseEventEmitted = true
assert(requestReceivedByServer)
assert(requestAbortEventEmitted)
assert(requestCloseEventEmitted)
done()
})
urlRequest.chunkedEncoding = true
urlRequest.write(randomString(kOneKiloByte))
2016-10-12 10:29:25 +00:00
function cancelRequest () {
urlRequest.abort()
}
})
2016-10-12 10:29:25 +00:00
it('it should be able to abort an HTTP request after request end and before response', function (done) {
const requestUrl = '/requestUrl'
let requestReceivedByServer = false
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
requestReceivedByServer = true
cancelRequest()
process.nextTick(() => {
response.statusCode = 200
response.statusMessage = 'OK'
2016-10-12 10:29:25 +00:00
response.end()
})
2016-10-12 10:29:25 +00:00
break
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
let requestAbortEventEmitted = false
let requestFinishEventEmitted = false
let requestCloseEventEmitted = false
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
assert(false)
})
2016-10-12 10:29:25 +00:00
urlRequest.on('finish', function () {
requestFinishEventEmitted = true
})
2016-10-12 10:29:25 +00:00
urlRequest.on('error', function () {
assert(false)
})
2016-10-12 10:29:25 +00:00
urlRequest.on('abort', function () {
requestAbortEventEmitted = true
})
2016-10-12 10:29:25 +00:00
urlRequest.on('close', function () {
requestCloseEventEmitted = true
assert(requestFinishEventEmitted)
assert(requestReceivedByServer)
assert(requestAbortEventEmitted)
assert(requestCloseEventEmitted)
done()
})
urlRequest.end(randomString(kOneKiloByte))
2016-10-12 10:29:25 +00:00
function cancelRequest () {
urlRequest.abort()
}
})
2016-10-12 10:29:25 +00:00
it('it should be able to abort an HTTP request after response start', function (done) {
const requestUrl = '/requestUrl'
let requestReceivedByServer = false
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
requestReceivedByServer = true
response.statusCode = 200
response.statusMessage = 'OK'
response.write(randomString(kOneKiloByte))
break
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
let requestFinishEventEmitted = false
let requestResponseEventEmitted = false
let requestAbortEventEmitted = false
let requestCloseEventEmitted = false
let responseAbortedEventEmitted = false
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
requestResponseEventEmitted = true
const statusCode = response.statusCode
assert.equal(statusCode, 200)
2016-10-12 10:29:25 +00:00
response.pause()
response.on('data', function (chunk) {
})
2016-10-12 10:29:25 +00:00
response.on('end', function () {
assert(false)
})
2016-10-12 10:29:25 +00:00
response.resume()
response.on('error', function () {
assert(false)
})
2016-10-12 10:29:25 +00:00
response.on('aborted', function () {
responseAbortedEventEmitted = true
})
urlRequest.abort()
})
2016-10-12 10:29:25 +00:00
urlRequest.on('finish', function () {
requestFinishEventEmitted = true
})
2016-10-12 10:29:25 +00:00
urlRequest.on('error', function () {
assert(false)
})
2016-10-12 10:29:25 +00:00
urlRequest.on('abort', function () {
requestAbortEventEmitted = true
})
urlRequest.on('close', function () {
requestCloseEventEmitted = true
assert(requestFinishEventEmitted, 'request should emit "finish" event')
assert(requestReceivedByServer, 'request should be received by the server')
assert(requestResponseEventEmitted, '"response" event should be emitted')
assert(requestAbortEventEmitted, 'request should emit "abort" event')
assert(responseAbortedEventEmitted, 'response should emit "aborted" event')
assert(requestCloseEventEmitted, 'request should emit "close" event')
done()
})
urlRequest.end(randomString(kOneKiloByte))
})
2016-10-12 10:29:25 +00:00
it('abort event should be emitted at most once', function (done) {
const requestUrl = '/requestUrl'
let requestReceivedByServer = false
server.on('request', function (request, response) {
2016-10-11 13:25:26 +00:00
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
requestReceivedByServer = true
cancelRequest()
break
2016-10-11 13:25:26 +00:00
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
let requestFinishEventEmitted = false
let requestAbortEventCount = 0
let requestCloseEventEmitted = false
2016-10-11 13:25:26 +00:00
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
2016-10-11 13:25:26 +00:00
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
2016-10-11 13:25:26 +00:00
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
2016-10-11 13:25:26 +00:00
assert(false)
})
2016-10-12 10:29:25 +00:00
urlRequest.on('finish', function () {
requestFinishEventEmitted = true
2016-10-11 13:25:26 +00:00
})
2016-10-12 10:29:25 +00:00
urlRequest.on('error', function () {
assert(false)
2016-10-11 13:25:26 +00:00
})
2016-10-12 10:29:25 +00:00
urlRequest.on('abort', function () {
++requestAbortEventCount
2016-10-11 13:25:26 +00:00
urlRequest.abort()
})
2016-10-12 10:29:25 +00:00
urlRequest.on('close', function () {
requestCloseEventEmitted = true
2016-10-11 13:25:26 +00:00
// Let all pending async events to be emitted
2016-10-12 10:29:25 +00:00
setTimeout(function () {
assert(requestFinishEventEmitted)
assert(requestReceivedByServer)
assert.equal(requestAbortEventCount, 1)
assert(requestCloseEventEmitted)
2016-10-11 13:25:26 +00:00
done()
}, 500)
})
urlRequest.end(randomString(kOneKiloByte))
2016-10-12 10:29:25 +00:00
function cancelRequest () {
2016-10-11 13:25:26 +00:00
urlRequest.abort()
urlRequest.abort()
}
})
2016-10-12 10:29:25 +00:00
it('Requests should be intercepted by webRequest module', function (done) {
const requestUrl = '/requestUrl'
const redirectUrl = '/redirectUrl'
let requestIsRedirected = false
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert(false)
break
2016-10-12 10:29:25 +00:00
case redirectUrl:
requestIsRedirected = true
response.end()
break
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
let requestIsIntercepted = false
session.defaultSession.webRequest.onBeforeRequest(
2016-10-12 10:29:25 +00:00
function (details, callback) {
if (details.url === `${server.url}${requestUrl}`) {
requestIsIntercepted = true
callback({
2016-10-12 10:29:25 +00:00
redirectURL: `${server.url}${redirectUrl}`
})
} else {
2016-10-12 10:29:25 +00:00
callback({
cancel: false
})
}
2016-10-12 10:29:25 +00:00
})
2016-10-12 10:29:25 +00:00
const urlRequest = net.request(`${server.url}${requestUrl}`)
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
assert.equal(response.statusCode, 200)
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
})
2016-10-12 10:29:25 +00:00
response.on('end', function () {
assert(requestIsRedirected, 'The server should receive a request to the forward URL')
assert(requestIsIntercepted, 'The request should be intercepted by the webRequest module')
done()
})
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should to able to create and intercept a request on a custom session', function (done) {
const requestUrl = '/requestUrl'
const redirectUrl = '/redirectUrl'
const customSessionName = 'custom-session'
let requestIsRedirected = false
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert(false)
break
2016-10-12 10:29:25 +00:00
case redirectUrl:
requestIsRedirected = true
response.end()
break
default:
assert(false)
}
})
session.defaultSession.webRequest.onBeforeRequest(
2016-10-12 10:29:25 +00:00
function (details, callback) {
assert(false, 'Request should not be intercepted by the default session')
2016-10-12 10:29:25 +00:00
})
2016-10-12 10:29:25 +00:00
let customSession = session.fromPartition(customSessionName, {
cache: false
})
2016-10-12 10:29:25 +00:00
let requestIsIntercepted = false
customSession.webRequest.onBeforeRequest(
function (details, callback) {
if (details.url === `${server.url}${requestUrl}`) {
requestIsIntercepted = true
callback({
2016-10-12 10:29:25 +00:00
redirectURL: `${server.url}${redirectUrl}`
})
} else {
2016-10-12 10:29:25 +00:00
callback({
cancel: false
})
}
2016-10-12 10:29:25 +00:00
})
const urlRequest = net.request({
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`,
session: customSessionName
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
assert.equal(response.statusCode, 200)
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
})
2016-10-12 10:29:25 +00:00
response.on('end', function () {
assert(requestIsRedirected, 'The server should receive a request to the forward URL')
assert(requestIsIntercepted, 'The request should be intercepted by the webRequest module')
done()
})
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should be able to create a request with options', function (done) {
const requestUrl = '/'
const customHeaderName = 'Some-Custom-Header-Name'
const customHeaderValue = 'Some-Customer-Header-Value'
server.on('request', function (request, response) {
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
assert.equal(request.method, 'GET')
2016-10-12 10:29:25 +00:00
assert.equal(request.headers[customHeaderName.toLowerCase()],
customHeaderValue)
2016-10-11 17:16:23 +00:00
response.statusCode = 200
response.statusMessage = 'OK'
2016-10-12 10:29:25 +00:00
response.end()
break
default:
assert(false)
}
})
2016-10-11 17:16:23 +00:00
const serverUrl = url.parse(server.url)
let options = {
2016-10-11 17:16:23 +00:00
port: serverUrl.port,
hostname: '127.0.0.1',
headers: {}
}
2016-10-12 10:29:25 +00:00
options.headers[customHeaderName] = customHeaderValue
const urlRequest = net.request(options)
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
assert.equal(response.statusCode, 200)
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
})
2016-10-12 10:29:25 +00:00
response.on('end', function () {
done()
})
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.end()
})
2016-10-12 10:29:25 +00:00
it('should be able to pipe a readable stream into a net request', function (done) {
const nodeRequestUrl = '/nodeRequestUrl'
const netRequestUrl = '/netRequestUrl'
const bodyData = randomString(kOneMegaByte)
let netRequestReceived = false
let netRequestEnded = false
server.on('request', function (request, response) {
2016-10-11 13:25:26 +00:00
switch (request.url) {
2016-10-12 10:29:25 +00:00
case nodeRequestUrl:
response.write(bodyData)
response.end()
break
case netRequestUrl:
netRequestReceived = true
let receivedBodyData = ''
request.on('data', function (chunk) {
receivedBodyData += chunk.toString()
2016-10-11 13:25:26 +00:00
})
2016-10-12 10:29:25 +00:00
request.on('end', function (chunk) {
netRequestEnded = true
2016-10-11 13:25:26 +00:00
if (chunk) {
2016-10-12 10:29:25 +00:00
receivedBodyData += chunk.toString()
2016-10-11 13:25:26 +00:00
}
2016-10-12 10:29:25 +00:00
assert.equal(receivedBodyData, bodyData)
2016-10-11 13:25:26 +00:00
response.end()
})
2016-10-12 10:29:25 +00:00
break
2016-10-11 13:25:26 +00:00
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
let nodeRequest = http.request(`${server.url}${nodeRequestUrl}`)
nodeRequest.on('response', function (nodeResponse) {
const netRequest = net.request(`${server.url}${netRequestUrl}`)
netRequest.on('response', function (netResponse) {
2016-10-11 13:25:26 +00:00
assert.equal(netResponse.statusCode, 200)
netResponse.pause()
2016-10-12 10:29:25 +00:00
netResponse.on('data', function (chunk) {
2016-10-11 13:25:26 +00:00
})
2016-10-12 10:29:25 +00:00
netResponse.on('end', function () {
assert(netRequestReceived)
assert(netRequestEnded)
2016-10-11 13:25:26 +00:00
done()
})
netResponse.resume()
})
nodeResponse.pipe(netRequest)
})
nodeRequest.end()
})
2016-10-11 17:16:23 +00:00
it('should emit error event on server socket close', function (done) {
const requestUrl = '/requestUrl'
server.on('request', function (request, response) {
switch (request.url) {
case requestUrl:
request.socket.destroy()
break
default:
assert(false)
}
})
let requestErrorEventEmitted = false
const urlRequest = net.request(`${server.url}${requestUrl}`)
urlRequest.on('error', function (error) {
assert(error)
requestErrorEventEmitted = true
})
urlRequest.on('close', function () {
assert(requestErrorEventEmitted)
done()
})
urlRequest.end()
})
2016-10-11 13:25:26 +00:00
})
2016-10-12 10:29:25 +00:00
describe('IncomingMessage API', function () {
2016-10-11 17:16:23 +00:00
let server
2016-10-11 13:25:26 +00:00
beforeEach(function (done) {
server = http.createServer()
server.listen(0, '127.0.0.1', function () {
server.url = 'http://127.0.0.1:' + server.address().port
done()
})
2016-10-07 14:34:36 +00:00
})
2016-10-11 13:25:26 +00:00
afterEach(function () {
2016-10-11 17:16:23 +00:00
server.close()
2016-10-11 13:25:26 +00:00
server = null
})
2016-10-12 10:29:25 +00:00
it('response object should implement the IncomingMessage API', function (done) {
const requestUrl = '/requestUrl'
const customHeaderName = 'Some-Custom-Header-Name'
const customHeaderValue = 'Some-Customer-Header-Value'
server.on('request', function (request, response) {
2016-10-11 13:25:26 +00:00
switch (request.url) {
2016-10-12 10:29:25 +00:00
case requestUrl:
2016-10-11 13:25:26 +00:00
response.statusCode = 200
response.statusMessage = 'OK'
2016-10-12 10:29:25 +00:00
response.setHeader(customHeaderName, customHeaderValue)
response.end()
break
2016-10-11 13:25:26 +00:00
default:
assert(false)
}
})
2016-10-12 10:29:25 +00:00
const urlRequest = net.request({
2016-10-11 13:25:26 +00:00
method: 'GET',
2016-10-12 10:29:25 +00:00
url: `${server.url}${requestUrl}`
2016-10-11 13:25:26 +00:00
})
2016-10-12 10:29:25 +00:00
urlRequest.on('response', function (response) {
2016-10-11 13:25:26 +00:00
const statusCode = response.statusCode
assert(typeof statusCode === 'number')
assert.equal(statusCode, 200)
const statusMessage = response.statusMessage
assert(typeof statusMessage === 'string')
assert.equal(statusMessage, 'OK')
const headers = response.headers
assert(typeof headers === 'object')
assert.deepEqual(headers[customHeaderName.toLowerCase()],
[customHeaderValue])
2016-10-12 10:29:25 +00:00
const httpVersion = response.httpVersion
2016-10-11 13:25:26 +00:00
assert(typeof httpVersion === 'string')
assert(httpVersion.length > 0)
2016-10-12 10:29:25 +00:00
const httpVersionMajor = response.httpVersionMajor
2016-10-11 13:25:26 +00:00
assert(typeof httpVersionMajor === 'number')
assert(httpVersionMajor >= 1)
2016-10-12 10:29:25 +00:00
const httpVersionMinor = response.httpVersionMinor
2016-10-11 13:25:26 +00:00
assert(typeof httpVersionMinor === 'number')
assert(httpVersionMinor >= 0)
response.pause()
2016-10-12 10:29:25 +00:00
response.on('data', function (chunk) {
})
response.on('end', function () {
2016-10-11 13:25:26 +00:00
done()
})
response.resume()
})
2016-10-12 10:29:25 +00:00
urlRequest.end()
})
2016-10-11 13:25:26 +00:00
it('should be able to pipe a net response into a writable stream', function (done) {
2016-10-12 10:29:25 +00:00
const nodeRequestUrl = '/nodeRequestUrl'
const netRequestUrl = '/netRequestUrl'
const bodyData = randomString(kOneMegaByte)
server.on('request', function (request, response) {
2016-10-11 13:25:26 +00:00
switch (request.url) {
2016-10-12 10:29:25 +00:00
case netRequestUrl:
2016-10-11 17:16:23 +00:00
response.statusCode = 200
response.statusMessage = 'OK'
2016-10-12 10:29:25 +00:00
response.write(bodyData)
response.end()
break
case nodeRequestUrl:
let receivedBodyData = ''
request.on('data', function (chunk) {
receivedBodyData += chunk.toString()
2016-10-11 13:25:26 +00:00
})
2016-10-12 10:29:25 +00:00
request.on('end', function (chunk) {
2016-10-11 13:25:26 +00:00
if (chunk) {
2016-10-12 10:29:25 +00:00
receivedBodyData += chunk.toString()
2016-10-11 13:25:26 +00:00
}
2016-10-12 10:29:25 +00:00
assert.equal(receivedBodyData, bodyData)
2016-10-11 13:25:26 +00:00
response.end()
})
2016-10-12 10:29:25 +00:00
break
2016-10-11 13:25:26 +00:00
default:
assert(false)
}
})
ipcRenderer.once('api-net-spec-done', function () {
done()
})
// Execute below code directly within the browser context without
// using the remote module.
ipcRenderer.send('eval', `
const {net} = require('electron')
const http = require('http')
const netRequest = net.request('${server.url}${netRequestUrl}')
netRequest.on('response', function (netResponse) {
const serverUrl = url.parse('${server.url}')
const nodeOptions = {
method: 'POST',
path: '${nodeRequestUrl}',
port: serverUrl.port
}
let nodeRequest = http.request(nodeOptions)
nodeRequest.on('response', function (nodeResponse) {
nodeResponse.on('data', function (chunk) {
})
nodeResponse.on('end', function (chunk) {
event.sender.send('api-net-spec-done')
})
2016-10-11 13:25:26 +00:00
})
netResponse.pipe(nodeRequest)
2016-10-11 13:25:26 +00:00
})
netRequest.end()
`)
})
2016-10-11 17:16:23 +00:00
it('should not emit any event after close', function (done) {
const requestUrl = '/requestUrl'
let bodyData = randomString(kOneKiloByte)
server.on('request', function (request, response) {
switch (request.url) {
case requestUrl:
response.statusCode = 200
response.statusMessage = 'OK'
response.write(bodyData)
response.end()
break
default:
assert(false)
}
})
let requestCloseEventEmitted = false
const urlRequest = net.request({
method: 'GET',
url: `${server.url}${requestUrl}`
})
urlRequest.on('response', function (response) {
assert(!requestCloseEventEmitted)
const statusCode = response.statusCode
assert.equal(statusCode, 200)
response.pause()
response.on('data', function () {
})
response.on('end', function () {
})
response.resume()
response.on('error', function () {
assert(!requestCloseEventEmitted)
})
response.on('aborted', function () {
assert(!requestCloseEventEmitted)
})
})
urlRequest.on('finish', function () {
assert(!requestCloseEventEmitted)
})
urlRequest.on('error', function () {
assert(!requestCloseEventEmitted)
})
urlRequest.on('abort', function () {
assert(!requestCloseEventEmitted)
})
urlRequest.on('close', function () {
requestCloseEventEmitted = true
// Wait so that all async events get scheduled.
setTimeout(function () {
done()
}, 100)
})
urlRequest.end()
2016-10-11 17:16:23 +00:00
})
})
describe('Stability and performance', function (done) {
let server
beforeEach(function (done) {
server = http.createServer()
server.listen(0, '127.0.0.1', function () {
server.url = 'http://127.0.0.1:' + server.address().port
done()
})
})
afterEach(function () {
server.close()
server = null
})
it('should free unreferenced, never-started request objects without crash', function (done) {
const requestUrl = '/requestUrl'
ipcRenderer.once('api-net-spec-done', function () {
done()
})
ipcRenderer.send('eval', `
const {net} = require('electron')
const urlRequest = net.request('${server.url}${requestUrl}')
process.nextTick(function () {
2016-10-25 10:41:01 +00:00
const v8Util = process.atomBinding('v8_util')
v8Util.requestGarbageCollectionForTesting()
event.sender.send('api-net-spec-done')
})
`)
})
it('should not collect on-going requests without crash', function (done) {
const requestUrl = '/requestUrl'
server.on('request', function (request, response) {
switch (request.url) {
case requestUrl:
response.statusCode = 200
response.statusMessage = 'OK'
response.write(randomString(kOneKiloByte))
ipcRenderer.once('api-net-spec-resume', function () {
response.write(randomString(kOneKiloByte))
response.end()
})
break
default:
assert(false)
}
})
ipcRenderer.once('api-net-spec-done', function () {
done()
})
// Execute below code directly within the browser context without
// using the remote module.
ipcRenderer.send('eval', `
const {net} = require('electron')
const urlRequest = net.request('${server.url}${requestUrl}')
urlRequest.on('response', function (response) {
response.on('data', function () {
})
response.on('end', function () {
event.sender.send('api-net-spec-done')
})
process.nextTick(function () {
// Trigger a garbage collection.
2016-10-25 10:41:01 +00:00
const v8Util = process.atomBinding('v8_util')
v8Util.requestGarbageCollectionForTesting()
event.sender.send('api-net-spec-resume')
})
})
urlRequest.end()
`)
})
it('should collect unreferenced, ended requests without crash', function (done) {
const requestUrl = '/requestUrl'
server.on('request', function (request, response) {
switch (request.url) {
case requestUrl:
response.statusCode = 200
response.statusMessage = 'OK'
response.end()
break
default:
assert(false)
}
})
ipcRenderer.once('api-net-spec-done', function () {
done()
})
ipcRenderer.send('eval', `
const {net} = require('electron')
const urlRequest = net.request('${server.url}${requestUrl}')
urlRequest.on('response', function (response) {
response.on('data', function () {
})
response.on('end', function () {
})
})
urlRequest.on('close', function () {
process.nextTick(function () {
2016-10-25 10:41:01 +00:00
const v8Util = process.atomBinding('v8_util')
v8Util.requestGarbageCollectionForTesting()
event.sender.send('api-net-spec-done')
})
})
urlRequest.end()
`)
})
})
2016-10-12 10:29:25 +00:00
})