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