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 appengine.assets; |
| 6 |
| 7 import 'dart:async'; |
| 8 import 'dart:io'; |
| 9 |
| 10 import 'package:http_server/http_server.dart' show VirtualDirectory; |
| 11 import 'package:path/path.dart' show normalize; |
| 12 |
| 13 import '../appengine_context.dart'; |
| 14 import '../client_context.dart'; |
| 15 |
| 16 class AssetsManager { |
| 17 static final root = 'build/web'; |
| 18 |
| 19 final Uri pubServeUrl; |
| 20 final bool usePubServe; |
| 21 final client = new HttpClient(); |
| 22 final VirtualDirectory vd = new VirtualDirectory(root); |
| 23 |
| 24 AssetsManager(Uri pubServeUrl, bool isDevEnvironment) |
| 25 : usePubServe = isDevEnvironment && pubServeUrl != null, |
| 26 pubServeUrl = pubServeUrl; |
| 27 |
| 28 Future _proxyToPub(HttpRequest request, String path) { |
| 29 const RESPONSE_HEADERS = const [ |
| 30 HttpHeaders.CONTENT_LENGTH, |
| 31 HttpHeaders.CONTENT_TYPE ]; |
| 32 |
| 33 var uri = pubServeUrl.resolve(path); |
| 34 return client.openUrl(request.method, uri) |
| 35 .then((proxyRequest) { |
| 36 proxyRequest.headers.removeAll(HttpHeaders.ACCEPT_ENCODING); |
| 37 return proxyRequest.close(); |
| 38 }) |
| 39 .then((proxyResponse) { |
| 40 proxyResponse.headers.forEach((name, values) { |
| 41 if (RESPONSE_HEADERS.contains(name)) { |
| 42 request.response.headers.set(name, values); |
| 43 } |
| 44 }); |
| 45 request.response.statusCode = proxyResponse.statusCode; |
| 46 request.response.reasonPhrase = proxyResponse.reasonPhrase; |
| 47 return proxyResponse.pipe(request.response); |
| 48 }) |
| 49 .catchError((e) { |
| 50 // TODO(kevmoo) Use logging here |
| 51 print("Unable to connect to 'pub serve' for '${request.uri}': $e"); |
| 52 throw new AssetError( |
| 53 "Unable to connect to 'pub serve' for '${request.uri}': $e"); |
| 54 }); |
| 55 } |
| 56 |
| 57 Future _serveFromFile(HttpRequest request, String path) { |
| 58 // Check if the request path is pointing to a static resource. |
| 59 path = normalize(path); |
| 60 return FileSystemEntity.isFile(root + path).then((exists) { |
| 61 if (exists) { |
| 62 return vd.serveFile(new File(root + path), request); |
| 63 } else { |
| 64 return _serve404(request); |
| 65 } |
| 66 }); |
| 67 } |
| 68 |
| 69 Future<Stream<List<int>>> _readFromPub(String path) { |
| 70 var uri = pubServeUrl.resolve(path); |
| 71 return client.openUrl('GET', uri) |
| 72 .then((request) => request.close()) |
| 73 .then((response) { |
| 74 if (response.statusCode == HttpStatus.OK) { |
| 75 return response; |
| 76 } else { |
| 77 throw new AssetError( |
| 78 "Failed to fetch asset '$path' from pub: " |
| 79 "${response.statusCode}."); |
| 80 } |
| 81 }) |
| 82 .catchError((error) { |
| 83 if (error is! AssetError) { |
| 84 error = new AssetError( |
| 85 "Failed to fetch asset '$path' from pub: '${path}': $error"); |
| 86 } |
| 87 throw error; |
| 88 }); |
| 89 } |
| 90 |
| 91 Future<Stream<List<int>>> _readFromFile(String path) { |
| 92 path = normalize(path); |
| 93 return FileSystemEntity.isFile(root + path).then((exists) { |
| 94 if (exists) { |
| 95 return new File(root + path).openRead(); |
| 96 } else { |
| 97 throw new AssetError("Asset '$path' not found"); |
| 98 } |
| 99 }); |
| 100 } |
| 101 |
| 102 Future _serve404(HttpRequest request) { |
| 103 // Serve 404. |
| 104 return request.drain().then((_) { |
| 105 request.response.statusCode = HttpStatus.NOT_FOUND; |
| 106 return request.response.close(); |
| 107 }); |
| 108 } |
| 109 |
| 110 Future<Stream<List<int>>> read(String path) { |
| 111 if (usePubServe) { |
| 112 return _readFromPub(path); |
| 113 } else { |
| 114 return _readFromFile(path); |
| 115 } |
| 116 } |
| 117 |
| 118 Future serve(HttpRequest request, String path) { |
| 119 if (usePubServe) { |
| 120 return _proxyToPub(request, path); |
| 121 } else { |
| 122 return _serveFromFile(request, path); |
| 123 } |
| 124 } |
| 125 } |
| 126 |
| 127 class AssetsImpl implements Assets { |
| 128 final HttpRequest request; |
| 129 final AppengineContext appengineContext; |
| 130 |
| 131 AssetsImpl(this.request, this.appengineContext); |
| 132 |
| 133 Future<Stream<List<int>>> read([String path]) { |
| 134 return appengineContext.assets.read( |
| 135 path == null ? request.uri.path : path); |
| 136 } |
| 137 |
| 138 void serve([String path]) { |
| 139 appengineContext.assets.serve(request, |
| 140 path == null ? request.uri.path : path); |
| 141 } |
| 142 } |
OLD | NEW |