Line data Source code
1 : import 'dart:io'; 2 : 3 : import 'package:intl/intl.dart'; 4 : 5 : /// 6 : /// 7 : /// 8 : class CurtHttpHeaders implements HttpHeaders { 9 : final Map<String, List<String>> _headers = <String, List<String>>{}; 10 : 11 : // TODO(anyone): properly implement these stubbed properties and methods? 12 : /// All of these go unused for our current use cases, so they're being stubbed 13 : @override 14 : bool chunkedTransferEncoding = true; 15 : 16 : @override 17 : int contentLength = -1; 18 : 19 : @override 20 : ContentType? contentType; 21 : 22 : @override 23 : DateTime? date; 24 : 25 : @override 26 : DateTime? expires; 27 : 28 : @override 29 : String? host; 30 : 31 : @override 32 : DateTime? ifModifiedSince; 33 : 34 : @override 35 : bool persistentConnection = true; 36 : 37 : @override 38 : int? port; 39 : 40 : /// 41 : /// 42 : /// 43 0 : @override 44 : void noFolding(String name) {} 45 : 46 : /// 47 : /// 48 : /// 49 1 : void _add(String name, String value) { 50 1 : final String lowerName = name.toLowerCase(); 51 : 52 : switch (lowerName) { 53 1 : case HttpHeaders.contentLengthHeader: 54 2 : contentLength = int.tryParse(value) ?? -1; 55 : break; 56 1 : case HttpHeaders.dateHeader: 57 : try { 58 3 : date = DateFormat('EEE, dd MMM yyyy HH:mm:ss zzz').parse(value); 59 0 : } on Exception catch (_) {} 60 : break; 61 : } 62 : 63 2 : if (_headers.containsKey(lowerName)) { 64 0 : if (!_headers[lowerName]!.contains(value)) { 65 0 : _headers[lowerName]!.add(value); 66 : } 67 : } else { 68 3 : _headers[lowerName] = <String>[value]; 69 : } 70 : } 71 : 72 : /// 73 : /// 74 : /// 75 0 : void _remove(String name, String value) { 76 0 : final String lowerName = name.toLowerCase(); 77 0 : if (_headers.containsKey(lowerName)) { 78 0 : _headers[lowerName]!.remove(value); 79 0 : if (_headers[lowerName]!.isEmpty) { 80 0 : _headers.remove(lowerName); 81 : } 82 : } 83 : } 84 : 85 : /// 86 : /// 87 : /// 88 0 : void _addAll(String name, Iterable<String> values) { 89 0 : for (final String value in values) { 90 0 : _add(name, value); 91 : } 92 : } 93 : 94 : /// 95 : /// 96 : /// 97 0 : void _removeAll(String name, Iterable<String> values) { 98 0 : for (final String value in values) { 99 0 : _remove(name, value); 100 : } 101 : } 102 : 103 : /// 104 : /// 105 : /// 106 0 : @override 107 : void set(String name, Object value, {bool preserveHeaderCase = false}) { 108 0 : final String nameToUse = preserveHeaderCase ? name : name.toLowerCase(); 109 0 : if (value is Iterable) { 110 0 : _headers[nameToUse] = value.map((dynamic v) => v.toString()).toList(); 111 : } else { 112 0 : _headers[nameToUse] = <String>[value.toString()]; 113 : } 114 : } 115 : 116 : /// 117 : /// 118 : /// 119 1 : @override 120 : void add(String name, Object value, {bool preserveHeaderCase = false}) { 121 1 : final String nameToUse = preserveHeaderCase ? name : name.toLowerCase(); 122 1 : if (value is Iterable) { 123 0 : _addAll(nameToUse, value.map((dynamic v) => v.toString())); 124 : } else { 125 2 : _add(nameToUse, value.toString()); 126 : } 127 : } 128 : 129 : /// 130 : /// 131 : /// 132 1 : @override 133 2 : void clear() => _headers.clear(); 134 : 135 : /// 136 : /// 137 : /// 138 0 : @override 139 : void remove(String name, Object value) { 140 0 : if (value is Iterable) { 141 0 : _removeAll(name, value.map((dynamic v) => v.toString())); 142 : } else { 143 0 : _remove(name, value.toString()); 144 : } 145 : } 146 : 147 : /// 148 : /// 149 : /// 150 0 : @override 151 0 : void removeAll(String name) => _headers.remove(name.toLowerCase()); 152 : 153 : /// 154 : /// 155 : /// 156 0 : @override 157 : void forEach(void Function(String name, List<String> values) action) => 158 0 : _headers.forEach(action); 159 : 160 : /// 161 : /// 162 : /// 163 1 : @override 164 : String? value(String name) { 165 1 : final String lowerName = name.toLowerCase(); 166 5 : if (_headers.containsKey(lowerName) && _headers[lowerName]!.isNotEmpty) { 167 3 : return _headers[lowerName]!.first; 168 : } 169 : return null; 170 : } 171 : 172 : /// 173 : /// 174 : /// 175 0 : @override 176 0 : List<String>? operator [](String name) => _headers[name.toLowerCase()]; 177 : 178 : /// 179 : /// 180 : /// 181 0 : @override 182 0 : String toString() => _headers.toString(); 183 : 184 : /// 185 : /// 186 : /// 187 0 : bool get isEmpty => _headers.isEmpty; 188 : 189 : /// 190 : /// 191 : /// 192 3 : bool get isNotEmpty => _headers.isNotEmpty; 193 : 194 : /// 195 : /// 196 : /// 197 1 : List<Cookie> get cookies { 198 2 : if (!_headers.containsKey(HttpHeaders.setCookieHeader)) { 199 1 : return <Cookie>[]; 200 : } 201 0 : final Map<String, String> rawInfo = <String, String>{}; 202 0 : for (final String rawValue in _headers[HttpHeaders.setCookieHeader]!) { 203 0 : final Cookie cookie = Cookie.fromSetCookieValue(rawValue); 204 0 : rawInfo[cookie.name] = cookie.value; // This prevents duplicate cookies 205 : } 206 0 : return rawInfo.entries 207 0 : .map((MapEntry<String, String> entry) => Cookie(entry.key, entry.value)) 208 0 : .toList(); 209 : } 210 : 211 : }