|
29 | 29 | import java.nio.file.Paths;
|
30 | 30 | import java.nio.file.StandardOpenOption;
|
31 | 31 | import java.util.Arrays;
|
| 32 | +import java.util.HashMap; |
32 | 33 | import java.util.Iterator;
|
33 | 34 | import java.util.List;
|
34 | 35 | import java.util.Map;
|
|
56 | 57 | import org.eclipse.jetty.http.HttpScheme;
|
57 | 58 | import org.eclipse.jetty.http.HttpStatus;
|
58 | 59 | import org.eclipse.jetty.http.HttpVersion;
|
| 60 | +import org.eclipse.jetty.io.ByteArrayEndPoint; |
59 | 61 | import org.eclipse.jetty.io.ClientConnector;
|
60 | 62 | import org.eclipse.jetty.io.Content;
|
61 | 63 | import org.eclipse.jetty.io.EndPoint;
|
|
76 | 78 | import org.eclipse.jetty.util.component.LifeCycle;
|
77 | 79 | import org.hamcrest.Matchers;
|
78 | 80 | import org.junit.jupiter.api.Assumptions;
|
| 81 | +import org.junit.jupiter.api.Test; |
79 | 82 | import org.junit.jupiter.api.extension.ExtendWith;
|
80 | 83 | import org.junit.jupiter.params.ParameterizedTest;
|
81 | 84 | import org.junit.jupiter.params.provider.ArgumentsSource;
|
@@ -2012,4 +2015,208 @@ public void perform()
|
2012 | 2015 | .send(this);
|
2013 | 2016 | }
|
2014 | 2017 | }
|
| 2018 | + |
| 2019 | + private static Random rnd = new Random(); |
| 2020 | + private static final String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; |
| 2021 | + |
| 2022 | + public static final int CHARS_LENGTH = CHARS.length(); |
| 2023 | + |
| 2024 | + protected static String getRandomString(int size) |
| 2025 | + { |
| 2026 | + StringBuilder sb = new StringBuilder(size); |
| 2027 | + while (sb.length() < size) |
| 2028 | + { // length of the random string. |
| 2029 | + int index = rnd.nextInt(CHARS_LENGTH); |
| 2030 | + sb.append(CHARS.charAt(index)); |
| 2031 | + } |
| 2032 | + return sb.toString(); |
| 2033 | + } |
| 2034 | + |
| 2035 | + @ParameterizedTest |
| 2036 | + @ArgumentsSource(ScenarioProvider.class) |
| 2037 | + public void testSmallHeadersSize(Scenario scenario) throws Exception |
| 2038 | + { |
| 2039 | + startClient(scenario); |
| 2040 | + ByteArrayEndPoint endPoint = new ByteArrayEndPoint(); |
| 2041 | + HttpDestination destination = new HttpDestination(client, new Origin("http", "localhost", 8080)); |
| 2042 | + destination.start(); |
| 2043 | + HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination, new Promise.Adapter<Connection>()); |
| 2044 | + Request request = client.newRequest(URI.create("http://localhost/")); |
| 2045 | + request.agent(getRandomString(888)); //More than the request buffer size, but less than the default max request headers size |
| 2046 | + final CountDownLatch headersLatch = new CountDownLatch(1); |
| 2047 | + final CountDownLatch successLatch = new CountDownLatch(1); |
| 2048 | + final CountDownLatch failureLatch = new CountDownLatch(1); |
| 2049 | + request.listener(new Request.Listener() |
| 2050 | + { |
| 2051 | + @Override |
| 2052 | + public void onHeaders(Request request) |
| 2053 | + { |
| 2054 | + headersLatch.countDown(); |
| 2055 | + } |
| 2056 | + |
| 2057 | + @Override |
| 2058 | + public void onSuccess(Request request) |
| 2059 | + { |
| 2060 | + successLatch.countDown(); |
| 2061 | + } |
| 2062 | + |
| 2063 | + @Override |
| 2064 | + public void onFailure(Request request, Throwable failure) |
| 2065 | + { |
| 2066 | + failureLatch.countDown(); |
| 2067 | + } |
| 2068 | + }); |
| 2069 | + connection.send(request, null); |
| 2070 | + |
| 2071 | + String requestString = endPoint.takeOutputString(); |
| 2072 | + assertTrue(requestString.startsWith("GET / HTTP/1.1\r\nAccept-Encoding: gzip\r\n")); |
| 2073 | + assertTrue(headersLatch.await(5, TimeUnit.SECONDS)); |
| 2074 | + assertTrue(successLatch.await(5, TimeUnit.SECONDS)); |
| 2075 | + } |
| 2076 | + |
| 2077 | + @ParameterizedTest |
| 2078 | + @ArgumentsSource(ScenarioProvider.class) |
| 2079 | + public void testMaxRequestHeadersSize(Scenario scenario) throws Exception |
| 2080 | + { |
| 2081 | + startClient(scenario); |
| 2082 | + byte[] buffer = new byte[32 * 1024]; |
| 2083 | + ByteArrayEndPoint endPoint = new ByteArrayEndPoint(buffer, buffer.length); |
| 2084 | + HttpDestination destination = new HttpDestination(client, new Origin("http", "localhost", 8080)); |
| 2085 | + destination.start(); |
| 2086 | + HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination, new Promise.Adapter<Connection>()); |
| 2087 | + Request request = client.newRequest(URI.create("http://localhost/")); |
| 2088 | + //More than the request buffer size, but less than the default max request headers size |
| 2089 | + |
| 2090 | + int desiredHeadersSize = 20 * 1024; |
| 2091 | + int currentHeadersSize = 0; |
| 2092 | + int i = 0; |
| 2093 | + while (currentHeadersSize < desiredHeadersSize) |
| 2094 | + { |
| 2095 | + final int index = i++; |
| 2096 | + final String headerValue = getRandomString(800); |
| 2097 | + final int headerSize = headerValue.length(); |
| 2098 | + currentHeadersSize += headerSize; |
| 2099 | + request.cookie(new HttpCookie() |
| 2100 | + { |
| 2101 | + @Override |
| 2102 | + public String getName() |
| 2103 | + { |
| 2104 | + return "large" + index; |
| 2105 | + } |
| 2106 | + |
| 2107 | + @Override |
| 2108 | + public String getValue() |
| 2109 | + { |
| 2110 | + return headerValue; |
| 2111 | + } |
| 2112 | + |
| 2113 | + @Override |
| 2114 | + public int getVersion() |
| 2115 | + { |
| 2116 | + return 0; |
| 2117 | + } |
| 2118 | + |
| 2119 | + @Override |
| 2120 | + public Map<String, String> getAttributes() |
| 2121 | + { |
| 2122 | + return new HashMap<>(); |
| 2123 | + } |
| 2124 | + }); |
| 2125 | + } |
| 2126 | + |
| 2127 | + final CountDownLatch headersLatch = new CountDownLatch(1); |
| 2128 | + final CountDownLatch successLatch = new CountDownLatch(1); |
| 2129 | + request.listener(new Request.Listener() |
| 2130 | + { |
| 2131 | + @Override |
| 2132 | + public void onHeaders(Request request) |
| 2133 | + { |
| 2134 | + headersLatch.countDown(); |
| 2135 | + } |
| 2136 | + |
| 2137 | + @Override |
| 2138 | + public void onSuccess(Request request) |
| 2139 | + { |
| 2140 | + successLatch.countDown(); |
| 2141 | + } |
| 2142 | + }); |
| 2143 | + connection.send(request, null); |
| 2144 | + |
| 2145 | + String requestString = endPoint.takeOutputString(); |
| 2146 | + assertTrue(requestString.startsWith("GET / HTTP/1.1\r\nAccept-Encoding: gzip\r\n")); |
| 2147 | + assertTrue(headersLatch.await(5, TimeUnit.SECONDS)); |
| 2148 | + assertTrue(successLatch.await(5, TimeUnit.SECONDS)); |
| 2149 | + } |
| 2150 | + |
| 2151 | + @ParameterizedTest |
| 2152 | + @ArgumentsSource(ScenarioProvider.class) |
| 2153 | + public void testMaxRequestHeadersSizeOverflow(Scenario scenario) throws Exception |
| 2154 | + { |
| 2155 | + startClient(scenario); |
| 2156 | + byte[] buffer = new byte[32 * 1024]; |
| 2157 | + ByteArrayEndPoint endPoint = new ByteArrayEndPoint(buffer, buffer.length); |
| 2158 | + HttpDestination destination = new HttpDestination(client, new Origin("http", "localhost", 8080)); |
| 2159 | + destination.start(); |
| 2160 | + HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination, new Promise.Adapter<Connection>()); |
| 2161 | + Request request = client.newRequest(URI.create("http://localhost/")); |
| 2162 | + //More than the request buffer size, but less than the default max request headers size |
| 2163 | + |
| 2164 | + int desiredHeadersSize = 35 * 1024; |
| 2165 | + int currentHeadersSize = 0; |
| 2166 | + int i = 0; |
| 2167 | + while (currentHeadersSize < desiredHeadersSize) |
| 2168 | + { |
| 2169 | + final int index = i++; |
| 2170 | + final String headerValue = getRandomString(800); |
| 2171 | + final int headerSize = headerValue.length(); |
| 2172 | + currentHeadersSize += headerSize; |
| 2173 | + request.cookie(new HttpCookie() |
| 2174 | + { |
| 2175 | + @Override |
| 2176 | + public String getName() |
| 2177 | + { |
| 2178 | + return "large" + index; |
| 2179 | + } |
| 2180 | + |
| 2181 | + @Override |
| 2182 | + public String getValue() |
| 2183 | + { |
| 2184 | + return headerValue; |
| 2185 | + } |
| 2186 | + |
| 2187 | + @Override |
| 2188 | + public int getVersion() |
| 2189 | + { |
| 2190 | + return 0; |
| 2191 | + } |
| 2192 | + |
| 2193 | + @Override |
| 2194 | + public Map<String, String> getAttributes() |
| 2195 | + { |
| 2196 | + return new HashMap<>(); |
| 2197 | + } |
| 2198 | + }); |
| 2199 | + } |
| 2200 | + |
| 2201 | + final CountDownLatch headersLatch = new CountDownLatch(1); |
| 2202 | + final CountDownLatch failureLatch = new CountDownLatch(1); |
| 2203 | + request.listener(new Request.Listener() |
| 2204 | + { |
| 2205 | + @Override |
| 2206 | + public void onHeaders(Request request) |
| 2207 | + { |
| 2208 | + headersLatch.countDown(); |
| 2209 | + } |
| 2210 | + |
| 2211 | + @Override |
| 2212 | + public void onFailure(Request request, Throwable failure) |
| 2213 | + { |
| 2214 | + failureLatch.countDown(); |
| 2215 | + } |
| 2216 | + }); |
| 2217 | + connection.send(request, null); |
| 2218 | + |
| 2219 | + assertTrue(headersLatch.await(5, TimeUnit.SECONDS)); |
| 2220 | + assertTrue(failureLatch.await(5, TimeUnit.SECONDS)); |
| 2221 | + } |
2015 | 2222 | }
|
0 commit comments