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.core5.http.impl;
29
30 import java.util.Iterator;
31
32 import org.apache.hc.core5.annotation.Contract;
33 import org.apache.hc.core5.annotation.ThreadingBehavior;
34 import org.apache.hc.core5.http.ConnectionReuseStrategy;
35 import org.apache.hc.core5.http.Header;
36 import org.apache.hc.core5.http.HeaderElements;
37 import org.apache.hc.core5.http.HttpHeaders;
38 import org.apache.hc.core5.http.HttpRequest;
39 import org.apache.hc.core5.http.HttpResponse;
40 import org.apache.hc.core5.http.HttpStatus;
41 import org.apache.hc.core5.http.HttpVersion;
42 import org.apache.hc.core5.http.ProtocolVersion;
43 import org.apache.hc.core5.http.message.BasicTokenIterator;
44 import org.apache.hc.core5.http.message.MessageSupport;
45 import org.apache.hc.core5.http.protocol.HttpContext;
46 import org.apache.hc.core5.util.Args;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 @Contract(threading = ThreadingBehavior.IMMUTABLE)
69 public class DefaultConnectionReuseStrategy implements ConnectionReuseStrategy {
70
71 public static final DefaultConnectionReuseStrategy INSTANCE = new DefaultConnectionReuseStrategy();
72
73 public DefaultConnectionReuseStrategy() {
74 super();
75 }
76
77
78 @Override
79 public boolean keepAlive(
80 final HttpRequest request, final HttpResponse response, final HttpContext context) {
81 Args.notNull(response, "HTTP response");
82
83 if (request != null) {
84
85 if (request.containsHeader(HttpHeaders.CONTENT_LENGTH) && request.containsHeader(HttpHeaders.TRANSFER_ENCODING)) {
86 return false;
87 }
88 final Iterator<String> it = MessageSupport.iterateTokens(request, HttpHeaders.CONNECTION);
89 while (it.hasNext()) {
90 final String token = it.next();
91 if (HeaderElements.CLOSE.equalsIgnoreCase(token)) {
92 return false;
93 }
94 }
95 }
96
97
98
99 final Header teh = response.getFirstHeader(HttpHeaders.TRANSFER_ENCODING);
100 if (teh == null
101 && MessageSupport.canResponseHaveBody(request != null ? request.getMethod() : null, response)
102 && response.countHeaders(HttpHeaders.CONTENT_LENGTH) != 1) {
103 return false;
104 }
105
106 final ProtocolVersion ver = response.getVersion() != null ? response.getVersion() : context.getProtocolVersion();
107
108 if (ver.lessEquals(HttpVersion.HTTP_1_0) && teh != null) {
109 return false;
110 }
111
112
113
114
115 if (response.getCode() == HttpStatus.SC_NO_CONTENT) {
116 final Header clh = response.getFirstHeader(HttpHeaders.CONTENT_LENGTH);
117 if (clh != null) {
118 try {
119 final long contentLen = Long.parseLong(clh.getValue());
120 if (contentLen > 0) {
121 return false;
122 }
123 } catch (final NumberFormatException ex) {
124
125 }
126 }
127 if (response.containsHeader(HttpHeaders.TRANSFER_ENCODING)) {
128 return false;
129 }
130 }
131
132
133
134
135 Iterator<Header> headerIterator = response.headerIterator(HttpHeaders.CONNECTION);
136 if (!headerIterator.hasNext()) {
137 headerIterator = response.headerIterator("Proxy-Connection");
138 }
139
140 if (headerIterator.hasNext()) {
141 if (ver.greaterEquals(HttpVersion.HTTP_1_1)) {
142 final Iterator<String> it = new BasicTokenIterator(headerIterator);
143 while (it.hasNext()) {
144 final String token = it.next();
145 if (HeaderElements.CLOSE.equalsIgnoreCase(token)) {
146 return false;
147 }
148 }
149 return true;
150 }
151 final Iterator<String> it = new BasicTokenIterator(headerIterator);
152 while (it.hasNext()) {
153 final String token = it.next();
154 if (HeaderElements.KEEP_ALIVE.equalsIgnoreCase(token)) {
155 return true;
156 }
157 }
158 return false;
159 }
160 return ver.greaterEquals(HttpVersion.HTTP_1_1);
161 }
162
163 }