Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Side by Side Diff: pkg/scheduled_test/lib/scheduled_server.dart

Issue 216373004: Use shelf handlers in ScheduledServer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: code review Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library scheduled_test.scheduled_server; 5 library scheduled_test.scheduled_server;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 import 'dart:io'; 9 import 'dart:io';
10 10
11 import 'package:stack_trace/stack_trace.dart'; 11 import 'package:shelf/shelf.dart' as shelf;
12 import 'package:shelf/shelf_io.dart' as shelf_io;
12 13
13 import 'scheduled_test.dart'; 14 import 'scheduled_test.dart';
14 import 'src/scheduled_server/handler.dart'; 15 import 'src/scheduled_server/handler.dart';
15 import 'src/utils.dart'; 16 import 'src/utils.dart';
16 17
17 typedef Future ScheduledHandler(HttpRequest request); 18 /// A class representing an HTTP server that's scheduled to run in the course of
18 19 /// the test. This class allows the server's request handling to be scheduled
19 /// A class representing an [HttpServer] that's scheduled to run in the course
20 /// of the test. This class allows the server's request handling to be scheduled
21 /// synchronously. 20 /// synchronously.
22 /// 21 ///
23 /// The server expects requests to be received in the order [handle] is called, 22 /// The server expects requests to be received in the order [handle] is called,
24 /// and expects that no additional requests will be received. 23 /// and expects that no additional requests will be received.
25 class ScheduledServer { 24 class ScheduledServer {
26 /// The description of the server. 25 /// The description of the server.
27 final String description; 26 final String description;
28 27
29 /// The wrapped server. 28 /// The wrapped server.
30 final Future<HttpServer> _server; 29 final Future<HttpServer> _server;
(...skipping 10 matching lines...) Expand all
41 40
42 /// Creates a new server listening on an automatically-allocated port on 41 /// Creates a new server listening on an automatically-allocated port on
43 /// 127.0.0.1. [description] is used to refer to the server in debugging 42 /// 127.0.0.1. [description] is used to refer to the server in debugging
44 /// messages. 43 /// messages.
45 factory ScheduledServer([String description]) { 44 factory ScheduledServer([String description]) {
46 var id = _count++; 45 var id = _count++;
47 if (description == null) description = 'scheduled server $id'; 46 if (description == null) description = 'scheduled server $id';
48 47
49 var scheduledServer; 48 var scheduledServer;
50 scheduledServer = new ScheduledServer._(schedule(() { 49 scheduledServer = new ScheduledServer._(schedule(() {
51 return Chain.track(HttpServer.bind("127.0.0.1", 0)).then((server) { 50 return shelf_io.serve(scheduledServer._handleRequest, "127.0.0.1", 0)
52 Chain.track(server).listen(scheduledServer._handleRequest, 51 .then((server) {
53 onError: currentSchedule.signalError); 52 currentSchedule.onComplete.schedule(() => server.close(force: true));
54 currentSchedule.onComplete.schedule(server.close);
55 return server; 53 return server;
56 }); 54 });
57 }, "starting '$description'"), description); 55 }, "starting '$description'"), description);
58 return scheduledServer; 56 return scheduledServer;
59 } 57 }
60 58
61 /// The port on which the server is listening. 59 /// The port on which the server is listening.
62 Future<int> get port => _server.then((s) => s.port); 60 Future<int> get port => _server.then((s) => s.port);
63 61
64 /// The base URL of the server, including its port. 62 /// The base URL of the server, including its port.
65 Future<Uri> get url => port.then((p) => Uri.parse("http://127.0.0.1:$p")); 63 Future<Uri> get url => port.then((p) => Uri.parse("http://127.0.0.1:$p"));
66 64
67 /// Schedules [handler] to handle a request to the server with [method] and 65 /// Schedules [handler] to handle a request to the server with [method] and
68 /// [path]. The schedule will wait until an HTTP request is received. If that 66 /// [path]. The schedule will wait until an HTTP request is received. If that
69 /// request doesn't have the expected [method] and [path], it will fail. 67 /// request doesn't have the expected [method] and [path], it will fail.
70 /// Otherwise, it will run [fn]. If [fn] returns a [Future], the schedule will 68 /// Otherwise, it will run [fn]. If [fn] returns a [Future], the schedule will
71 /// wait until that [Future] completes. 69 /// wait until that [Future] completes.
72 /// 70 ///
73 /// The request must be received at the point in the schedule at which 71 /// The request must be received at the point in the schedule at which
74 /// [handle] was called, or in the task immediately prior (to allow for 72 /// [handle] was called, or in the task immediately prior (to allow for
75 /// non-deterministic asynchronicity). Otherwise, an error will be thrown. 73 /// non-deterministic asynchronicity). Otherwise, an error will be thrown.
76 void handle(String method, String path, ScheduledHandler fn) { 74 void handle(String method, String path, shelf.Handler fn) {
77 var handler = new Handler(this, method, path, fn); 75 var handler = new Handler(this, method, path, fn);
78 _handlers.add(handler); 76 _handlers.add(handler);
79 schedule(() { 77 schedule(() {
80 handler.ready = true; 78 handler.ready = true;
81 return handler.result.catchError((e) { 79 return handler.result;
82 // Close the server so that we don't leave a dangling request.
83 _server.then((s) => s.close(force: true));
84 throw e;
85 });
86 }, "'$description' waiting for $method $path"); 80 }, "'$description' waiting for $method $path");
87 } 81 }
88 82
89 /// The handler for incoming [HttpRequest]s to this server. This dispatches 83 /// The handler for incoming [shelf.Request]s to this server.
90 /// the request to the first handler in the queue. It's that handler's 84 ///
91 /// responsibility to check that the method/path are correct and that it's 85 /// This dispatches the request to the first handler in the queue. It's that
92 /// being run at the correct time. 86 /// handler's responsibility to check that the method/path are correct and
93 void _handleRequest(HttpRequest request) { 87 /// that it's being run at the correct time.
94 wrapFuture(syncFuture(() { 88 Future<shelf.Response> _handleRequest(shelf.Request request) {
89 return wrapFuture(syncFuture(() {
95 if (_handlers.isEmpty) { 90 if (_handlers.isEmpty) {
96 fail("'$description' received ${request.method} ${request.uri.path} " 91 fail("'$description' received ${request.method} ${request.pathInfo} "
97 "when no more requests were expected."); 92 "when no more requests were expected.");
98 } 93 }
99 return _handlers.removeFirst().fn(request); 94 return _handlers.removeFirst().fn(request);
100 }).catchError((e) { 95 }), 'receiving ${request.method} ${request.pathInfo}').catchError((error) {
101 // Close the server so that we don't leave a dangling request. 96 // Don't let errors bubble up to the shelf handler. It will print them to
102 _server.then((s) => s.close(force: true)); 97 // stderr, but the user will already be notified via the scheduled_test
103 throw e; 98 // infrastructure.
104 }), 'receiving ${request.method} ${request.uri}'); 99 return new shelf.Response.internalServerError(
100 body: error.toString(),
101 headers: {'content-type': 'text/plain'});
102 });
105 } 103 }
106 } 104 }
OLDNEW
« no previous file with comments | « pkg/scheduled_test/CHANGELOG.md ('k') | pkg/scheduled_test/lib/src/scheduled_server/handler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698