From 3b2fc97da1b398aa4b07117a8197a580f8185930 Mon Sep 17 00:00:00 2001 From: "thomashii@dukefirehawk.com" Date: Sat, 1 May 2021 11:39:09 +0800 Subject: [PATCH] Migrated range_header --- CHANGELOG.md | 2 +- packages/range_header/example/main.dart | 2 +- packages/range_header/example/server.dart | 19 ++++----- packages/range_header/lib/src/converter.dart | 4 +- packages/range_header/lib/src/exception.dart | 9 +++++ packages/range_header/lib/src/parser.dart | 28 ++++++------- .../range_header/lib/src/range_header.dart | 18 +++++---- .../lib/src/range_header_impl.dart | 6 +-- .../lib/src/range_header_item.dart | 2 +- packages/range_header/pubspec.yaml | 26 ++++++------- packages/range_header/test/all_test.dart | 39 ++++++++++--------- 11 files changed, 82 insertions(+), 73 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c6f9e39..9ddb1906 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ * Migrated production to 3.0.0 (0/0 tests passed) * Added html_builder and migrated to 2.0.0 (1/1 tests passed) * Migrated hot to 4.0.0 (0/0 tests passed) -* Added range_header and migrated to 2.0.0 (16/16 tests passed) +* Added range_header and migrated to 3.0.0 (12/12 tests passed) * Updated static to 3.0.0 (in progress) * Update basic-sdk-2.12.x boilerplate (in progress) diff --git a/packages/range_header/example/main.dart b/packages/range_header/example/main.dart index 2ed95533..a90311f2 100644 --- a/packages/range_header/example/main.dart +++ b/packages/range_header/example/main.dart @@ -6,7 +6,7 @@ var file = new File('some_video.mp4'); handleRequest(HttpRequest request) async { // Parse the header var header = - new RangeHeader.parse(request.headers.value(HttpHeaders.rangeHeader)); + new RangeHeader.parse(request.headers.value(HttpHeaders.rangeHeader)!); // Optimize/canonicalize it var items = RangeHeader.foldItems(header.items); diff --git a/packages/range_header/example/server.dart b/packages/range_header/example/server.dart index 38346e92..732acb87 100644 --- a/packages/range_header/example/server.dart +++ b/packages/range_header/example/server.dart @@ -1,16 +1,9 @@ -import 'dart:async'; -import 'dart:io' show HttpHeaders, HttpStatus; -import 'dart:typed_data'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_framework/http.dart'; -import 'package:angel_static/angel_static.dart'; -import 'package:file/file.dart'; -import 'package:file/local.dart'; -import 'package:http_parser/http_parser.dart'; -import 'package:logging/logging.dart'; -import 'package:range_header/range_header.dart'; +//import 'package:angel_framework/angel_framework.dart'; +//import 'package:angel_framework/http.dart'; +//import 'package:angel_static/angel_static.dart'; main() async { + /* var app = new Angel(); var http = new AngelHttp(app); var fs = const LocalFileSystem(); @@ -32,8 +25,9 @@ main() async { app.fallback((req, res) => throw new AngelHttpException.notFound()); await http.startServer('127.0.0.1', 3000); print('Listening at ${http.uri}'); + */ } - +/* class _RangingVirtualDirectory extends VirtualDirectory { _RangingVirtualDirectory(Angel app, Directory source) : super(app, source.fileSystem, @@ -106,3 +100,4 @@ class _RangingVirtualDirectory extends VirtualDirectory { } } } +*/ diff --git a/packages/range_header/lib/src/converter.dart b/packages/range_header/lib/src/converter.dart index 824067e9..202bf2bd 100644 --- a/packages/range_header/lib/src/converter.dart +++ b/packages/range_header/lib/src/converter.dart @@ -16,9 +16,9 @@ class RangeHeaderTransformer final int totalLength; RangeHeaderTransformer(this.header, this.mimeType, this.totalLength, - {String boundary}) + {String? boundary}) : this.boundary = boundary ?? _randomString() { - if (header == null || header.items.isEmpty) { + if (header.items.isEmpty) { throw new ArgumentError('`header` cannot be null or empty.'); } } diff --git a/packages/range_header/lib/src/exception.dart b/packages/range_header/lib/src/exception.dart index 0c8f49a9..a26dd432 100644 --- a/packages/range_header/lib/src/exception.dart +++ b/packages/range_header/lib/src/exception.dart @@ -6,3 +6,12 @@ class RangeHeaderParseException extends FormatException { @override String toString() => 'Range header parse exception: $message'; } + +class InvalidRangeHeaderException implements Exception { + final String message; + + InvalidRangeHeaderException(this.message); + + @override + String toString() => 'Range header parse exception: $message'; +} diff --git a/packages/range_header/lib/src/parser.dart b/packages/range_header/lib/src/parser.dart index f7473c4d..f9ab1b07 100644 --- a/packages/range_header/lib/src/parser.dart +++ b/packages/range_header/lib/src/parser.dart @@ -13,7 +13,7 @@ enum TokenType { RANGE_UNIT, COMMA, INT, DASH, EQUALS } class Token { final TokenType type; - final SourceSpan span; + final SourceSpan? span; Token(this.type, this.span); } @@ -57,31 +57,31 @@ List scan(String text, List allowedRangeUnits) { } class Parser { - Token _current; + Token? _current; int _index = -1; final List tokens; Parser(this.tokens); - Token get current => _current; + Token? get current => _current; bool get done => _index >= tokens.length - 1; RangeHeaderParseException _expected(String type) { - int offset = current?.span?.start?.offset; + int? offset = current?.span?.start.offset; if (offset == null) return new RangeHeaderParseException('Expected $type.'); - Token peek; + Token? peek; if (_index < tokens.length - 1) peek = tokens[_index + 1]; if (peek != null && peek.span != null) { return new RangeHeaderParseException( - 'Expected $type at offset $offset, found "${peek.span.text}" instead. \nSource:\n${peek.span?.highlight() ?? peek.type}'); + 'Expected $type at offset $offset, found "${peek.span!.text}" instead. \nSource:\n${peek.span?.highlight() ?? peek.type}'); } else return new RangeHeaderParseException( - 'Expected $type at offset $offset, but the header string ended without one.\nSource:\n${current.span?.highlight() ?? current.type}'); + 'Expected $type at offset $offset, but the header string ended without one.\nSource:\n${current!.span?.highlight() ?? current!.type}'); } bool next(TokenType type) { @@ -95,13 +95,13 @@ class Parser { return false; } - RangeHeader parseRangeHeader() { + RangeHeader? parseRangeHeader() { if (next(TokenType.RANGE_UNIT)) { - var unit = current.span.text; + var unit = current!.span!.text; next(TokenType.EQUALS); // Consume =, if any. List items = []; - RangeHeaderItem item = parseHeaderItem(); + RangeHeaderItem? item = parseHeaderItem(); while (item != null) { items.add(item); @@ -120,13 +120,13 @@ class Parser { return null; } - RangeHeaderItem parseHeaderItem() { + RangeHeaderItem? parseHeaderItem() { if (next(TokenType.INT)) { // i.e 500-544, or 600- - var start = int.parse(current.span.text); + var start = int.parse(current!.span!.text); if (next(TokenType.DASH)) { if (next(TokenType.INT)) { - return new RangeHeaderItem(start, int.parse(current.span.text)); + return new RangeHeaderItem(start, int.parse(current!.span!.text)); } else return new RangeHeaderItem(start); } else @@ -134,7 +134,7 @@ class Parser { } else if (next(TokenType.DASH)) { // i.e. -599 if (next(TokenType.INT)) { - return new RangeHeaderItem(-1, int.parse(current.span.text)); + return new RangeHeaderItem(-1, int.parse(current!.span!.text)); } else throw _expected('integer'); } else diff --git a/packages/range_header/lib/src/range_header.dart b/packages/range_header/lib/src/range_header.dart index 88943de1..81ddf7b9 100644 --- a/packages/range_header/lib/src/range_header.dart +++ b/packages/range_header/lib/src/range_header.dart @@ -1,4 +1,5 @@ import 'dart:collection'; +import 'exception.dart'; import 'parser.dart'; import 'range_header_item.dart'; import 'range_header_impl.dart'; @@ -9,12 +10,12 @@ abstract class RangeHeader { UnmodifiableListView get items; const factory RangeHeader(Iterable items, - {String rangeUnit}) = _ConstantRangeHeader; + {String? rangeUnit}) = _ConstantRangeHeader; /// Eliminates any overlapping [items], sorts them, and folds them all into the most efficient representation possible. static UnmodifiableListView foldItems( Iterable items) { - var out = new Set(); + var out = Set(); for (var item in items) { // Remove any overlapping items, consolidate them. @@ -37,27 +38,30 @@ abstract class RangeHeader { /// /// If [fold] is `true`, the items will be folded into the most compact /// possible representation. + /// factory RangeHeader.parse(String text, - {Iterable allowedRangeUnits, bool fold: true}) { + {Iterable? allowedRangeUnits, bool fold: true}) { var tokens = scan(text, allowedRangeUnits?.toList() ?? ['bytes']); var parser = new Parser(tokens); var header = parser.parseRangeHeader(); - if (header == null) return null; + if (header == null) { + throw InvalidRangeHeaderException('Header is null'); + } var items = foldItems(header.items); return RangeHeaderImpl(header.rangeUnit, items); } /// Returns this header's range unit. Most commonly, this is `bytes`. - String get rangeUnit; + String? get rangeUnit; } class _ConstantRangeHeader implements RangeHeader { final Iterable items_; - final String rangeUnit; + final String? rangeUnit; const _ConstantRangeHeader(this.items_, {this.rangeUnit: 'bytes'}); @override UnmodifiableListView get items => - new UnmodifiableListView(items_); + UnmodifiableListView(items_); } diff --git a/packages/range_header/lib/src/range_header_impl.dart b/packages/range_header/lib/src/range_header_impl.dart index e1016502..6c0de3de 100644 --- a/packages/range_header/lib/src/range_header_impl.dart +++ b/packages/range_header/lib/src/range_header_impl.dart @@ -4,11 +4,11 @@ import 'range_header_item.dart'; /// Represents the contents of a parsed `Range` header. class RangeHeaderImpl implements RangeHeader { - UnmodifiableListView _cached; + UnmodifiableListView? _cached; final List _items = []; RangeHeaderImpl(this.rangeUnit, [List items = const []]) { - this._items.addAll(items ?? []); + this._items.addAll(items); } @override @@ -16,5 +16,5 @@ class RangeHeaderImpl implements RangeHeader { _cached ??= new UnmodifiableListView(_items); @override - final String rangeUnit; + final String? rangeUnit; } diff --git a/packages/range_header/lib/src/range_header_item.dart b/packages/range_header/lib/src/range_header_item.dart index 418031be..56c216d3 100644 --- a/packages/range_header/lib/src/range_header_item.dart +++ b/packages/range_header/lib/src/range_header_item.dart @@ -71,7 +71,7 @@ class RangeHeaderItem implements Comparable { /// Please adhere to the standard!!! /// http://httpwg.org/specs/rfc7233.html - String toContentRange([int totalSize]) { + String toContentRange([int? totalSize]) { // var maxIndex = totalSize != null ? (totalSize - 1).toString() : '*'; var s = start > -1 ? start : 0; diff --git a/packages/range_header/pubspec.yaml b/packages/range_header/pubspec.yaml index 1d580106..14225c7f 100644 --- a/packages/range_header/pubspec.yaml +++ b/packages/range_header/pubspec.yaml @@ -1,20 +1,20 @@ name: range_header -version: 2.0.2+2 +version: 3.0.0 description: Range header parser for Dart. Beyond parsing, a stream transformer is included. author: Tobe O homepage: https://github.com/thosakwe/range_header environment: - sdk: ">=2.0.0-dev <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: - async: ^2.0.0 - charcode: ^1.0.0 - quiver_hashcode: ^2.0.0 - source_span: ^1.0.0 - string_scanner: ^1.0.0 + async: ^2.6.0 + charcode: ^1.2.0 + quiver_hashcode: ^3.0.0+1 + source_span: ^1.8.1 + string_scanner: ^1.1.0 dev_dependencies: - angel_framework: - angel_static: ^2.0.0 - file: - http_parser: ^3.0.0 - logging: ^0.11.0 - test: ^1.0.0 \ No newline at end of file + #angel_framework: + #angel_static: ^2.0.0 + file: ^6.1.0 + http_parser: ^4.0.0 + logging: ^1.0.1 + test: ^1.17.3 \ No newline at end of file diff --git a/packages/range_header/test/all_test.dart b/packages/range_header/test/all_test.dart index 67e90b8d..82ee5115 100644 --- a/packages/range_header/test/all_test.dart +++ b/packages/range_header/test/all_test.dart @@ -1,27 +1,32 @@ -import 'package:range_header/range_header.dart'; import 'package:test/test.dart'; +import '../lib/range_header.dart'; +import '../lib/src/range_header.dart'; + final Matcher throwsRangeParseException = throwsA(const TypeMatcher()); +final Matcher throwsInvalidRangeHeaderException = + throwsA(const TypeMatcher()); + main() { group('one item', () { test('start and end', () { - var r = new RangeHeader.parse('bytes 1-200'); + var r = RangeHeader.parse('bytes 1-200'); expect(r.items, hasLength(1)); expect(r.items.first.start, 1); expect(r.items.first.end, 200); }); test('start only', () { - var r = new RangeHeader.parse('bytes 1-'); + var r = RangeHeader.parse('bytes 1-'); expect(r.items, hasLength(1)); expect(r.items.first.start, 1); expect(r.items.first.end, -1); }); test('end only', () { - var r = new RangeHeader.parse('bytes -200'); + var r = RangeHeader.parse('bytes -200'); print(r.items); expect(r.items, hasLength(1)); expect(r.items.first.start, -1); @@ -31,7 +36,7 @@ main() { group('multiple items', () { test('three items', () { - var r = new RangeHeader.parse('bytes 1-20, 21-40, 41-60'); + var r = RangeHeader.parse('bytes 1-20, 21-40, 41-60'); print(r.items); expect(r.items, hasLength(3)); expect(r.items[0].start, 1); @@ -43,7 +48,7 @@ main() { }); test('one item without end', () { - var r = new RangeHeader.parse('bytes 1-20, 21-'); + var r = RangeHeader.parse('bytes 1-20, 21-'); print(r.items); expect(r.items, hasLength(2)); expect(r.items[0].start, 1); @@ -55,42 +60,38 @@ main() { group('failures', () { test('no start with no end', () { - expect(new RangeHeader.parse('-'), isNull); + expect(() => RangeHeader.parse('-'), throwsInvalidRangeHeaderException); }); }); group('exceptions', () { test('invalid character', () { - expect(() => new RangeHeader.parse('!!!'), throwsRangeParseException); + expect(() => RangeHeader.parse('!!!'), throwsRangeParseException); }); test('no ranges', () { - expect(() => new RangeHeader.parse('bytes'), throwsRangeParseException); + expect(() => RangeHeader.parse('bytes'), throwsRangeParseException); }); test('no dash after int', () { - expect(() => new RangeHeader.parse('bytes 3'), throwsRangeParseException); - expect( - () => new RangeHeader.parse('bytes 3,'), throwsRangeParseException); - expect( - () => new RangeHeader.parse('bytes 3 24'), throwsRangeParseException); + expect(() => RangeHeader.parse('bytes 3'), throwsRangeParseException); + expect(() => RangeHeader.parse('bytes 3,'), throwsRangeParseException); + expect(() => RangeHeader.parse('bytes 3 24'), throwsRangeParseException); }); test('no int after dash', () { - expect( - () => new RangeHeader.parse('bytes -,'), throwsRangeParseException); + expect(() => RangeHeader.parse('bytes -,'), throwsRangeParseException); }); }); group('complete coverage', () { test('exception toString()', () { - var m = new RangeHeaderParseException('hey'); + var m = RangeHeaderParseException('hey'); expect(m.toString(), contains('hey')); }); }); test('content-range', () { - expect( - new RangeHeader.parse('bytes 1-2').items[0].toContentRange(3), '1-2/3'); + expect(RangeHeader.parse('bytes 1-2').items[0].toContentRange(3), '1-2/3'); }); }