1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.foxinmy.weixin4j.http;
18
19 import java.io.Serializable;
20 import java.net.URI;
21 import java.nio.charset.Charset;
22 import java.text.ParseException;
23 import java.text.SimpleDateFormat;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.Date;
28 import java.util.EnumSet;
29 import java.util.Iterator;
30 import java.util.LinkedHashMap;
31 import java.util.LinkedList;
32 import java.util.List;
33 import java.util.Locale;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.TimeZone;
37
38 import com.foxinmy.weixin4j.util.LinkedCaseInsensitiveMap;
39 import com.foxinmy.weixin4j.util.MultiValueMap;
40 import com.foxinmy.weixin4j.util.StringUtil;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public class HttpHeaders implements MultiValueMap<String, String>, Serializable {
65
66 private static final long serialVersionUID = -8578554704772377436L;
67
68
69
70
71
72
73
74 public static final String ACCEPT = "Accept";
75
76
77
78
79
80
81 public static final String ACCEPT_CHARSET = "Accept-Charset";
82
83
84
85
86
87
88 public static final String ACCEPT_ENCODING = "Accept-Encoding";
89
90
91
92
93
94
95 public static final String ACCEPT_LANGUAGE = "Accept-Language";
96
97
98
99
100
101
102 public static final String ACCEPT_RANGES = "Accept-Ranges";
103
104
105
106
107
108
109 public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
110
111
112
113
114
115 public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
116
117
118
119
120
121 public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
122
123
124
125
126
127 public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
128
129
130
131
132
133
134 public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
135
136
137
138
139
140 public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
141
142
143
144
145
146
147 public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
148
149
150
151
152
153 public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
154
155
156
157
158
159
160 public static final String AGE = "Age";
161
162
163
164
165
166
167 public static final String ALLOW = "Allow";
168
169
170
171
172
173
174 public static final String AUTHORIZATION = "Authorization";
175
176
177
178
179
180
181 public static final String CACHE_CONTROL = "Cache-Control";
182
183
184
185
186
187
188 public static final String CONNECTION = "Connection";
189
190
191
192
193
194
195 public static final String CONTENT_ENCODING = "Content-Encoding";
196
197
198
199
200
201 public static final String CONTENT_DISPOSITION = "Content-Disposition";
202
203
204
205
206
207
208 public static final String CONTENT_LANGUAGE = "Content-Language";
209
210
211
212
213
214
215 public static final String CONTENT_LENGTH = "Content-Length";
216
217
218
219
220
221
222 public static final String CONTENT_LOCATION = "Content-Location";
223
224
225
226
227
228
229 public static final String CONTENT_RANGE = "Content-Range";
230
231
232
233
234
235
236 public static final String CONTENT_TYPE = "Content-Type";
237
238
239
240
241
242
243 public static final String COOKIE = "Cookie";
244
245
246
247
248
249
250 public static final String DATE = "Date";
251
252
253
254
255
256
257 public static final String ETAG = "ETag";
258
259
260
261
262
263
264 public static final String EXPECT = "Expect";
265
266
267
268
269
270
271 public static final String EXPIRES = "Expires";
272
273
274
275
276
277
278 public static final String FROM = "From";
279
280
281
282
283
284
285 public static final String HOST = "Host";
286
287
288
289
290
291
292 public static final String IF_MATCH = "If-Match";
293
294
295
296
297
298
299 public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
300
301
302
303
304
305
306 public static final String IF_NONE_MATCH = "If-None-Match";
307
308
309
310
311
312
313 public static final String IF_RANGE = "If-Range";
314
315
316
317
318
319
320 public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
321
322
323
324
325
326
327 public static final String LAST_MODIFIED = "Last-Modified";
328
329
330
331
332
333 public static final String LINK = "Link";
334
335
336
337
338
339
340 public static final String LOCATION = "Location";
341
342
343
344
345
346
347 public static final String MAX_FORWARDS = "Max-Forwards";
348
349
350
351
352
353 public static final String ORIGIN = "Origin";
354
355
356
357
358
359
360 public static final String PRAGMA = "Pragma";
361
362
363
364
365
366
367 public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
368
369
370
371
372
373
374 public static final String PROXY_AUTHORIZATION = "Proxy-Authorization";
375
376
377
378
379
380
381 public static final String RANGE = "Range";
382
383
384
385
386
387
388 public static final String REFERER = "Referer";
389
390
391
392
393
394
395 public static final String RETRY_AFTER = "Retry-After";
396
397
398
399
400
401
402 public static final String SERVER = "Server";
403
404
405
406
407
408
409 public static final String SET_COOKIE = "Set-Cookie";
410
411
412
413
414
415 public static final String SET_COOKIE2 = "Set-Cookie2";
416
417
418
419
420
421
422 public static final String TE = "TE";
423
424
425
426
427
428
429 public static final String TRAILER = "Trailer";
430
431
432
433
434
435
436 public static final String TRANSFER_ENCODING = "Transfer-Encoding";
437
438
439
440
441
442
443 public static final String UPGRADE = "Upgrade";
444
445
446
447
448
449
450 public static final String USER_AGENT = "User-Agent";
451
452
453
454
455
456
457 public static final String VARY = "Vary";
458
459
460
461
462
463
464 public static final String VIA = "Via";
465
466
467
468
469
470
471 public static final String WARNING = "Warning";
472
473
474
475
476
477
478 public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
479
480
481
482
483
484
485
486
487 private static final String[] DATE_FORMATS = new String[] {
488 "EEE, dd MMM yyyy HH:mm:ss zzz", "EEE, dd-MMM-yy HH:mm:ss zzz",
489 "EEE MMM dd HH:mm:ss yyyy" };
490
491 private static TimeZone GMT = TimeZone.getTimeZone("GMT");
492
493 private final Map<String, List<String>> headers;
494
495
496
497
498 public HttpHeaders() {
499 this(new LinkedCaseInsensitiveMap<List<String>>(8, Locale.ENGLISH),
500 false);
501 }
502
503
504
505
506
507 private HttpHeaders(Map<String, List<String>> headers, boolean readOnly) {
508 if (readOnly) {
509 Map<String, List<String>> map = new LinkedCaseInsensitiveMap<List<String>>(
510 headers.size(), Locale.ENGLISH);
511 for (Entry<String, List<String>> entry : headers.entrySet()) {
512 List<String> values = Collections.unmodifiableList(entry
513 .getValue());
514 map.put(entry.getKey(), values);
515 }
516 this.headers = Collections.unmodifiableMap(map);
517 } else {
518 this.headers = headers;
519 }
520 }
521
522
523
524
525
526 public void setAccept(List<ContentType> acceptableMediaTypes) {
527 set(ACCEPT, ContentType.toString(acceptableMediaTypes));
528 }
529
530
531
532
533
534
535
536 public String getAccept() {
537 return getFirst(ACCEPT);
538 }
539
540
541
542
543
544 public void setAccessControlAllowCredentials(boolean allowCredentials) {
545 set(ACCESS_CONTROL_ALLOW_CREDENTIALS,
546 Boolean.toString(allowCredentials));
547 }
548
549
550
551
552
553 public boolean getAccessControlAllowCredentials() {
554 return Boolean.valueOf(getFirst(ACCESS_CONTROL_ALLOW_CREDENTIALS));
555 }
556
557
558
559
560
561 public void setAccessControlAllowHeaders(List<String> allowedHeaders) {
562 set(ACCESS_CONTROL_ALLOW_HEADERS,
563 toCommaDelimitedString(allowedHeaders));
564 }
565
566
567
568
569
570 public List<String> getAccessControlAllowHeaders() {
571 return getFirstValueAsList(ACCESS_CONTROL_ALLOW_HEADERS);
572 }
573
574
575
576
577
578 public void setAccessControlAllowMethods(List<HttpMethod> allowedMethods) {
579 set(ACCESS_CONTROL_ALLOW_METHODS, StringUtil.join(allowedMethods, ','));
580 }
581
582
583
584
585
586 public List<HttpMethod> getAccessControlAllowMethods() {
587 List<HttpMethod> result = new ArrayList<HttpMethod>();
588 String value = getFirst(ACCESS_CONTROL_ALLOW_METHODS);
589 if (value != null) {
590 String[] tokens = value.split(",\\s*");
591 for (String token : tokens) {
592 result.add(HttpMethod.valueOf(token));
593 }
594 }
595 return result;
596 }
597
598
599
600
601
602 public void setAccessControlAllowOrigin(String allowedOrigin) {
603 set(ACCESS_CONTROL_ALLOW_ORIGIN, allowedOrigin);
604 }
605
606
607
608
609
610 public String getAccessControlAllowOrigin() {
611 return getFirst(ACCESS_CONTROL_ALLOW_ORIGIN);
612 }
613
614
615
616
617
618 public void setAccessControlExposeHeaders(List<String> exposedHeaders) {
619 set(ACCESS_CONTROL_EXPOSE_HEADERS,
620 toCommaDelimitedString(exposedHeaders));
621 }
622
623
624
625
626
627 public List<String> getAccessControlExposeHeaders() {
628 return getFirstValueAsList(ACCESS_CONTROL_EXPOSE_HEADERS);
629 }
630
631
632
633
634
635 public void setAccessControlMaxAge(long maxAge) {
636 set(ACCESS_CONTROL_MAX_AGE, Long.toString(maxAge));
637 }
638
639
640
641
642
643
644 public long getAccessControlMaxAge() {
645 String value = getFirst(ACCESS_CONTROL_MAX_AGE);
646 return (value != null ? Long.parseLong(value) : -1);
647 }
648
649
650
651
652
653 public void setAccessControlRequestHeaders(List<String> requestHeaders) {
654 set(ACCESS_CONTROL_REQUEST_HEADERS,
655 toCommaDelimitedString(requestHeaders));
656 }
657
658
659
660
661
662 public List<String> getAccessControlRequestHeaders() {
663 return getFirstValueAsList(ACCESS_CONTROL_REQUEST_HEADERS);
664 }
665
666
667
668
669
670 public void setAccessControlRequestMethod(HttpMethod requestedMethod) {
671 set(ACCESS_CONTROL_REQUEST_METHOD, requestedMethod.name());
672 }
673
674
675
676
677
678 public HttpMethod getAccessControlRequestMethod() {
679 String value = getFirst(ACCESS_CONTROL_REQUEST_METHOD);
680 return (value != null ? HttpMethod.valueOf(value) : null);
681 }
682
683
684
685
686
687 public void setAcceptCharset(List<Charset> acceptableCharsets) {
688 StringBuilder builder = new StringBuilder();
689 for (Iterator<Charset> iterator = acceptableCharsets.iterator(); iterator
690 .hasNext();) {
691 Charset charset = iterator.next();
692 builder.append(charset.name().toLowerCase(Locale.ENGLISH));
693 if (iterator.hasNext()) {
694 builder.append(", ");
695 }
696 }
697 set(ACCEPT_CHARSET, builder.toString());
698 }
699
700
701
702
703
704 public List<Charset> getAcceptCharset() {
705 List<Charset> result = new ArrayList<Charset>();
706 String value = getFirst(ACCEPT_CHARSET);
707 if (value != null) {
708 String[] tokens = value.split(",\\s*");
709 for (String token : tokens) {
710 int paramIdx = token.indexOf(';');
711 String charsetName;
712 if (paramIdx == -1) {
713 charsetName = token;
714 } else {
715 charsetName = token.substring(0, paramIdx);
716 }
717 if (!charsetName.equals("*")) {
718 result.add(Charset.forName(charsetName));
719 }
720 }
721 }
722 return result;
723 }
724
725
726
727
728
729 public void setAllow(Set<HttpMethod> allowedMethods) {
730 set(ALLOW, StringUtil.join(allowedMethods, ','));
731 }
732
733
734
735
736
737
738
739 public Set<HttpMethod> getAllow() {
740 String value = getFirst(ALLOW);
741 if (StringUtil.isNotBlank(value)) {
742 List<HttpMethod> allowedMethod = new ArrayList<HttpMethod>(5);
743 String[] tokens = value.split(",\\s*");
744 for (String token : tokens) {
745 allowedMethod.add(HttpMethod.valueOf(token));
746 }
747 return EnumSet.copyOf(allowedMethod);
748 } else {
749 return EnumSet.noneOf(HttpMethod.class);
750 }
751 }
752
753
754
755
756 public void setCacheControl(String cacheControl) {
757 set(CACHE_CONTROL, cacheControl);
758 }
759
760
761
762
763 public String getCacheControl() {
764 return getFirst(CACHE_CONTROL);
765 }
766
767
768
769
770 public void setConnection(String connection) {
771 set(CONNECTION, connection);
772 }
773
774
775
776
777 public void setConnection(List<String> connection) {
778 set(CONNECTION, toCommaDelimitedString(connection));
779 }
780
781
782
783
784 public List<String> getConnection() {
785 return getFirstValueAsList(CONNECTION);
786 }
787
788
789
790
791
792
793
794
795
796
797 public void setContentDispositionFormData(String name, String filename) {
798 StringBuilder builder = new StringBuilder("form-data; name=\"");
799 builder.append(name).append('\"');
800 if (filename != null) {
801 builder.append("; filename=\"");
802 builder.append(filename).append('\"');
803 }
804 set(CONTENT_DISPOSITION, builder.toString());
805 }
806
807
808
809
810
811 public void setContentLength(long contentLength) {
812 set(CONTENT_LENGTH, Long.toString(contentLength));
813 }
814
815
816
817
818
819
820
821 public long getContentLength() {
822 String value = getFirst(CONTENT_LENGTH);
823 return (value != null ? Long.parseLong(value) : -1);
824 }
825
826
827
828
829
830 public void setContentType(ContentType contentType) {
831 set(CONTENT_TYPE, contentType.toString());
832 }
833
834
835
836
837
838
839
840 public String getContentType() {
841 return getFirst(CONTENT_TYPE);
842 }
843
844
845
846
847
848
849
850
851 public void setDate(long date) {
852 setDate(DATE, date);
853 }
854
855
856
857
858
859
860
861
862
863
864
865 public long getDate() {
866 return getFirstDate(DATE);
867 }
868
869
870
871
872
873 public void setETag(String eTag) {
874 set(ETAG, eTag);
875 }
876
877
878
879
880
881 public String getETag() {
882 return getFirst(ETAG);
883 }
884
885
886
887
888
889
890
891
892 public void setExpires(long expires) {
893 setDate(EXPIRES, expires);
894 }
895
896
897
898
899
900
901
902
903 public long getExpires() {
904 try {
905 return getFirstDate(EXPIRES);
906 } catch (IllegalArgumentException ex) {
907 return -1;
908 }
909 }
910
911
912
913
914
915
916
917 public void setIfModifiedSince(long ifModifiedSince) {
918 setDate(IF_MODIFIED_SINCE, ifModifiedSince);
919 }
920
921
922
923
924
925
926
927 public long getIfModifiedSince() {
928 return getFirstDate(IF_MODIFIED_SINCE);
929 }
930
931
932
933
934 public void setIfNoneMatch(String ifNoneMatch) {
935 set(IF_NONE_MATCH, ifNoneMatch);
936 }
937
938
939
940
941 public void setIfNoneMatch(List<String> ifNoneMatchList) {
942 set(IF_NONE_MATCH, toCommaDelimitedString(ifNoneMatchList));
943 }
944
945 protected String toCommaDelimitedString(List<String> list) {
946 StringBuilder builder = new StringBuilder();
947 for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
948 String ifNoneMatch = iterator.next();
949 builder.append(ifNoneMatch);
950 if (iterator.hasNext()) {
951 builder.append(", ");
952 }
953 }
954 return builder.toString();
955 }
956
957
958
959
960 public List<String> getIfNoneMatch() {
961 return getFirstValueAsList(IF_NONE_MATCH);
962 }
963
964 protected List<String> getFirstValueAsList(String header) {
965 List<String> result = new ArrayList<String>();
966 String value = getFirst(header);
967 if (value != null) {
968 String[] tokens = value.split(",\\s*");
969 for (String token : tokens) {
970 result.add(token);
971 }
972 }
973 return result;
974 }
975
976
977
978
979
980
981
982
983 public void setLastModified(long lastModified) {
984 setDate(LAST_MODIFIED, lastModified);
985 }
986
987
988
989
990
991
992
993
994 public long getLastModified() {
995 return getFirstDate(LAST_MODIFIED);
996 }
997
998
999
1000
1001
1002 public void setLocation(URI location) {
1003 set(LOCATION, location.toASCIIString());
1004 }
1005
1006
1007
1008
1009
1010
1011
1012 public URI getLocation() {
1013 String value = getFirst(LOCATION);
1014 return (value != null ? URI.create(value) : null);
1015 }
1016
1017
1018
1019
1020 public void setOrigin(String origin) {
1021 set(ORIGIN, origin);
1022 }
1023
1024
1025
1026
1027 public String getOrigin() {
1028 return getFirst(ORIGIN);
1029 }
1030
1031
1032
1033
1034 public void setPragma(String pragma) {
1035 set(PRAGMA, pragma);
1036 }
1037
1038
1039
1040
1041 public String getPragma() {
1042 return getFirst(PRAGMA);
1043 }
1044
1045
1046
1047
1048 public void setRange(String range) {
1049 set(RANGE, range);
1050 }
1051
1052
1053
1054
1055
1056
1057 public String getRange() {
1058 return getFirst(RANGE);
1059 }
1060
1061
1062
1063
1064 public void setUpgrade(String upgrade) {
1065 set(UPGRADE, upgrade);
1066 }
1067
1068
1069
1070
1071 public String getUpgrade() {
1072 return getFirst(UPGRADE);
1073 }
1074
1075
1076
1077
1078
1079
1080 public long getFirstDate(String headerName) {
1081 String headerValue = getFirst(headerName);
1082 if (headerValue == null) {
1083 return -1;
1084 }
1085 for (String dateFormat : DATE_FORMATS) {
1086 SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
1087 dateFormat, Locale.US);
1088 simpleDateFormat.setTimeZone(GMT);
1089 try {
1090 return simpleDateFormat.parse(headerValue).getTime();
1091 } catch (ParseException ex) {
1092
1093 }
1094 }
1095 throw new IllegalArgumentException("Cannot parse date value \""
1096 + headerValue + "\" for \"" + headerName + "\" header");
1097 }
1098
1099
1100
1101
1102
1103
1104 public void setDate(String headerName, long date) {
1105 SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMATS[0],
1106 Locale.US);
1107 dateFormat.setTimeZone(GMT);
1108 set(headerName, dateFormat.format(new Date(date)));
1109 }
1110
1111
1112
1113
1114
1115
1116
1117
1118 @Override
1119 public String getFirst(String headerName) {
1120 List<String> headerValues = this.headers.get(headerName);
1121 return (headerValues != null ? headerValues.get(0) : null);
1122 }
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136 @Override
1137 public void add(String headerName, String headerValue) {
1138 List<String> headerValues = this.headers.get(headerName);
1139 if (headerValues == null) {
1140 headerValues = new LinkedList<String>();
1141 this.headers.put(headerName, headerValues);
1142 }
1143 headerValues.add(headerValue);
1144 }
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158 @Override
1159 public void set(String headerName, String headerValue) {
1160 List<String> headerValues = new LinkedList<String>();
1161 headerValues.add(headerValue);
1162 this.headers.put(headerName, headerValues);
1163 }
1164
1165 @Override
1166 public void setAll(Map<String, String> values) {
1167 for (Entry<String, String> entry : values.entrySet()) {
1168 set(entry.getKey(), entry.getValue());
1169 }
1170 }
1171
1172 @Override
1173 public Map<String, String> toSingleValueMap() {
1174 LinkedHashMap<String, String> singleValueMap = new LinkedHashMap<String, String>(
1175 this.headers.size());
1176 for (Entry<String, List<String>> entry : this.headers.entrySet()) {
1177 singleValueMap.put(entry.getKey(), entry.getValue().get(0));
1178 }
1179 return singleValueMap;
1180 }
1181
1182
1183
1184 @Override
1185 public int size() {
1186 return this.headers.size();
1187 }
1188
1189 @Override
1190 public boolean isEmpty() {
1191 return this.headers.isEmpty();
1192 }
1193
1194 @Override
1195 public boolean containsKey(Object key) {
1196 return this.headers.containsKey(key);
1197 }
1198
1199 @Override
1200 public boolean containsValue(Object value) {
1201 return this.headers.containsValue(value);
1202 }
1203
1204 @Override
1205 public List<String> get(Object key) {
1206 return this.headers.get(key);
1207 }
1208
1209 @Override
1210 public List<String> put(String key, List<String> value) {
1211 return this.headers.put(key, value);
1212 }
1213
1214 @Override
1215 public List<String> remove(Object key) {
1216 return this.headers.remove(key);
1217 }
1218
1219 @Override
1220 public void putAll(Map<? extends String, ? extends List<String>> map) {
1221 this.headers.putAll(map);
1222 }
1223
1224 @Override
1225 public void clear() {
1226 this.headers.clear();
1227 }
1228
1229 @Override
1230 public Set<String> keySet() {
1231 return this.headers.keySet();
1232 }
1233
1234 @Override
1235 public Collection<List<String>> values() {
1236 return this.headers.values();
1237 }
1238
1239 @Override
1240 public Set<Entry<String, List<String>>> entrySet() {
1241 return this.headers.entrySet();
1242 }
1243
1244 @Override
1245 public boolean equals(Object other) {
1246 if (this == other) {
1247 return true;
1248 }
1249 if (!(other instanceof HttpHeaders)) {
1250 return false;
1251 }
1252 HttpHeaders otherHeaders = (HttpHeaders) other;
1253 return this.headers.equals(otherHeaders.headers);
1254 }
1255
1256 @Override
1257 public int hashCode() {
1258 return this.headers.hashCode();
1259 }
1260
1261 @Override
1262 public String toString() {
1263 return this.headers.toString();
1264 }
1265
1266
1267
1268
1269
1270 public static HttpHeaders readOnlyHttpHeaders(HttpHeaders headers) {
1271 return new HttpHeaders(headers, true);
1272 }
1273 }