public void RangeHeader_Reports_Syntactically_Invalid_Byte_Ranges() { Assert.IsFalse(RangeHeader.IsValid(CreateHeadersWithRange(""))); Assert.IsFalse(RangeHeader.IsValid(CreateHeadersWithRange("foobar"))); Assert.IsFalse(RangeHeader.IsValid(CreateHeadersWithRange("furlongs=123-456"))); Assert.IsFalse(RangeHeader.IsValid(CreateHeadersWithRange("bytes="))); Assert.IsFalse(RangeHeader.IsValid(CreateHeadersWithRange(""))); // A range of non-positive length is syntactically invalid and ignored: Assert.IsNull(CreateByteRanges("bytes=123,456", 500)); Assert.IsNull(CreateByteRanges("bytes=456-123", 500)); Assert.IsNull(CreateByteRanges("bytes=456-455", 500)); }
private Task Serve(IDictionary <string, object> env) { Request request = new Request(env); Response response = new Response(env); var fileInfo = new FileInfo(path); var size = fileInfo.Length; if (!RangeHeader.IsValid(request.Headers)) { response.StatusCode = OK; range = new Tuple <long, long>(0, size - 1); } else { var ranges = RangeHeader.Parse(request.Headers, size); if (ranges == null) { // Unsatisfiable. Return error and file size. return(Fail( RequestedRangeNotSatisfiable, "Byte range unsatisfiable", "Content-Range", "bytes */" + size) .Invoke(env)); } if (ranges.Count() > 1) { // TODO: Support multiple byte ranges. response.StatusCode = OK; range = new Tuple <long, long>(0, size - 1); } else { // Partial content range = ranges.First(); response.StatusCode = PartialContent; response.Headers.SetHeader("Content-Range", "bytes " + range.Item1 + "-" + range.Item2 + "/" + size); size = range.Item2 - range.Item1 + 1; } } response.Headers .SetHeader("Last-Modified", fileInfo.LastWriteTimeUtc.ToHttpDateString()) .SetHeader("Content-Type", Mime.MimeType(fileInfo.Extension, "text/plain")) .SetHeader("Content-Length", size.ToString(CultureInfo.InvariantCulture)); return(new FileBody(path, range).Start(response.OutputStream)); }
private Task Serve(IDictionary <string, object> env, string path) { Request request = new Request(env); Response response = new Response(env); var fileInfo = new FileInfo(path); var size = fileInfo.Length; Tuple <long, long> range; if (!RangeHeader.IsValid(request.Headers)) { response.StatusCode = OK; range = new Tuple <long, long>(0, size - 1); } else { var ranges = RangeHeader.Parse(request.Headers, size); if (ranges == null) { // Unsatisfiable. Return error and file size. return(Fail( RequestedRangeNotSatisfiable, "Byte range unsatisfiable", "Content-Range", "bytes */" + size) .Invoke(env)); } if (ranges.Count() > 1) { // TODO: Support multiple byte ranges. response.StatusCode = OK; range = new Tuple <long, long>(0, size - 1); } else { // Partial content range = ranges.First(); response.StatusCode = PartialContent; response.Headers.SetHeader("Content-Range", "bytes " + range.Item1 + "-" + range.Item2 + "/" + size); size = range.Item2 - range.Item1 + 1; } } response.Headers .SetHeader("Last-Modified", fileInfo.LastWriteTimeUtc.ToHttpDateString()) .SetHeader("Content-Type", Mime.MimeType(fileInfo.Extension, "text/plain")) .SetHeader("Content-Length", size.ToString(CultureInfo.InvariantCulture)); if ("HEAD".Equals(request.Method, StringComparison.OrdinalIgnoreCase)) { // Suppress the body. return(TaskHelpers.Completed()); } FileBody body = new FileBody(path, range); //TODO: update for current send file spec //var req = new Request(env); //SendFileFunc sendFile = env.Get<SendFileFunc>("sendfile.Func"); //if (sendFile != null) //{ // return body.Start(sendFile); //} return(body.Start(response.OutputStream)); }