mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8328286: Enhance HTTP client
Reviewed-by: aefimov, michaelm
This commit is contained in:
parent
893e7bc894
commit
03bc6b359f
29 changed files with 1126 additions and 185 deletions
|
@ -253,6 +253,15 @@ to determine the proxy that should be used for connecting to a given URI.</P>
|
|||
</OL>
|
||||
<P>The channel binding tokens generated are of the type "tls-server-end-point" as defined in
|
||||
RFC 5929.</P>
|
||||
|
||||
<LI><P><B>{@systemProperty jdk.http.maxHeaderSize}</B> (default: 393216 or 384kB)<BR>
|
||||
This is the maximum header field section size that a client is prepared to accept.
|
||||
This is computed as the sum of the size of the uncompressed header name, plus
|
||||
the size of the uncompressed header value, plus an overhead of 32 bytes for
|
||||
each field section line. If a peer sends a field section that exceeds this
|
||||
size a {@link java.net.ProtocolException ProtocolException} will be raised.
|
||||
This applies to all versions of the HTTP protocol. A value of zero or a negative
|
||||
value means no limit. If left unspecified, the default value is 393216 bytes.
|
||||
</UL>
|
||||
<P>All these properties are checked only once at startup.</P>
|
||||
<a id="AddressCache"></a>
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
package sun.net.www;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Array;
|
||||
import java.net.ProtocolException;
|
||||
import java.util.Collections;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -45,11 +47,32 @@ public final class MessageHeader {
|
|||
private String[] values;
|
||||
private int nkeys;
|
||||
|
||||
// max number of bytes for headers, <=0 means unlimited;
|
||||
// this corresponds to the length of the names, plus the length
|
||||
// of the values, plus an overhead of 32 bytes per name: value
|
||||
// pair.
|
||||
// Note: we use the same definition as HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE
|
||||
// see RFC 9113, section 6.5.2.
|
||||
// https://www.rfc-editor.org/rfc/rfc9113.html#SETTINGS_MAX_HEADER_LIST_SIZE
|
||||
private final int maxHeaderSize;
|
||||
|
||||
// Aggregate size of the field lines (name + value + 32) x N
|
||||
// that have been parsed and accepted so far.
|
||||
// This is defined as a long to force promotion to long
|
||||
// and avoid overflows; see checkNewSize;
|
||||
private long size;
|
||||
|
||||
public MessageHeader () {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public MessageHeader (int maxHeaderSize) {
|
||||
this.maxHeaderSize = maxHeaderSize;
|
||||
grow();
|
||||
}
|
||||
|
||||
public MessageHeader (InputStream is) throws java.io.IOException {
|
||||
maxHeaderSize = 0;
|
||||
parseHeader(is);
|
||||
}
|
||||
|
||||
|
@ -476,10 +499,28 @@ public final class MessageHeader {
|
|||
public void parseHeader(InputStream is) throws java.io.IOException {
|
||||
synchronized (this) {
|
||||
nkeys = 0;
|
||||
size = 0;
|
||||
}
|
||||
mergeHeader(is);
|
||||
}
|
||||
|
||||
private void checkMaxHeaderSize(int sz) throws ProtocolException {
|
||||
if (maxHeaderSize > 0) checkNewSize(size, sz, 0);
|
||||
}
|
||||
|
||||
private long checkNewSize(long size, int name, int value) throws ProtocolException {
|
||||
// See SETTINGS_MAX_HEADER_LIST_SIZE, RFC 9113, section 6.5.2.
|
||||
long newSize = size + name + value + 32;
|
||||
if (maxHeaderSize > 0 && newSize > maxHeaderSize) {
|
||||
Arrays.fill(keys, 0, nkeys, null);
|
||||
Arrays.fill(values,0, nkeys, null);
|
||||
nkeys = 0;
|
||||
throw new ProtocolException(String.format("Header size too big: %s > %s",
|
||||
newSize, maxHeaderSize));
|
||||
}
|
||||
return newSize;
|
||||
}
|
||||
|
||||
/** Parse and merge a MIME header from an input stream. */
|
||||
@SuppressWarnings("fallthrough")
|
||||
public void mergeHeader(InputStream is) throws java.io.IOException {
|
||||
|
@ -493,7 +534,15 @@ public final class MessageHeader {
|
|||
int c;
|
||||
boolean inKey = firstc > ' ';
|
||||
s[len++] = (char) firstc;
|
||||
checkMaxHeaderSize(len);
|
||||
parseloop:{
|
||||
// We start parsing for a new name value pair here.
|
||||
// The max header size includes an overhead of 32 bytes per
|
||||
// name value pair.
|
||||
// See SETTINGS_MAX_HEADER_LIST_SIZE, RFC 9113, section 6.5.2.
|
||||
long maxRemaining = maxHeaderSize > 0
|
||||
? maxHeaderSize - size - 32
|
||||
: Long.MAX_VALUE;
|
||||
while ((c = is.read()) >= 0) {
|
||||
switch (c) {
|
||||
case ':':
|
||||
|
@ -527,6 +576,9 @@ public final class MessageHeader {
|
|||
s = ns;
|
||||
}
|
||||
s[len++] = (char) c;
|
||||
if (maxHeaderSize > 0 && len > maxRemaining) {
|
||||
checkMaxHeaderSize(len);
|
||||
}
|
||||
}
|
||||
firstc = -1;
|
||||
}
|
||||
|
@ -548,6 +600,9 @@ public final class MessageHeader {
|
|||
v = new String();
|
||||
else
|
||||
v = String.copyValueOf(s, keyend, len - keyend);
|
||||
int klen = k == null ? 0 : k.length();
|
||||
|
||||
size = checkNewSize(size, klen, v.length());
|
||||
add(k, v);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -172,6 +172,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
*/
|
||||
private static final int bufSize4ES;
|
||||
|
||||
private static final int maxHeaderSize;
|
||||
|
||||
/*
|
||||
* Restrict setting of request headers through the public api
|
||||
* consistent with JavaScript XMLHttpRequest2 with a few
|
||||
|
@ -288,6 +290,19 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
} else {
|
||||
restrictedHeaderSet = null;
|
||||
}
|
||||
|
||||
int defMaxHeaderSize = 384 * 1024;
|
||||
String maxHeaderSizeStr = getNetProperty("jdk.http.maxHeaderSize");
|
||||
int maxHeaderSizeVal = defMaxHeaderSize;
|
||||
if (maxHeaderSizeStr != null) {
|
||||
try {
|
||||
maxHeaderSizeVal = Integer.parseInt(maxHeaderSizeStr);
|
||||
} catch (NumberFormatException n) {
|
||||
maxHeaderSizeVal = defMaxHeaderSize;
|
||||
}
|
||||
}
|
||||
if (maxHeaderSizeVal < 0) maxHeaderSizeVal = 0;
|
||||
maxHeaderSize = maxHeaderSizeVal;
|
||||
}
|
||||
|
||||
static final String httpVersion = "HTTP/1.1";
|
||||
|
@ -754,7 +769,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
}
|
||||
ps = (PrintStream) http.getOutputStream();
|
||||
connected=true;
|
||||
responses = new MessageHeader();
|
||||
responses = new MessageHeader(maxHeaderSize);
|
||||
setRequests=false;
|
||||
writeRequests();
|
||||
}
|
||||
|
@ -912,7 +927,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
throws IOException {
|
||||
super(checkURL(u));
|
||||
requests = new MessageHeader();
|
||||
responses = new MessageHeader();
|
||||
responses = new MessageHeader(maxHeaderSize);
|
||||
userHeaders = new MessageHeader();
|
||||
this.handler = handler;
|
||||
instProxy = p;
|
||||
|
@ -2810,7 +2825,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
}
|
||||
|
||||
// clear out old response headers!!!!
|
||||
responses = new MessageHeader();
|
||||
responses = new MessageHeader(maxHeaderSize);
|
||||
if (stat == HTTP_USE_PROXY) {
|
||||
/* This means we must re-request the resource through the
|
||||
* proxy denoted in the "Location:" field of the response.
|
||||
|
@ -3000,7 +3015,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
} catch (IOException e) { }
|
||||
}
|
||||
responseCode = -1;
|
||||
responses = new MessageHeader();
|
||||
responses = new MessageHeader(maxHeaderSize);
|
||||
connected = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,3 +130,20 @@ jdk.http.auth.tunneling.disabledSchemes=Basic
|
|||
#jdk.http.ntlm.transparentAuth=trustedHosts
|
||||
#
|
||||
jdk.http.ntlm.transparentAuth=disabled
|
||||
|
||||
#
|
||||
# Maximum HTTP field section size that a client is prepared to accept
|
||||
#
|
||||
# jdk.http.maxHeaderSize=393216
|
||||
#
|
||||
# This is the maximum header field section size that a client is prepared to accept.
|
||||
# This is computed as the sum of the size of the uncompressed header name, plus
|
||||
# the size of the uncompressed header value, plus an overhead of 32 bytes for
|
||||
# each field section line. If a peer sends a field section that exceeds this
|
||||
# size a {@link java.net.ProtocolException ProtocolException} will be raised.
|
||||
# This applies to all versions of the HTTP protocol. A value of zero or a negative
|
||||
# value means no limit. If left unspecified, the default value is 393216 bytes
|
||||
# or 384kB.
|
||||
#
|
||||
# Note: This property is currently used by the JDK Reference implementation. It
|
||||
# is not guaranteed to be examined and used by other implementations.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue