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.ArrayList;
32 import java.util.Date;
33 import java.util.List;
34
35 import org.apache.hc.client5.http.RouteInfo;
36 import org.apache.hc.client5.http.cookie.StandardCookieSpec;
37 import org.apache.hc.client5.http.config.RequestConfig;
38 import org.apache.hc.client5.http.cookie.Cookie;
39 import org.apache.hc.client5.http.cookie.CookieOrigin;
40 import org.apache.hc.client5.http.cookie.CookieSpec;
41 import org.apache.hc.client5.http.cookie.CookieSpecFactory;
42 import org.apache.hc.client5.http.cookie.CookieStore;
43 import org.apache.hc.core5.annotation.Contract;
44 import org.apache.hc.core5.annotation.ThreadingBehavior;
45 import org.apache.hc.core5.http.EntityDetails;
46 import org.apache.hc.core5.http.Header;
47 import org.apache.hc.core5.http.HttpException;
48 import org.apache.hc.core5.http.HttpRequest;
49 import org.apache.hc.core5.http.HttpRequestInterceptor;
50 import org.apache.hc.core5.http.Method;
51 import org.apache.hc.core5.http.config.Lookup;
52 import org.apache.hc.core5.http.protocol.HttpContext;
53 import org.apache.hc.core5.net.URIAuthority;
54 import org.apache.hc.core5.util.Args;
55 import org.apache.hc.core5.util.TextUtils;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59
60
61
62
63
64
65
66 @Contract(threading = ThreadingBehavior.STATELESS)
67 public class RequestAddCookies implements HttpRequestInterceptor {
68
69 private static final Logger LOG = LoggerFactory.getLogger(RequestAddCookies.class);
70
71 public RequestAddCookies() {
72 super();
73 }
74
75 @Override
76 public void process(final HttpRequest request, final EntityDetails entity, final HttpContext context)
77 throws HttpException, IOException {
78 Args.notNull(request, "HTTP request");
79 Args.notNull(context, "HTTP context");
80
81 final String method = request.getMethod();
82 if (Method.CONNECT.isSame(method) || Method.TRACE.isSame(method)) {
83 return;
84 }
85
86 final HttpClientContext clientContext = HttpClientContext.adapt(context);
87 final String exchangeId = clientContext.getExchangeId();
88
89
90 final CookieStore cookieStore = clientContext.getCookieStore();
91 if (cookieStore == null) {
92 if (LOG.isDebugEnabled()) {
93 LOG.debug("{} Cookie store not specified in HTTP context", exchangeId);
94 }
95 return;
96 }
97
98
99 final Lookup<CookieSpecFactory> registry = clientContext.getCookieSpecRegistry();
100 if (registry == null) {
101 if (LOG.isDebugEnabled()) {
102 LOG.debug("{} CookieSpec registry not specified in HTTP context", exchangeId);
103 }
104 return;
105 }
106
107
108 final RouteInfo route = clientContext.getHttpRoute();
109 if (route == null) {
110 if (LOG.isDebugEnabled()) {
111 LOG.debug("{} Connection route not set in the context", exchangeId);
112 }
113 return;
114 }
115
116 final RequestConfig config = clientContext.getRequestConfig();
117 String cookieSpecName = config.getCookieSpec();
118 if (cookieSpecName == null) {
119 cookieSpecName = StandardCookieSpec.STRICT;
120 }
121 if (LOG.isDebugEnabled()) {
122 LOG.debug("{} Cookie spec selected: {}", exchangeId, cookieSpecName);
123 }
124
125 final URIAuthority authority = request.getAuthority();
126 String path = request.getPath();
127 if (TextUtils.isEmpty(path)) {
128 path = "/";
129 }
130 String hostName = authority != null ? authority.getHostName() : null;
131 if (hostName == null) {
132 hostName = route.getTargetHost().getHostName();
133 }
134 int port = authority != null ? authority.getPort() : -1;
135 if (port < 0) {
136 port = route.getTargetHost().getPort();
137 }
138 final CookieOriginCookieOrigin.html#CookieOrigin">CookieOrigin cookieOrigin = new CookieOrigin(hostName, port, path, route.isSecure());
139
140
141 final CookieSpecFactory factory = registry.lookup(cookieSpecName);
142 if (factory == null) {
143 if (LOG.isDebugEnabled()) {
144 LOG.debug("{} Unsupported cookie spec: {}", exchangeId, cookieSpecName);
145 }
146 return;
147 }
148 final CookieSpec cookieSpec = factory.create(clientContext);
149
150 final List<Cookie> cookies = cookieStore.getCookies();
151
152 final List<Cookie> matchedCookies = new ArrayList<>();
153 final Date now = new Date();
154 boolean expired = false;
155 for (final Cookie cookie : cookies) {
156 if (!cookie.isExpired(now)) {
157 if (cookieSpec.match(cookie, cookieOrigin)) {
158 if (LOG.isDebugEnabled()) {
159 LOG.debug("{} Cookie {} match {}", exchangeId, cookie, cookieOrigin);
160 }
161 matchedCookies.add(cookie);
162 }
163 } else {
164 if (LOG.isDebugEnabled()) {
165 LOG.debug("{} Cookie {} expired", exchangeId, cookie);
166 }
167 expired = true;
168 }
169 }
170
171
172
173 if (expired) {
174 cookieStore.clearExpired(now);
175 }
176
177 if (!matchedCookies.isEmpty()) {
178 final List<Header> headers = cookieSpec.formatCookies(matchedCookies);
179 for (final Header header : headers) {
180 request.addHeader(header);
181 }
182 }
183
184
185
186 context.setAttribute(HttpClientContext.COOKIE_SPEC, cookieSpec);
187 context.setAttribute(HttpClientContext.COOKIE_ORIGIN, cookieOrigin);
188 }
189
190 }