blob: 0049f1d9cad716570e4a6608bb1cbf9dccced3b1 [file] [log] [blame]
library shelf_static;
import 'dart:io';
import 'package:path/path.dart' as p;
import 'package:shelf/shelf.dart';
// directory listing
// default document
// sym links
// mime type handling
// hidden files
// If-Modified-Since on request
Handler getHandler(String fileSystemPath) {
var rootDir = new Directory(fileSystemPath);
fileSystemPath = rootDir.resolveSymbolicLinksSync();
return (Request request) {
// TODO: expand these checks and/or follow updates to Uri class to be more
// strict. https://code.google.com/p/dart/issues/detail?id=16081
if (request.requestedUri.path.contains(' ')) {
return new Response.forbidden('The requested path is invalid.');
}
var segs = [fileSystemPath]..addAll(request.url.pathSegments);
var requestedPath = p.joinAll(segs);
var file = new File(requestedPath);
if (!file.existsSync()) {
return new Response.notFound('Not Found');
}
var resolvedPath = file.resolveSymbolicLinksSync();
// Do not serve a file outside of the original fileSystemPath
if (!p.isWithin(fileSystemPath, resolvedPath)) {
// TODO(kevmoo) throw a real error here. Perhaps a new error type?
throw 'Requested path ${request.url.path} resolved to $resolvedPath '
'is not under $fileSystemPath.';
}
var fileStat = file.statSync();
var headers = <String, String>{
HttpHeaders.CONTENT_LENGTH: fileStat.size.toString(),
HttpHeaders.LAST_MODIFIED: _formatHttpDate(fileStat.changed)
};
return new Response.ok(file.openRead(), headers: headers);
};
}
const _WEEKDAYS = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
const _MONTHS = const ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"];
// TODO(kevmoo) remove once http_parser fix
// https://codereview.chromium.org/278783002/ is landed
String _formatHttpDate(DateTime date) {
date = date.toUtc();
var buffer = new StringBuffer()
..write(_WEEKDAYS[date.weekday - 1])
..write(", ")
..write(date.day <= 9 ? "0" : "")
..write(date.day.toString())
..write(" ")
..write(_MONTHS[date.month - 1])
..write(" ")
..write(date.year.toString())
..write(date.hour <= 9 ? " 0" : " ")
..write(date.hour.toString())
..write(date.minute <= 9 ? ":0" : ":")
..write(date.minute.toString())
..write(date.second <= 9 ? ":0" : ":")
..write(date.second.toString())
..write(" GMT");
return buffer.toString();
}