-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(server): move socket handling into server.listen (#2061)
- Loading branch information
1 parent
17dec00
commit 7af06d9
Showing
9 changed files
with
484 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
'use strict'; | ||
|
||
const fs = require('fs'); | ||
const net = require('net'); | ||
const { promisify } = require('util'); | ||
|
||
const accessAsync = promisify(fs.access); | ||
|
||
async function startUnixSocket(listeningApp, socket, cb) { | ||
const chmodSocket = (done) => { | ||
// chmod 666 (rw rw rw) - octal | ||
const READ_WRITE = 438; | ||
fs.chmod(socket, READ_WRITE, done); | ||
}; | ||
|
||
const startSocket = () => { | ||
listeningApp.on('error', (err) => { | ||
cb(err); | ||
}); | ||
|
||
// 511 is the default value for the server.listen backlog parameter | ||
// https://nodejs.org/api/net.html#net_server_listen | ||
listeningApp.listen(socket, 511, (err) => { | ||
if (err) { | ||
cb(err); | ||
} else { | ||
chmodSocket(cb); | ||
} | ||
}); | ||
}; | ||
|
||
try { | ||
await accessAsync(socket, fs.constants.F_OK); | ||
} catch (e) { | ||
// file does not exist | ||
startSocket(); | ||
return; | ||
} | ||
|
||
// file exists | ||
|
||
const clientSocket = new net.Socket(); | ||
|
||
clientSocket.on('error', (err) => { | ||
if (err.code === 'ECONNREFUSED' || err.code === 'ENOTSOCK') { | ||
// No other server listening on this socket so it can be safely removed | ||
fs.unlinkSync(socket); | ||
|
||
startSocket(); | ||
} | ||
}); | ||
|
||
clientSocket.connect({ path: socket }, () => { | ||
// if a client socket successfully connects to the given socket path, | ||
// it means that the socket is in use | ||
const err = new Error('This socket is already used'); | ||
clientSocket.destroy(); | ||
cb(err); | ||
}); | ||
} | ||
|
||
module.exports = startUnixSocket; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
'use strict'; | ||
|
||
const http = require('http'); | ||
|
||
const TestUnixSocket = class TestUnixSocket { | ||
constructor() { | ||
this.server = http.createServer(); | ||
this.sockets = new Set(); | ||
this.server.on('connection', (socket) => { | ||
this.sockets.add(socket); | ||
socket.on('close', () => { | ||
this.sockets.delete(socket); | ||
}); | ||
}); | ||
} | ||
|
||
close(done) { | ||
if (this.server.listening) { | ||
// get rid of connected sockets | ||
for (const socket of this.sockets.values()) { | ||
socket.destroy(); | ||
} | ||
this.server.close(done); | ||
} else { | ||
done(); | ||
} | ||
} | ||
}; | ||
|
||
module.exports = TestUnixSocket; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,71 @@ | ||
'use strict'; | ||
|
||
const { unlink } = require('fs'); | ||
const { join } = require('path'); | ||
const testServer = require('../helpers/test-server'); | ||
const config = require('../fixtures/simple-config/webpack.config'); | ||
const port = require('../ports-map')['onListening-option']; | ||
const { skipTestOnWindows } = require('../helpers/conditional-test'); | ||
|
||
describe('onListening option', () => { | ||
let onListeningIsRunning = false; | ||
|
||
beforeAll((done) => { | ||
testServer.start( | ||
config, | ||
{ | ||
onListening: (devServer) => { | ||
if (!devServer) { | ||
throw new Error('webpack-dev-server is not defined'); | ||
} | ||
|
||
onListeningIsRunning = true; | ||
describe('with host and port', () => { | ||
let onListeningIsRunning = false; | ||
|
||
beforeAll((done) => { | ||
testServer.start( | ||
config, | ||
{ | ||
onListening: (devServer) => { | ||
if (!devServer) { | ||
throw new Error('webpack-dev-server is not defined'); | ||
} | ||
|
||
onListeningIsRunning = true; | ||
}, | ||
port, | ||
}, | ||
port, | ||
}, | ||
done | ||
); | ||
done | ||
); | ||
}); | ||
|
||
afterAll(testServer.close); | ||
|
||
it('should run onListening callback', () => { | ||
expect(onListeningIsRunning).toBe(true); | ||
}); | ||
}); | ||
|
||
afterAll(testServer.close); | ||
describe('with Unix socket', () => { | ||
if (skipTestOnWindows('Unix sockets are not supported on Windows')) { | ||
return; | ||
} | ||
|
||
const socketPath = join('.', 'onListening.webpack.sock'); | ||
let onListeningIsRunning = false; | ||
|
||
beforeAll((done) => { | ||
testServer.start( | ||
config, | ||
{ | ||
onListening: (devServer) => { | ||
if (!devServer) { | ||
throw new Error('webpack-dev-server is not defined'); | ||
} | ||
|
||
onListeningIsRunning = true; | ||
}, | ||
socket: socketPath, | ||
}, | ||
done | ||
); | ||
}); | ||
|
||
afterAll(testServer.close); | ||
|
||
it('should run onListening callback', (done) => { | ||
expect(onListeningIsRunning).toBe(true); | ||
|
||
it('should runs onListening callback', () => { | ||
expect(onListeningIsRunning).toBe(true); | ||
unlink(socketPath, done); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.