1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.client5.http.protocol;
29
30 import java.io.IOException;
31 import java.util.Iterator;
32 import java.util.List;
33
34 import org.apache.hc.client5.http.cookie.Cookie;
35 import org.apache.hc.client5.http.cookie.CookieOrigin;
36 import org.apache.hc.client5.http.cookie.CookieSpec;
37 import org.apache.hc.client5.http.cookie.CookieStore;
38 import org.apache.hc.client5.http.cookie.MalformedCookieException;
39 import org.apache.hc.core5.annotation.Contract;
40 import org.apache.hc.core5.annotation.ThreadingBehavior;
41 import org.apache.hc.core5.http.EntityDetails;
42 import org.apache.hc.core5.http.Header;
43 import org.apache.hc.core5.http.HttpException;
44 import org.apache.hc.core5.http.HttpResponse;
45 import org.apache.hc.core5.http.HttpResponseInterceptor;
46 import org.apache.hc.core5.http.protocol.HttpContext;
47 import org.apache.hc.core5.util.Args;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51
52
53
54
55
56
57 @Contract(threading = ThreadingBehavior.STATELESS)
58 public class ResponseProcessCookies implements HttpResponseInterceptor {
59
60 private static final Logger LOG = LoggerFactory.getLogger(ResponseProcessCookies.class);
61
62 public ResponseProcessCookies() {
63 super();
64 }
65
66 @Override
67 public void process(final HttpResponse response, final EntityDetails entity, final HttpContext context)
68 throws HttpException, IOException {
69 Args.notNull(response, "HTTP request");
70 Args.notNull(context, "HTTP context");
71
72 final HttpClientContext clientContext = HttpClientContext.adapt(context);
73 final String exchangeId = clientContext.getExchangeId();
74
75
76 final CookieSpec cookieSpec = clientContext.getCookieSpec();
77 if (cookieSpec == null) {
78 if (LOG.isDebugEnabled()) {
79 LOG.debug("{} Cookie spec not specified in HTTP context", exchangeId);
80 }
81 return;
82 }
83
84 final CookieStore cookieStore = clientContext.getCookieStore();
85 if (cookieStore == null) {
86 if (LOG.isDebugEnabled()) {
87 LOG.debug("{} Cookie store not specified in HTTP context", exchangeId);
88 }
89 return;
90 }
91
92 final CookieOrigin cookieOrigin = clientContext.getCookieOrigin();
93 if (cookieOrigin == null) {
94 if (LOG.isDebugEnabled()) {
95 LOG.debug("{} Cookie origin not specified in HTTP context", exchangeId);
96 }
97 return;
98 }
99 final Iterator<Header> it = response.headerIterator("Set-Cookie");
100 processCookies(exchangeId, it, cookieSpec, cookieOrigin, cookieStore);
101 }
102
103 private void processCookies(
104 final String exchangeId,
105 final Iterator<Header> iterator,
106 final CookieSpec cookieSpec,
107 final CookieOrigin cookieOrigin,
108 final CookieStore cookieStore) {
109 while (iterator.hasNext()) {
110 final Header header = iterator.next();
111 try {
112 final List<Cookie> cookies = cookieSpec.parse(header, cookieOrigin);
113 for (final Cookie cookie : cookies) {
114 try {
115 cookieSpec.validate(cookie, cookieOrigin);
116 cookieStore.addCookie(cookie);
117
118 if (LOG.isDebugEnabled()) {
119 LOG.debug("{} Cookie accepted [{}]", exchangeId, formatCookie(cookie));
120 }
121 } catch (final MalformedCookieException ex) {
122 if (LOG.isWarnEnabled()) {
123 LOG.warn("{} Cookie rejected [{}] {}", exchangeId, formatCookie(cookie), ex.getMessage());
124 }
125 }
126 }
127 } catch (final MalformedCookieException ex) {
128 if (LOG.isWarnEnabled()) {
129 LOG.warn("{} Invalid cookie header: \"{}\". {}", exchangeId, header, ex.getMessage());
130 }
131 }
132 }
133 }
134
135 private static String formatCookie(final Cookie cookie) {
136 final StringBuilder buf = new StringBuilder();
137 buf.append(cookie.getName());
138 buf.append("=\"");
139 String v = cookie.getValue();
140 if (v != null) {
141 if (v.length() > 100) {
142 v = v.substring(0, 100) + "...";
143 }
144 buf.append(v);
145 }
146 buf.append("\"");
147 buf.append(", domain:");
148 buf.append(cookie.getDomain());
149 buf.append(", path:");
150 buf.append(cookie.getPath());
151 buf.append(", expiry:");
152 buf.append(cookie.getExpiryDate());
153 return buf.toString();
154 }
155
156 }