Add HttpMultiServer.bind utility (dart-lang/http_multi_server#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.
diff --git a/pkgs/http_multi_server/CHANGELOG.md b/pkgs/http_multi_server/CHANGELOG.md
index 7a85e02..181b4bd 100644
--- a/pkgs/http_multi_server/CHANGELOG.md
+++ b/pkgs/http_multi_server/CHANGELOG.md
@@ -1,7 +1,11 @@
-## 2.0.7
+## 2.1.0
+- Add `HttpMultiServer.bind` static which centralizes logic around common local
+ serving scenarios - handling a more flexible 'localhost' and listening on
+ 'any' hostname.
- Update SDK constraints to `>=2.1.0 <3.0.0`.
+
## 2.0.6
* If there is a problem starting a loopback Ipv6 server, don't keep the Ipv4
diff --git a/pkgs/http_multi_server/lib/http_multi_server.dart b/pkgs/http_multi_server/lib/http_multi_server.dart
index d54022b..1f10215 100644
--- a/pkgs/http_multi_server/lib/http_multi_server.dart
+++ b/pkgs/http_multi_server/lib/http_multi_server.dart
@@ -133,6 +133,29 @@
requestClientCertificate: requestClientCertificate));
}
+ /// Bind an [HttpServer] with handling for special addresses 'localhost' and
+ /// 'any'.
+ ///
+ /// For address 'localhost' behaves like [loopback]. For 'any' listens on
+ /// [InternetAddress.anyIPv6] which listens on all hostnames for both IPv4 and
+ /// IPV6. For any other address forwards directly to `HttpServer.bind` where
+ /// the IPvX support may vary.
+ ///
+ /// See [HttpServer.bind].
+ static Future<HttpServer> bind(dynamic address, int port,
+ {int backlog = 0, bool v6Only = false, bool shared = false}) {
+ if (address == 'localhost') {
+ return HttpMultiServer.loopback(port,
+ backlog: backlog, v6Only: v6Only, shared: shared);
+ }
+ if (address == 'any') {
+ return HttpServer.bind(InternetAddress.anyIPv6, port,
+ backlog: backlog, v6Only: v6Only, shared: shared);
+ }
+ return HttpServer.bind(address, port,
+ backlog: backlog, v6Only: v6Only, shared: shared);
+ }
+
/// A helper method for initializing loopback servers.
///
/// [bind] should forward to either [HttpServer.bind] or
diff --git a/pkgs/http_multi_server/pubspec.yaml b/pkgs/http_multi_server/pubspec.yaml
index b058fbe..7249a60 100644
--- a/pkgs/http_multi_server/pubspec.yaml
+++ b/pkgs/http_multi_server/pubspec.yaml
@@ -1,5 +1,5 @@
name: http_multi_server
-version: 2.0.7-dev
+version: 2.1.0
description: >-
A dart:io HttpServer wrapper that handles requests from multiple servers.
diff --git a/pkgs/http_multi_server/test/http_multi_server_test.dart b/pkgs/http_multi_server/test/http_multi_server_test.dart
index a61212e..65cfd57 100644
--- a/pkgs/http_multi_server/test/http_multi_server_test.dart
+++ b/pkgs/http_multi_server/test/http_multi_server_test.dart
@@ -181,6 +181,62 @@
}
});
});
+
+ group("HttpMultiServer.bind", () {
+ test("listens on all localhost interfaces for 'localhost'", () async {
+ final server = await HttpMultiServer.bind("localhost", 0);
+ server.listen((request) {
+ request.response.write("got request");
+ request.response.close();
+ });
+
+ if (await supportsIPv4) {
+ expect(http.read("http://127.0.0.1:${server.port}/"),
+ completion(equals("got request")));
+ }
+
+ if (await supportsIPv6) {
+ expect(http.read("http://[::1]:${server.port}/"),
+ completion(equals("got request")));
+ }
+ });
+
+ test("listens on all localhost interfaces for 'any'", () async {
+ final server = await HttpMultiServer.bind("any", 0);
+ server.listen((request) {
+ request.response.write("got request");
+ request.response.close();
+ });
+
+ if (await supportsIPv4) {
+ expect(http.read("http://127.0.0.1:${server.port}/"),
+ completion(equals("got request")));
+ }
+
+ if (await supportsIPv6) {
+ expect(http.read("http://[::1]:${server.port}/"),
+ completion(equals("got request")));
+ }
+ });
+
+ test("listens on specified hostname", () async {
+ final server = await HttpMultiServer.bind(InternetAddress.anyIPv4, 0);
+ server.listen((request) {
+ request.response.write("got request");
+ request.response.close();
+ });
+
+ if (await supportsIPv4) {
+ expect(http.read("http://127.0.0.1:${server.port}/"),
+ completion(equals("got request")));
+ }
+
+ if (await supportsIPv6) {
+ expect(http.read("http://[::1]:${server.port}/"),
+ throwsA(isA<SocketException>()));
+ }
+ });
+ });
}
/// Makes a GET request to the root of [server] and returns the response.