Version 2.14.0-93.0.dev
Merge commit 'd0f7a5b6d1011e60fe70fc6a9339b98b999c873d' into 'dev'
diff --git a/pkg/dartdev/lib/src/templates.dart b/pkg/dartdev/lib/src/templates.dart
index 0b5aa0d..53666a3 100644
--- a/pkg/dartdev/lib/src/templates.dart
+++ b/pkg/dartdev/lib/src/templates.dart
@@ -9,7 +9,7 @@
import 'templates/console_full.dart';
import 'templates/console_simple.dart';
import 'templates/package_simple.dart';
-import 'templates/server_simple.dart';
+import 'templates/server_shelf.dart';
import 'templates/web_simple.dart';
final _substituteRegExp = RegExp(r'__([a-zA-Z]+)__');
@@ -19,7 +19,7 @@
ConsoleSimpleGenerator(),
ConsoleFullGenerator(),
PackageSimpleGenerator(),
- ServerSimpleGenerator(),
+ ServerShelfGenerator(),
WebSimpleGenerator(),
];
diff --git a/pkg/dartdev/lib/src/templates/server_shelf.dart b/pkg/dartdev/lib/src/templates/server_shelf.dart
new file mode 100644
index 0000000..b3bbba7
--- /dev/null
+++ b/pkg/dartdev/lib/src/templates/server_shelf.dart
@@ -0,0 +1,209 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../templates.dart';
+import 'common.dart' as common;
+
+/// A generator for a server app using `package:shelf`.
+class ServerShelfGenerator extends DefaultGenerator {
+ ServerShelfGenerator()
+ : super(
+ 'server-shelf', 'Server app', 'A server app using `package:shelf`',
+ categories: const ['dart', 'server']) {
+ addFile('.gitignore', common.gitignore);
+ addFile('analysis_options.yaml', common.analysisOptions);
+ addFile('CHANGELOG.md', common.changelog);
+ addFile('pubspec.yaml', _pubspec);
+ addFile('README.md', _readme);
+ addFile('Dockerfile', _dockerfile);
+ addFile('.dockerignore', _dockerignore);
+ addFile('test/server_test.dart', _test);
+ setEntrypoint(
+ addFile('bin/server.dart', _main),
+ );
+ }
+
+ @override
+ String getInstallInstructions() => '${super.getInstallInstructions()}\n'
+ 'run your app using `dart run ${entrypoint.path}`.';
+}
+
+final String _pubspec = '''
+name: __projectName__
+description: A server app using the shelf package and Docker.
+version: 1.0.0
+# homepage: https://www.example.com
+
+environment:
+ sdk: ">=2.12.0 <3.0.0"
+
+dependencies:
+ args: ^2.0.0
+ shelf: ^1.1.0
+ shelf_router: ^1.0.0
+
+dev_dependencies:
+ http: ^0.13.0
+ pedantic: ^1.10.0
+ test_process: ^2.0.0
+ test: ^1.15.0
+''';
+
+final String _readme = '''
+A server app built using [Shelf](https://pub.dev/packages/shelf),
+configured to enable running with [Docker](https://www.docker.com/).
+
+This sample code handles HTTP GET requests to `/` and `/echo/<message>`
+
+# Running the sample
+
+## Running with the Dart SDK
+
+You can run the example with the [Dart SDK](https://dart.dev/get-dart)
+like this:
+
+```
+\$ dart run bin/server.dart
+Server listening on port 8080
+```
+
+And then from a second terminal:
+```
+\$ curl http://0.0.0.0:8080
+Hello, World!
+\$ curl http://0.0.0.0:8080/echo/I_love_Dart
+I_love_Dart
+```
+
+## Running with Docker
+
+If you have [Docker Desktop](https://www.docker.com/get-started) installed, you
+can build and run with the `docker` command:
+
+```
+\$ docker build . -t myserver
+\$ docker run -it -p 8080:8080 myserver
+Server listening on port 8080
+```
+
+And then from a second terminal:
+```
+\$ curl http://0.0.0.0:8080
+Hello, World!
+\$ curl http://0.0.0.0:8080/echo/I_love_Dart
+I_love_Dart
+```
+
+You should see the logging printed in the first terminal:
+```
+2021-05-06T15:47:04.620417 0:00:00.000158 GET [200] /
+2021-05-06T15:47:08.392928 0:00:00.001216 GET [200] /echo/I_love_Dart
+```
+''';
+
+final String _main = r'''
+import 'dart:io';
+
+import 'package:shelf/shelf.dart';
+import 'package:shelf/shelf_io.dart';
+import 'package:shelf_router/shelf_router.dart';
+
+// Configure routes.
+final _router = Router()
+ ..get('/', _rootHandler)
+ ..get('/echo/<message>', _echoHandler);
+
+Response _rootHandler(Request req) {
+ return Response.ok('Hello, World!\n');
+}
+
+Response _echoHandler(Request request) {
+ final message = params(request, 'message');
+ return Response.ok('$message\n');
+}
+
+void main(List<String> args) async {
+ // Use any available host or container IP (usually `0.0.0.0`).
+ final ip = InternetAddress.anyIPv4;
+
+ // Configure a pipeline that logs requests.
+ final _handler = Pipeline().addMiddleware(logRequests()).addHandler(_router);
+
+ // For running in containers, we respect the PORT environment variable.
+ final port = int.parse(Platform.environment['PORT'] ?? '8080');
+ final server = await serve(_handler, ip, port);
+ print('Server listening on port ${server.port}');
+}
+''';
+
+final String _dockerfile = r'''
+# Use latest stable channel SDK.
+FROM dart:stable AS build
+
+# Resolve app dependencies.
+WORKDIR /app
+COPY pubspec.* .
+RUN dart pub get
+
+# Copy app source code (except anything in .dockerignore) and AOT compile app.
+COPY . .
+RUN dart compile exe bin/server.dart -o /server
+
+# Build minimal serving image from AOT-compiled `/server`
+# and the pre-built AOT-runtime in the `/runtime/` directory of the base image.
+FROM scratch
+COPY --from=build /runtime/ /
+COPY --from=build /server /bin/
+
+# Start server.
+EXPOSE 8080
+CMD ["/bin/server"]
+''';
+
+final String _dockerignore = r'''
+.dockerignore
+Dockerfile
+build/
+.dart_tool/
+.git/
+.github/
+.gitignore
+.idea/
+.packages
+''';
+
+final String _test = r'''
+import 'package:http/http.dart';
+import 'package:test/test.dart';
+import 'package:test_process/test_process.dart';
+
+void main() {
+ final port = '8080';
+ final host = 'http://0.0.0.0:$port';
+
+ setUp(() async {
+ await TestProcess.start(
+ 'dart',
+ ['run', 'bin/server.dart'],
+ environment: {'PORT': port},
+ );
+ });
+
+ test('Root', () async {
+ final response = await get(Uri.parse(host + '/'));
+ expect(response.statusCode, 200);
+ expect(response.body, 'Hello, World!\n');
+ });
+
+ test('Echo', () async {
+ final response = await get(Uri.parse(host + '/echo/hello'));
+ expect(response.statusCode, 200);
+ expect(response.body, 'hello\n');
+ });
+ test('404', () async {
+ final response = await get(Uri.parse(host + '/foobar'));
+ expect(response.statusCode, 404);
+ });
+}
+''';
diff --git a/pkg/dartdev/lib/src/templates/server_simple.dart b/pkg/dartdev/lib/src/templates/server_simple.dart
deleted file mode 100644
index 6688f23..0000000
--- a/pkg/dartdev/lib/src/templates/server_simple.dart
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import '../templates.dart';
-import 'common.dart' as common;
-
-/// A generator for a server app built on `package:shelf`.
-class ServerSimpleGenerator extends DefaultGenerator {
- ServerSimpleGenerator()
- : super('server-simple', 'Web Server',
- 'A web server built using package:shelf.',
- categories: const ['dart', 'server']) {
- addFile('.gitignore', common.gitignore);
- addFile('analysis_options.yaml', common.analysisOptions);
- addFile('CHANGELOG.md', common.changelog);
- addFile('pubspec.yaml', _pubspec);
- addFile('README.md', _readme);
- setEntrypoint(
- addFile('bin/server.dart', _main),
- );
- }
-
- @override
- String getInstallInstructions() => '${super.getInstallInstructions()}\n'
- 'run your app using `dart ${entrypoint.path}`.';
-}
-
-final String _pubspec = '''
-name: __projectName__
-description: A web server built using the shelf package.
-version: 1.0.0
-# homepage: https://www.example.com
-
-environment:
- sdk: ">=2.12.0 <3.0.0"
-
-dependencies:
- args: ^2.0.0
- shelf: ^1.1.0
-
-dev_dependencies:
- pedantic: ^1.10.0
-''';
-
-final String _readme = '''
-A web server built using [Shelf](https://pub.dev/packages/shelf).
-''';
-
-final String _main = r'''
-import 'dart:io';
-
-import 'package:args/args.dart';
-import 'package:shelf/shelf.dart' as shelf;
-import 'package:shelf/shelf_io.dart' as io;
-
-// For Google Cloud Run, set _hostname to '0.0.0.0'.
-const _hostname = 'localhost';
-
-void main(List<String> args) async {
- var parser = ArgParser()..addOption('port', abbr: 'p');
- var result = parser.parse(args);
-
- // For Google Cloud Run, we respect the PORT environment variable
- var portStr = result['port'] ?? Platform.environment['PORT'] ?? '8080';
- var port = int.tryParse(portStr);
-
- if (port == null) {
- stdout.writeln('Could not parse port value "$portStr" into a number.');
- // 64: command line usage error
- exitCode = 64;
- return;
- }
-
- var handler = const shelf.Pipeline()
- .addMiddleware(shelf.logRequests())
- .addHandler(_echoRequest);
-
- var server = await io.serve(handler, _hostname, port);
- print('Serving at http://${server.address.host}:${server.port}');
-}
-
-shelf.Response _echoRequest(shelf.Request request) =>
- shelf.Response.ok('Request for "${request.url}"');
-''';
diff --git a/tools/VERSION b/tools/VERSION
index c2db219..99a1532 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 92
+PRERELEASE 93
PRERELEASE_PATCH 0
\ No newline at end of file