| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 library pub.barback.base_server; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 import 'dart:convert'; | |
| 9 import 'dart:io'; | |
| 10 | |
| 11 import 'package:barback/barback.dart'; | |
| 12 import 'package:shelf/shelf.dart' as shelf; | |
| 13 import 'package:shelf/shelf_io.dart' as shelf_io; | |
| 14 | |
| 15 import '../log.dart' as log; | |
| 16 import '../utils.dart'; | |
| 17 import 'asset_environment.dart'; | |
| 18 | |
| 19 /// Base class for a pub-controlled server. | |
| 20 abstract class BaseServer<T> { | |
| 21 /// The [BuildEnvironment] being served. | |
| 22 final AssetEnvironment environment; | |
| 23 | |
| 24 /// The underlying HTTP server. | |
| 25 final HttpServer _server; | |
| 26 | |
| 27 /// The server's port. | |
| 28 int get port => _server.port; | |
| 29 | |
| 30 /// The servers's address. | |
| 31 InternetAddress get address => _server.address; | |
| 32 | |
| 33 /// The server's base URL. | |
| 34 Uri get url => baseUrlForAddress(_server.address, port); | |
| 35 | |
| 36 /// The results of requests handled by the server. | |
| 37 /// | |
| 38 /// These can be used to provide visual feedback for the server's processing. | |
| 39 /// This stream is also used to emit any programmatic errors that occur in the | |
| 40 /// server. | |
| 41 Stream<T> get results => _resultsController.stream; | |
| 42 final _resultsController = new StreamController<T>.broadcast(); | |
| 43 | |
| 44 BaseServer(this.environment, this._server) { | |
| 45 shelf_io.serveRequests(_server, const shelf.Pipeline() | |
| 46 .addMiddleware(shelf.createMiddleware(errorHandler: _handleError)) | |
| 47 .addHandler(handleRequest)); | |
| 48 } | |
| 49 | |
| 50 /// Closes this server. | |
| 51 Future close() { | |
| 52 return Future.wait([_server.close(), _resultsController.close()]); | |
| 53 } | |
| 54 | |
| 55 /// Handles an HTTP request. | |
| 56 handleRequest(shelf.Request request); | |
| 57 | |
| 58 /// Returns a 405 response to [request]. | |
| 59 shelf.Response methodNotAllowed(shelf.Request request) { | |
| 60 logRequest(request, "405 Method Not Allowed"); | |
| 61 return new shelf.Response(405, | |
| 62 body: "The ${request.method} method is not allowed for ${request.url}.", | |
| 63 headers: {'Allow': 'GET, HEAD'}); | |
| 64 } | |
| 65 | |
| 66 /// Returns a 404 response to [request]. | |
| 67 /// | |
| 68 /// If [asset] is given, it is the ID of the asset that couldn't be found. | |
| 69 shelf.Response notFound(shelf.Request request, {String error, | |
| 70 AssetId asset}) { | |
| 71 logRequest(request, "Not Found"); | |
| 72 | |
| 73 // TODO(rnystrom): Apply some styling to make it visually clear that this | |
| 74 // error is coming from pub serve itself. | |
| 75 var body = new StringBuffer(); | |
| 76 body.writeln(""" | |
| 77 <!DOCTYPE html> | |
| 78 <head> | |
| 79 <title>404 Not Found</title> | |
| 80 </head> | |
| 81 <body> | |
| 82 <h1>404 Not Found</h1>"""); | |
| 83 | |
| 84 if (asset != null) { | |
| 85 body.writeln("<p>Could not find asset " | |
| 86 "<code>${HTML_ESCAPE.convert(asset.path)}</code> in package " | |
| 87 "<code>${HTML_ESCAPE.convert(asset.package)}</code>.</p>"); | |
| 88 } | |
| 89 | |
| 90 if (error != null) { | |
| 91 body.writeln("<p>Error: ${HTML_ESCAPE.convert(error)}</p>"); | |
| 92 } | |
| 93 | |
| 94 body.writeln(""" | |
| 95 </body>"""); | |
| 96 | |
| 97 // Force a UTF-8 encoding so that error messages in non-English locales are | |
| 98 // sent correctly. | |
| 99 return new shelf.Response.notFound(body.toString(), | |
| 100 headers: {'Content-Type': 'text/html; charset=utf-8'}); | |
| 101 } | |
| 102 | |
| 103 /// Log [message] at [log.Level.FINE] with metadata about [request]. | |
| 104 void logRequest(shelf.Request request, String message) => | |
| 105 log.fine("$this ${request.method} ${request.url}\n$message"); | |
| 106 | |
| 107 /// Adds [result] to the server's [results] stream. | |
| 108 void addResult(T result) { | |
| 109 _resultsController.add(result); | |
| 110 } | |
| 111 | |
| 112 /// Adds [error] as an error to the server's [results] stream. | |
| 113 void addError(error, [stackTrace]) { | |
| 114 _resultsController.addError(error, stackTrace); | |
| 115 } | |
| 116 | |
| 117 /// Handles an error thrown by [handleRequest]. | |
| 118 _handleError(error, StackTrace stackTrace) { | |
| 119 _resultsController.addError(error, stackTrace); | |
| 120 close(); | |
| 121 return new shelf.Response.internalServerError(); | |
| 122 } | |
| 123 } | |
| OLD | NEW |