Shelf response ctx
This commit is contained in:
parent
b115aae975
commit
548f5d7704
1 changed files with 120 additions and 0 deletions
|
@ -0,0 +1,120 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
|
import 'package:shelf/shelf.dart' as shelf;
|
||||||
|
import 'shelf_request.dart';
|
||||||
|
|
||||||
|
class ShelfResponseContext extends ResponseContext<ShelfResponseContext> {
|
||||||
|
final Angel app;
|
||||||
|
final ShelfRequestContext correspondingRequest;
|
||||||
|
final StreamController<List<int>> _ctrl = StreamController();
|
||||||
|
bool _isOpen = true, _isDetached = false;
|
||||||
|
|
||||||
|
ShelfResponseContext(this.app, this.correspondingRequest);
|
||||||
|
|
||||||
|
shelf.Response get shelfResponse {
|
||||||
|
return shelf.Response(statusCode, body: _ctrl.stream, headers: headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() {
|
||||||
|
_isOpen = false;
|
||||||
|
_ctrl.close();
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterable<String> __allowedEncodings;
|
||||||
|
|
||||||
|
Iterable<String> get _allowedEncodings {
|
||||||
|
return __allowedEncodings ??= correspondingRequest.headers
|
||||||
|
.value('accept-encoding')
|
||||||
|
?.split(',')
|
||||||
|
?.map((s) => s.trim())
|
||||||
|
?.where((s) => s.isNotEmpty)
|
||||||
|
?.map((str) {
|
||||||
|
// Ignore quality specifications in accept-encoding
|
||||||
|
// ex. gzip;q=0.8
|
||||||
|
if (!str.contains(';')) return str;
|
||||||
|
return str.split(';')[0];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future addStream(Stream<List<int>> stream) {
|
||||||
|
if (!isOpen && isBuffered) throw ResponseContext.closed();
|
||||||
|
Stream<List<int>> output = stream;
|
||||||
|
|
||||||
|
if (encoders.isNotEmpty && correspondingRequest != null) {
|
||||||
|
if (_allowedEncodings != null) {
|
||||||
|
for (var encodingName in _allowedEncodings) {
|
||||||
|
Converter<List<int>, List<int>> encoder;
|
||||||
|
String key = encodingName;
|
||||||
|
|
||||||
|
if (encoders.containsKey(encodingName)) {
|
||||||
|
encoder = encoders[encodingName];
|
||||||
|
} else if (encodingName == '*') {
|
||||||
|
encoder = encoders[key = encoders.keys.first];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoder != null) {
|
||||||
|
output = encoders[key].bind(output);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _ctrl.addStream(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void add(List<int> data) {
|
||||||
|
if (!isOpen && isBuffered) {
|
||||||
|
throw ResponseContext.closed();
|
||||||
|
} else if (_isOpen) {
|
||||||
|
if (encoders.isNotEmpty && correspondingRequest != null) {
|
||||||
|
if (_allowedEncodings != null) {
|
||||||
|
for (var encodingName in _allowedEncodings) {
|
||||||
|
Converter<List<int>, List<int>> encoder;
|
||||||
|
String key = encodingName;
|
||||||
|
|
||||||
|
if (encoders.containsKey(encodingName)) {
|
||||||
|
encoder = encoders[encodingName];
|
||||||
|
} else if (encodingName == '*') {
|
||||||
|
encoder = encoders[key = encoders.keys.first];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoder != null) {
|
||||||
|
data = encoders[key].convert(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ctrl.add(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
BytesBuilder get buffer => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<ShelfResponseContext> detach() {
|
||||||
|
_isDetached = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isBuffered => false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isOpen => _isOpen && !_isDetached;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void useBuffer() {}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ShelfResponseContext get rawResponse => this;
|
||||||
|
}
|
Loading…
Reference in a new issue