Line data Source code
1 : import 'package:http_parser/http_parser.dart'; 2 : 3 : import 'utils.dart'; 4 : 5 : typedef HeaderForEachCallback = void Function(String name, List<String> values); 6 : 7 : class Headers { 8 : // Header field name 9 : static const acceptHeader = 'accept'; 10 : static const contentEncodingHeader = 'content-encoding'; 11 : static const contentLengthHeader = 'content-length'; 12 : static const contentTypeHeader = 'content-type'; 13 : static const wwwAuthenticateHeader = 'www-authenticate'; 14 : 15 : // Header field value 16 : static const jsonContentType = 'application/json; charset=utf-8'; 17 : static const formUrlEncodedContentType = 18 : 'application/x-www-form-urlencoded;charset=utf-8'; 19 : static const textPlainContentType = 'text/plain'; 20 : 21 15 : static final jsonMimeType = MediaType.parse(jsonContentType); 22 : 23 : final Map<String, List<String>> _map; 24 : 25 2 : Map<String, List<String>> get map => _map; 26 : 27 6 : Headers() : _map = caseInsensitiveKeyMap<List<String>>(); 28 : 29 7 : Headers.fromMap(Map<String, List<String>> map) 30 7 : : _map = caseInsensitiveKeyMap<List<String>>( 31 31 : map.map((k, v) => MapEntry(k.trim().toLowerCase(), v)), 32 : ); 33 : 34 : /// Returns the list of values for the header named [name]. If there 35 : /// is no header with the provided name, [:null:] will be returned. 36 3 : List<String>? operator [](String name) { 37 12 : return _map[name.trim().toLowerCase()]; 38 : } 39 : 40 : /// Convenience method for the value for a single valued header. If 41 : /// there is no header with the provided name, [:null:] will be 42 : /// returned. If the header has more than one value an exception is 43 : /// thrown. 44 3 : String? value(String name) { 45 3 : var arr = this[name]; 46 : if (arr == null) return null; 47 9 : if (arr.length == 1) return arr.first; 48 1 : throw Exception( 49 1 : '"$name" header has more than one value, please use Headers[name]'); 50 : } 51 : 52 : /// Adds a header value. The header named [name] will have the value 53 : /// [value] added to its list of values. 54 2 : void add(String name, String value) { 55 2 : var arr = this[name]; 56 1 : if (arr == null) return set(name, value); 57 1 : arr.add(value); 58 : } 59 : 60 : /// Sets a header. The header named [name] will have all its values 61 : /// cleared before the value [value] is added as its value. 62 2 : void set(String name, dynamic value) { 63 : if (value == null) return; 64 4 : name = name.trim().toLowerCase(); 65 2 : if (value is List) { 66 6 : _map[name] = value.map<String>((e) => e.toString()).toList(); 67 : } else { 68 10 : _map[name] = ['$value'.trim()]; 69 : } 70 : } 71 : 72 : /// Removes a specific value for a header name. 73 1 : void remove(String name, String value) { 74 1 : var arr = this[name]; 75 : if (arr == null) return; 76 3 : arr.removeWhere((v) => v == value); 77 : } 78 : 79 : /// Removes all values for the specified header name. 80 1 : void removeAll(String name) { 81 2 : _map.remove(name); 82 : } 83 : 84 1 : void clear() { 85 2 : _map.clear(); 86 : } 87 : 88 0 : bool get isEmpty => _map.isEmpty; 89 : 90 : /// Enumerates the headers, applying the function [f] to each 91 : /// header. The header name passed in [:name:] will be all lower 92 : /// case. 93 2 : void forEach(HeaderForEachCallback f) { 94 10 : _map.keys.forEach((key) => f(key, this[key]!)); 95 : } 96 : 97 1 : @override 98 : String toString() { 99 1 : var stringBuffer = StringBuffer(); 100 3 : _map.forEach((key, value) { 101 4 : value.forEach((e) => stringBuffer.writeln('$key: $e')); 102 : }); 103 1 : return stringBuffer.toString(); 104 : } 105 : }