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 : }
|