-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(server): add serverMode option (#1937)
- Loading branch information
1 parent
def98d8
commit 44a8cde
Showing
6 changed files
with
260 additions
and
2 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,41 @@ | ||
'use strict'; | ||
|
||
function getSocketServerImplementation(options) { | ||
let ServerImplementation; | ||
let serverImplFound = true; | ||
switch (typeof options.serverMode) { | ||
case 'string': | ||
// could be 'sockjs', in the future 'ws', or a path that should be required | ||
if (options.serverMode === 'sockjs') { | ||
// eslint-disable-next-line global-require | ||
ServerImplementation = require('../servers/SockJSServer'); | ||
} else { | ||
try { | ||
// eslint-disable-next-line global-require, import/no-dynamic-require | ||
ServerImplementation = require(options.serverMode); | ||
} catch (e) { | ||
serverImplFound = false; | ||
} | ||
} | ||
break; | ||
case 'function': | ||
// potentially do more checks here to confirm that the user implemented this properlly | ||
// since errors could be difficult to understand | ||
ServerImplementation = options.serverMode; | ||
break; | ||
default: | ||
serverImplFound = false; | ||
} | ||
|
||
if (!serverImplFound) { | ||
throw new Error( | ||
"serverMode must be a string denoting a default implementation (e.g. 'sockjs'), a full path to " + | ||
'a JS file which exports a class extending BaseServer (webpack-dev-server/lib/servers/BaseServer) ' + | ||
'via require.resolve(...), or the class itself which extends BaseServer' | ||
); | ||
} | ||
|
||
return ServerImplementation; | ||
} | ||
|
||
module.exports = getSocketServerImplementation; |
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,50 @@ | ||
'use strict'; | ||
|
||
const getSocketServerImplementation = require('../lib/utils/getSocketServerImplementation'); | ||
const SockJSServer = require('../lib/servers/SockJSServer'); | ||
|
||
describe('getSocketServerImplementation', () => { | ||
it("should work with serverMode: 'sockjs'", () => { | ||
let result; | ||
|
||
expect(() => { | ||
result = getSocketServerImplementation({ | ||
serverMode: 'sockjs', | ||
}); | ||
}).not.toThrow(); | ||
|
||
expect(result).toEqual(SockJSServer); | ||
}); | ||
|
||
it('should work with serverMode: SockJSServer class', () => { | ||
let result; | ||
|
||
expect(() => { | ||
result = getSocketServerImplementation({ | ||
serverMode: SockJSServer, | ||
}); | ||
}).not.toThrow(); | ||
|
||
expect(result).toEqual(SockJSServer); | ||
}); | ||
|
||
it('should work with serverMode: SockJSServer full path', () => { | ||
let result; | ||
|
||
expect(() => { | ||
result = getSocketServerImplementation({ | ||
serverMode: require.resolve('../lib/servers/SockJSServer'), | ||
}); | ||
}).not.toThrow(); | ||
|
||
expect(result).toEqual(SockJSServer); | ||
}); | ||
|
||
it('should throw with serverMode: bad path', () => { | ||
expect(() => { | ||
getSocketServerImplementation({ | ||
serverMode: '/bad/path/to/implementation', | ||
}); | ||
}).toThrow(/serverMode must be a string/); | ||
}); | ||
}); |
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,133 @@ | ||
'use strict'; | ||
|
||
/* eslint-disable | ||
class-methods-use-this | ||
*/ | ||
const request = require('supertest'); | ||
const sockjs = require('sockjs'); | ||
const SockJSServer = require('../lib/servers/SockJSServer'); | ||
const config = require('./fixtures/simple-config/webpack.config'); | ||
const testServer = require('./helpers/test-server'); | ||
const BaseServer = require('./../lib/servers/BaseServer'); | ||
|
||
describe('serverMode', () => { | ||
let server; | ||
let req; | ||
|
||
afterEach((done) => { | ||
testServer.close(done); | ||
req = null; | ||
server = null; | ||
}); | ||
describe("supplying 'sockjs' as a string", () => { | ||
beforeEach((done) => { | ||
server = testServer.start( | ||
config, | ||
{ | ||
serverMode: 'sockjs', | ||
}, | ||
done | ||
); | ||
req = request('http://localhost:8080'); | ||
}); | ||
|
||
it('sockjs path responds with a 200', (done) => { | ||
req.get('/sockjs-node').expect(200, done); | ||
}); | ||
}); | ||
|
||
describe('supplying path to sockjs implementation', () => { | ||
beforeEach((done) => { | ||
server = testServer.start( | ||
config, | ||
{ | ||
serverMode: require.resolve('../lib/servers/SockJSServer'), | ||
}, | ||
done | ||
); | ||
req = request('http://localhost:8080'); | ||
}); | ||
|
||
it('sockjs path responds with a 200', (done) => { | ||
req.get('/sockjs-node').expect(200, done); | ||
}); | ||
}); | ||
|
||
describe('supplying sockjs implementation class', () => { | ||
beforeEach((done) => { | ||
server = testServer.start( | ||
config, | ||
{ | ||
serverMode: SockJSServer, | ||
}, | ||
done | ||
); | ||
req = request('http://localhost:8080'); | ||
}); | ||
|
||
it('sockjs path responds with a 200', (done) => { | ||
req.get('/sockjs-node').expect(200, done); | ||
}); | ||
}); | ||
|
||
describe('custom sockjs implementation', () => { | ||
it('uses supplied server implementation', (done) => { | ||
server = testServer.start( | ||
config, | ||
{ | ||
sockPath: '/foo/test/bar/', | ||
serverMode: class MySockJSServer extends BaseServer { | ||
constructor(serv) { | ||
super(serv); | ||
this.socket = sockjs.createServer({ | ||
// Use provided up-to-date sockjs-client | ||
sockjs_url: '/__webpack_dev_server__/sockjs.bundle.js', | ||
// Limit useless logs | ||
log: (severity, line) => { | ||
if (severity === 'error') { | ||
this.server.log.error(line); | ||
} else { | ||
this.server.log.debug(line); | ||
} | ||
}, | ||
}); | ||
|
||
this.socket.installHandlers(this.server.listeningApp, { | ||
prefix: this.server.sockPath, | ||
}); | ||
|
||
expect(server.options.sockPath).toEqual('/foo/test/bar/'); | ||
} | ||
|
||
send(connection, message) { | ||
connection.write(message); | ||
} | ||
|
||
close(connection) { | ||
connection.close(); | ||
} | ||
|
||
onConnection(f) { | ||
this.socket.on('connection', f); | ||
} | ||
}, | ||
}, | ||
done | ||
); | ||
}); | ||
}); | ||
|
||
describe('supplying nonexistent path', () => { | ||
it('should throw an error', () => { | ||
expect(() => { | ||
server = testServer.start( | ||
config, | ||
{ | ||
serverMode: '/bad/path/to/implementation', | ||
}, | ||
() => {} | ||
); | ||
}).toThrow(/serverMode must be a string/); | ||
}); | ||
}); | ||
}); |
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