diff --git a/README.md b/README.md index a6c58cac..0850305d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # angel_static -![version 1.1.0-dev+2](https://img.shields.io/badge/version-1.1.0--dev+2-red.svg) +![version 1.1.1](https://img.shields.io/badge/version-1.1.1-red.svg) ![build status](https://travis-ci.org/angel-dart/static.svg?branch=master) Static server middleware for Angel. @@ -39,3 +39,5 @@ The `VirtualDirectory` API accepts a few named parameters: angel_static is serving your files. If you are not serving static files at the site root, please include this. - **debug**: Print verbose debug output. +- **callback**: Runs before sending a file to a client. Use this to set headers, etc. If it returns anything other than `null` or `true`, +then the callback's result will be sent to the user, instead of the file contents. diff --git a/lib/src/virtual_directory.dart b/lib/src/virtual_directory.dart index 461d5c99..0de0a209 100644 --- a/lib/src/virtual_directory.dart +++ b/lib/src/virtual_directory.dart @@ -3,6 +3,8 @@ import 'dart:io'; import 'package:angel_framework/angel_framework.dart'; import 'package:angel_route/angel_route.dart'; +typedef StaticFileCallback(File file, RequestContext req, ResponseContext res); + final RegExp _param = new RegExp(r':([A-Za-z0-9_]+)(\((.+)\))?'); final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)'); @@ -27,6 +29,7 @@ class VirtualDirectory { String _prefix; Directory _source; Directory get source => _source; + final StaticFileCallback callback; final List indexFileNames; final String publicPath; @@ -34,7 +37,8 @@ class VirtualDirectory { {Directory source, this.debug: false, this.indexFileNames: const ['index.html'], - this.publicPath: '/'}) { + this.publicPath: '/', + this.callback}) { _prefix = publicPath.replaceAll(_straySlashes, ''); if (source != null) { @@ -53,9 +57,17 @@ class VirtualDirectory { call(AngelBase app) async => serve(app); - Future sendFile(File file, ResponseContext res) async { - _printDebug('Streaming file ${file.absolute.path}...'); + Future sendFile( + File file, RequestContext req, ResponseContext res) async { + _printDebug('Sending file ${file.absolute.path}...'); res.statusCode = 200; + + if (callback != null) { + var r = callback(file, req, res); + r = r is Future ? await r : r; + if (r != null && r != true) return r; + } + await res.streamFile(file); return false; } @@ -63,17 +75,14 @@ class VirtualDirectory { void serve(Router router) { _printDebug('Source directory: ${source.absolute.path}'); _printDebug('Public path prefix: "$_prefix"'); - - handler(RequestContext req, ResponseContext res) async { + router.get('$publicPath/*', + (RequestContext req, ResponseContext res) async { var path = req.path.replaceAll(_straySlashes, ''); - - return serveFile(path, res); - } - - router.get('$publicPath/*', handler); + return serveFile(path, req, res); + }); } - serveFile(String path, ResponseContext res) async { + serveFile(String path, RequestContext req, ResponseContext res) async { if (_prefix.isNotEmpty) { path = path.replaceAll(new RegExp('^' + _pathify(_prefix)), ''); } @@ -82,7 +91,7 @@ class VirtualDirectory { _printDebug('Attempting to statically serve file: ${file.absolute.path}'); if (await file.exists()) { - return sendFile(file, res); + return sendFile(file, req, res); } else { // Try to resolve index if (path.isEmpty) { @@ -90,7 +99,7 @@ class VirtualDirectory { final index = new File.fromUri(source.absolute.uri.resolve(indexFileName)); if (await index.exists()) { - return await sendFile(index, res); + return await sendFile(index, req, res); } } } else { diff --git a/pubspec.yaml b/pubspec.yaml index 8db7412e..f077cbde 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ environment: sdk: ">=1.19.0" homepage: https://github.com/angel-dart/angel_static author: thosakwe -version: 1.1.0-dev+2 +version: 1.1.1 dependencies: angel_framework: ^1.0.0-dev dev_dependencies: