Skip to content

Commit ccc74bd

Browse files
authored
Add HttpMultiServer.bind utility (flutter#16)
We have a few places where we want to allow listening on 'any' hostname for the case where the server may be both access locally with something like "localhost" and externally with something like the servers hostname.
1 parent 00a4575 commit ccc74bd

File tree

4 files changed

+85
-2
lines changed

4 files changed

+85
-2
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
## 2.0.7
1+
## 2.1.0
22

3+
- Add `HttpMultiServer.bind` static which centralizes logic around common local
4+
serving scenarios - handling a more flexible 'localhost' and listening on
5+
'any' hostname.
36
- Update SDK constraints to `>=2.1.0 <3.0.0`.
47

8+
59
## 2.0.6
610

711
* If there is a problem starting a loopback Ipv6 server, don't keep the Ipv4

lib/http_multi_server.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,29 @@ class HttpMultiServer extends StreamView<HttpRequest> implements HttpServer {
133133
requestClientCertificate: requestClientCertificate));
134134
}
135135

136+
/// Bind an [HttpServer] with handling for special addresses 'localhost' and
137+
/// 'any'.
138+
///
139+
/// For address 'localhost' behaves like [loopback]. For 'any' listens on
140+
/// [InternetAddress.anyIPv6] which listens on all hostnames for both IPv4 and
141+
/// IPV6. For any other address forwards directly to `HttpServer.bind` where
142+
/// the IPvX support may vary.
143+
///
144+
/// See [HttpServer.bind].
145+
static Future<HttpServer> bind(dynamic address, int port,
146+
{int backlog = 0, bool v6Only = false, bool shared = false}) {
147+
if (address == 'localhost') {
148+
return HttpMultiServer.loopback(port,
149+
backlog: backlog, v6Only: v6Only, shared: shared);
150+
}
151+
if (address == 'any') {
152+
return HttpServer.bind(InternetAddress.anyIPv6, port,
153+
backlog: backlog, v6Only: v6Only, shared: shared);
154+
}
155+
return HttpServer.bind(address, port,
156+
backlog: backlog, v6Only: v6Only, shared: shared);
157+
}
158+
136159
/// A helper method for initializing loopback servers.
137160
///
138161
/// [bind] should forward to either [HttpServer.bind] or

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: http_multi_server
2-
version: 2.0.7-dev
2+
version: 2.1.0
33

44
description: >-
55
A dart:io HttpServer wrapper that handles requests from multiple servers.

test/http_multi_server_test.dart

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,62 @@ void main() {
181181
}
182182
});
183183
});
184+
185+
group("HttpMultiServer.bind", () {
186+
test("listens on all localhost interfaces for 'localhost'", () async {
187+
final server = await HttpMultiServer.bind("localhost", 0);
188+
server.listen((request) {
189+
request.response.write("got request");
190+
request.response.close();
191+
});
192+
193+
if (await supportsIPv4) {
194+
expect(http.read("http://127.0.0.1:${server.port}/"),
195+
completion(equals("got request")));
196+
}
197+
198+
if (await supportsIPv6) {
199+
expect(http.read("http://[::1]:${server.port}/"),
200+
completion(equals("got request")));
201+
}
202+
});
203+
204+
test("listens on all localhost interfaces for 'any'", () async {
205+
final server = await HttpMultiServer.bind("any", 0);
206+
server.listen((request) {
207+
request.response.write("got request");
208+
request.response.close();
209+
});
210+
211+
if (await supportsIPv4) {
212+
expect(http.read("http://127.0.0.1:${server.port}/"),
213+
completion(equals("got request")));
214+
}
215+
216+
if (await supportsIPv6) {
217+
expect(http.read("http://[::1]:${server.port}/"),
218+
completion(equals("got request")));
219+
}
220+
});
221+
222+
test("listens on specified hostname", () async {
223+
final server = await HttpMultiServer.bind(InternetAddress.anyIPv4, 0);
224+
server.listen((request) {
225+
request.response.write("got request");
226+
request.response.close();
227+
});
228+
229+
if (await supportsIPv4) {
230+
expect(http.read("http://127.0.0.1:${server.port}/"),
231+
completion(equals("got request")));
232+
}
233+
234+
if (await supportsIPv6) {
235+
expect(http.read("http://[::1]:${server.port}/"),
236+
throwsA(isA<SocketException>()));
237+
}
238+
});
239+
});
184240
}
185241

186242
/// Makes a GET request to the root of [server] and returns the response.

0 commit comments

Comments
 (0)