下面列出了 io.netty.handler.codec.http2.HttpConversionUtil.ExtensionHeaderNames #io.netty.handler.codec.http.DefaultHttpHeaders 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@BeforeMethod
public void setup() {
applicationMapping = mock(ApplicationMapping.class);
request = mock(FullHttpRequest.class);
response = mock(FullHttpResponse.class);
when(request.getMethod()).thenReturn(HttpMethod.GET);
when(request.getUri()).thenReturn("/test");
when(request.headers()).thenReturn(new DefaultHttpHeaders());
when(request.content()).thenReturn(mock(ByteBuf.class));
when(request.getProtocolVersion()).thenReturn(HttpVersion.HTTP_1_1);
when(response.getStatus()).thenReturn(HttpResponseStatus.PROCESSING);
application = mock(Application.class);
context = mock(MessageContext.class);
router = spy(new Router(applicationMapping));
doReturn(new ApplicationHandler()).when(router).getApplicationHandler(application);
when(application.getPath()).thenReturn(URI.create("/app"));
when(context.getRequest()).thenReturn(request);
when(context.getResponse()).thenReturn(response);
when(context.getApplication()).thenReturn(application);
when(context.getBaseUri()).thenReturn(URI.create("http://localhost:8080"));
when(applicationMapping.resolve(request)).thenReturn(application);
}
@Test
public void testBindUnknownSession() throws Exception {
EasyMock
.expect(sessionDao.readSession("test"))
.andThrow(new UnknownSessionException());
replay();
DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/client");
DefaultHttpHeaders.addHeader(request, "Cookie", "irisAuthToken=test;");
handler.channelRead(context, request);
// an authenticated Client should have been bound
ClientFactory factory = ServiceLocator.getInstance(ClientFactory.class);
Client client = factory.get(channel);
assertNotNull(client);
assertFalse(client.isAuthenticated());
assertEquals(null, client.getSessionId());
verify();
}
/**
* Tests multipart POST and verifies it via GET operations.
* @throws Exception
*/
@Test
public void multipartPostGetHeadUpdateDeleteUndeleteTest() throws Exception {
Account refAccount = ACCOUNT_SERVICE.createAndAddRandomAccount();
Container refContainer = refAccount.getContainerById(Container.DEFAULT_PUBLIC_CONTAINER_ID);
doPostGetHeadUpdateDeleteUndeleteTest(0, refAccount, refContainer, refAccount.getName(),
!refContainer.isCacheable(), refAccount.getName(), refContainer.getName(), true);
doPostGetHeadUpdateDeleteUndeleteTest(FRONTEND_CONFIG.chunkedGetResponseThresholdInBytes * 3, refAccount,
refContainer, refAccount.getName(), !refContainer.isCacheable(), refAccount.getName(), refContainer.getName(),
true);
// failure case
// size of content being POSTed is higher than what is allowed via multipart/form-data
long maxAllowedSizeBytes = new NettyConfig(FRONTEND_VERIFIABLE_PROPS).nettyMultipartPostMaxSizeBytes;
ByteBuffer content = ByteBuffer.wrap(TestUtils.getRandomBytes((int) maxAllowedSizeBytes + 1));
HttpHeaders headers = new DefaultHttpHeaders();
setAmbryHeadersForPut(headers, TTL_SECS, !refContainer.isCacheable(), refAccount.getName(),
"application/octet-stream", null, refAccount.getName(), refContainer.getName());
HttpRequest httpRequest = RestTestUtils.createRequest(HttpMethod.POST, "/", headers);
HttpPostRequestEncoder encoder = createEncoder(httpRequest, content, ByteBuffer.allocate(0));
ResponseParts responseParts = nettyClient.sendRequest(encoder.finalizeRequest(), encoder, null).get();
HttpResponse response = getHttpResponse(responseParts);
assertEquals("Unexpected response status", HttpResponseStatus.REQUEST_ENTITY_TOO_LARGE, response.status());
assertTrue("No Date header", response.headers().getTimeMillis(HttpHeaderNames.DATE, -1) != -1);
assertFalse("Channel should not be active", HttpUtil.isKeepAlive(response));
}
@Test
public void extractCookies_handles_cookie_values_leniently() {
// given
//these are cookie values seen in the wild...
Cookie cookie1 = new DefaultCookie(UUID.randomUUID().toString(), "2094%3Az%7C2021%3Ab");
Cookie cookie2 = new DefaultCookie(UUID.randomUUID().toString(), "geoloc=cc=US,rc=OR,tp=vhigh,tz=PST,la=45.4978,lo=-122.6937,bw=5000");
Cookie cookie3 = new DefaultCookie(UUID.randomUUID().toString(), "\"dm=n.com&si=27431295-a282-4745-8cd5-542e7fce" +
"429e&ss=1477551008358&sl=76&tt=437632&obo=12&sh=1477552753923%3D76%3A12%3A437632%2C1477552698670%3D75%3" +
"A12%3A429879%2C1477552677137%3D74%3A12%3A426596%2C1477552672564%3D73%3A12%3A425585%2C1477552669893%3D72" +
"%3A12%3A423456&bcn=%2F%2F3408178b.mpstat.us%2F&ld=1477552753923&r=http%3A%2F%2Fwww.nike.com%2Fbe%2Fde_de%" +
"2F&ul=1477552756811\"");
HttpHeaders headers = new DefaultHttpHeaders().add(HttpHeaders.Names.COOKIE, ClientCookieEncoder.LAX.encode(cookie1, cookie2, cookie3));
HttpRequest nettyRequestMock = mock(HttpRequest.class);
doReturn(headers).when(nettyRequestMock).headers();
// when
Set<Cookie> extractedCookies = HttpUtils.extractCookies(nettyRequestMock);
// then
assertThat(extractedCookies.contains(cookie1), is(true));
assertThat(extractedCookies.contains(cookie2), is(true));
assertThat(extractedCookies.contains(cookie3), is(true));
}
@Test
void outboundCookiesMustBeMergedForHttp1() {
final HttpHeaders in = HttpHeaders.builder()
.add(HttpHeaderNames.COOKIE, "a=b; c=d")
.add(HttpHeaderNames.COOKIE, "e=f;g=h")
.addObject(HttpHeaderNames.CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8)
.add(HttpHeaderNames.COOKIE, "i=j")
.add(HttpHeaderNames.COOKIE, "k=l;")
.build();
final io.netty.handler.codec.http.HttpHeaders out =
new DefaultHttpHeaders();
toNettyHttp1ClientHeader(in, out);
assertThat(out.getAll(HttpHeaderNames.COOKIE))
.containsExactly("a=b; c=d; e=f; g=h; i=j; k=l");
}
private static void testUpgrade(Http2ConnectionHandler handler) {
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.OPTIONS, "*");
request.headers().set(HttpHeaderNames.HOST, "netty.io");
request.headers().set(HttpHeaderNames.CONNECTION, "Upgrade, HTTP2-Settings");
request.headers().set(HttpHeaderNames.UPGRADE, "h2c");
request.headers().set("HTTP2-Settings", "AAMAAABkAAQAAP__");
EmbeddedChannel channel = new EmbeddedChannel(new ChannelInboundHandlerAdapter());
ChannelHandlerContext ctx = channel.pipeline().firstContext();
Http2ServerUpgradeCodec codec = new Http2ServerUpgradeCodec("connectionHandler", handler);
assertTrue(codec.prepareUpgradeResponse(ctx, request, new DefaultHttpHeaders()));
codec.upgradeTo(ctx, request);
// Flush the channel to ensure we write out all buffered data
channel.flush();
assertSame(handler, channel.pipeline().remove("connectionHandler"));
assertNull(channel.pipeline().get(handler.getClass()));
assertTrue(channel.finish());
// Check that the preface was send (a.k.a the settings frame)
ByteBuf settingsBuffer = channel.readOutbound();
assertNotNull(settingsBuffer);
settingsBuffer.release();
assertNull(channel.readOutbound());
}
/**
* Asks the server to write more data than the set Content-Length and checks behavior.
* @param chunkCount the number of chunks of {@link MockNettyMessageProcessor#CHUNK} to use to set Content-Length.
* @throws Exception
*/
private void doWriteMoreThanContentLengthTest(int chunkCount) throws Exception {
EmbeddedChannel channel = createEmbeddedChannel();
MockNettyMessageProcessor processor = channel.pipeline().get(MockNettyMessageProcessor.class);
HttpHeaders httpHeaders = new DefaultHttpHeaders();
httpHeaders.set(MockNettyMessageProcessor.CHUNK_COUNT_HEADER_NAME, chunkCount);
HttpRequest httpRequest =
RestTestUtils.createRequest(HttpMethod.POST, TestingUri.WriteMoreThanContentLength.toString(), httpHeaders);
HttpUtil.setKeepAlive(httpRequest, true);
channel.writeInbound(httpRequest);
try {
verifyCallbacks(processor);
fail("One of the callbacks should have failed because the data written was more than Content-Length");
} catch (IllegalStateException e) {
// expected. Nothing to do.
}
// It doesn't matter what the response is - because it may either fail or succeed depending on certain race
// conditions. What matters is that the programming error is caught appropriately by NettyResponseChannel and it
// makes a callback with the right exception.
while (channel.readOutbound() != null) {
}
channel.close();
}
@Override
public void beforeRequest(Channel clientChannel, HttpRequest httpRequest, HttpProxyInterceptPipeline pipeline) throws Exception {
String acceptValue = httpRequest.headers().get(HttpHeaderNames.ACCEPT);
if (acceptValue != null && acceptValue.contains("application/x-sniff-cookie")) {
HttpResponse httpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, new DefaultHttpHeaders());
httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, 0);
//https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
AsciiString customHeadKey = AsciiString.cached("X-Sniff-Cookie");
String cookie = pipeline.getHttpRequest().headers().get(HttpHeaderNames.COOKIE);
httpResponse.headers().set(customHeadKey, cookie == null ? "" : cookie);
httpResponse.headers().set(HttpHeaderNames.ACCESS_CONTROL_EXPOSE_HEADERS, customHeadKey);
String origin = httpRequest.headers().get(HttpHeaderNames.ORIGIN);
if (StringUtil.isNullOrEmpty(origin)) {
String referer = httpRequest.headers().get(HttpHeaderNames.REFERER);
URL url = new URL(referer);
origin = url.getHost();
}
httpResponse.headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
httpResponse.headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_CREDENTIALS, true);
clientChannel.writeAndFlush(httpResponse);
clientChannel.writeAndFlush(new DefaultLastHttpContent());
clientChannel.close();
} else {
super.beforeRequest(clientChannel, httpRequest, pipeline);
}
}
/**
* Call the {@code GET /accounts} API and deserialize the response.
* @param accountName if non-null, fetch a single account by name instead of all accounts.
* @param accountId if non-null, fetch a single account by ID instead of all accounts.
* @return the accounts fetched.
*/
private Set<Account> getAccounts(String accountName, Short accountId) throws Exception {
HttpHeaders headers = new DefaultHttpHeaders();
if (accountName != null) {
headers.add(RestUtils.Headers.TARGET_ACCOUNT_NAME, accountName);
} else if (accountId != null) {
headers.add(RestUtils.Headers.TARGET_ACCOUNT_ID, accountId);
}
FullHttpRequest request = buildRequest(HttpMethod.GET, Operations.ACCOUNTS, headers, null);
ResponseParts responseParts = nettyClient.sendRequest(request, null, null).get();
HttpResponse response = getHttpResponse(responseParts);
assertEquals("Unexpected response status", HttpResponseStatus.OK, response.status());
verifyTrackingHeaders(response);
ByteBuffer content = getContent(responseParts.queue, HttpUtil.getContentLength(response));
return new HashSet<>(
AccountCollectionSerde.fromJson(new JSONObject(new String(content.array(), StandardCharsets.UTF_8))));
}
@Override
public @NotNull CompletableFuture<ResponseInfo<String>> execute(
@NotNull RequestInfo<Void> request,
@NotNull Executor longRunningTaskExecutor,
@NotNull ChannelHandlerContext ctx
) {
HttpHeaders reqHeaders = request.getHeaders();
return CompletableFuture.completedFuture(
ResponseInfo.newBuilder(RESPONSE_PAYLOAD)
.withHeaders(
new DefaultHttpHeaders()
.set(RECEIVED_TRACE_ID_HEADER_KEY, String.valueOf(reqHeaders.get(TraceHeaders.TRACE_ID)))
.set(RECEIVED_SPAN_ID_HEADER_KEY, String.valueOf(reqHeaders.get(TraceHeaders.SPAN_ID)))
.set(RECEIVED_PARENT_SPAN_ID_HEADER_KEY, String.valueOf(reqHeaders.get(TraceHeaders.PARENT_SPAN_ID)))
.set(RECEIVED_SAMPLED_HEADER_KEY, String.valueOf(reqHeaders.get(TraceHeaders.TRACE_SAMPLED)))
)
.build()
);
}
@Test
public void doChannelRead_uses_existing_RequestInfo_on_state_if_available_and_does_not_recreate_it() {
// given
HttpRequest msgMock = mock(HttpRequest.class);
String uri = "/some/url";
HttpHeaders headers = new DefaultHttpHeaders();
doReturn(uri).when(msgMock).uri();
doReturn(headers).when(msgMock).headers();
doReturn(HttpVersion.HTTP_1_1).when(msgMock).protocolVersion();
doReturn(requestInfo).when(stateMock).getRequestInfo();
// when
PipelineContinuationBehavior result = handler.doChannelRead(ctxMock, msgMock);
// then
verify(stateMock, never()).setRequestInfo(any(RequestInfo.class));
assertThat(result).isEqualTo(PipelineContinuationBehavior.CONTINUE);
}
@Test
public void uber_constructor_for_full_response_sets_fields_as_expected() {
// given
int httpStatusCode = 200;
HttpHeaders headers = new DefaultHttpHeaders();
String mimeType = "text/text";
Charset contentCharset = CharsetUtil.UTF_8;
Set<Cookie> cookies = Sets.newHashSet(new DefaultCookie("key1", "val1"), new DefaultCookie("key2", "val2"));
boolean preventCompressedResponse = true;
// when
BaseResponseInfo<?> responseInfo = createNewBaseResponseInfoForTesting(httpStatusCode, headers, mimeType, contentCharset, cookies, preventCompressedResponse);
// then
assertThat(responseInfo.getHttpStatusCode(), is(httpStatusCode));
assertThat(responseInfo.getHeaders(), is(headers));
assertThat(responseInfo.getDesiredContentWriterMimeType(), is(mimeType));
assertThat(responseInfo.getDesiredContentWriterEncoding(), is(contentCharset));
assertThat(responseInfo.getCookies(), is(cookies));
assertThat(responseInfo.getUncompressedRawContentLength(), nullValue());
assertThat(responseInfo.isPreventCompressedOutput(), is(preventCompressedResponse));
assertThat(responseInfo.isResponseSendingStarted(), is(false));
assertThat(responseInfo.isResponseSendingLastChunkSent(), is(false));
}
@Test
@DataProvider(value = {
"text/text charset=US-ASCII | UTF-8 | US-ASCII",
"text/text charset=us-ascii | UTF-8 | US-ASCII",
"text/text | UTF-8 | UTF-8",
" | UTF-8 | UTF-8",
"null | UTF-8 | UTF-8",
}, splitBy = "\\|")
public void determineCharsetFromContentType_works(String contentTypeHeader, String defaultCharsetString, String expectedCharsetString) {
// given
Charset defaultCharset = Charset.forName(defaultCharsetString);
Charset expectedCharset = Charset.forName(expectedCharsetString);
HttpHeaders headers = new DefaultHttpHeaders().add(HttpHeaders.Names.CONTENT_TYPE, String.valueOf(contentTypeHeader));
// when
Charset actualCharset = HttpUtils.determineCharsetFromContentType(headers, defaultCharset);
// then
assertThat(actualCharset, is(expectedCharset));
}
@Test
public void extractCookies_works_if_cookies_defined_in_headers() {
// given
Cookie cookie1 = new DefaultCookie(UUID.randomUUID().toString(), UUID.randomUUID().toString());
Cookie cookie2 = new DefaultCookie(UUID.randomUUID().toString(), UUID.randomUUID().toString());
HttpHeaders headers = new DefaultHttpHeaders().add(HttpHeaders.Names.COOKIE, ClientCookieEncoder.LAX.encode(cookie1, cookie2));
HttpRequest nettyRequestMock = mock(HttpRequest.class);
doReturn(headers).when(nettyRequestMock).headers();
// when
Set<Cookie> extractedCookies = HttpUtils.extractCookies(nettyRequestMock);
// then
assertThat(extractedCookies.contains(cookie1), is(true));
assertThat(extractedCookies.contains(cookie2), is(true));
}
@Test
public void extractCookies_works_if_cookies_defined_in_trailing_headers() {
// given
Cookie cookie1 = new DefaultCookie(UUID.randomUUID().toString(), UUID.randomUUID().toString());
Cookie cookie2 = new DefaultCookie(UUID.randomUUID().toString(), UUID.randomUUID().toString());
HttpHeaders trailingHeaders = new DefaultHttpHeaders().add(HttpHeaders.Names.COOKIE, ClientCookieEncoder.LAX.encode(cookie1, cookie2));
FullHttpRequest nettyRequestMock = mock(FullHttpRequest.class);
doReturn(new DefaultHttpHeaders()).when(nettyRequestMock).headers();
doReturn(trailingHeaders).when(nettyRequestMock).trailingHeaders();
// when
Set<Cookie> extractedCookies = HttpUtils.extractCookies(nettyRequestMock);
// then
assertThat(extractedCookies.contains(cookie1), is(true));
assertThat(extractedCookies.contains(cookie2), is(true));
}
@Test
void inboundCookiesMustBeMergedForHttp1() {
final io.netty.handler.codec.http.HttpHeaders in = new DefaultHttpHeaders();
in.add(HttpHeaderNames.COOKIE, "a=b; c=d");
in.add(HttpHeaderNames.COOKIE, "e=f;g=h");
in.add(HttpHeaderNames.CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8);
in.add(HttpHeaderNames.COOKIE, "i=j");
in.add(HttpHeaderNames.COOKIE, "k=l;");
final HttpHeadersBuilder out = HttpHeaders.builder();
toArmeria(in, out);
assertThat(out.getAll(HttpHeaderNames.COOKIE))
.containsExactly("a=b; c=d; e=f; g=h; i=j; k=l");
}
@Parameterized.Parameters(name = "headers [{0}]")
public static Object[][] arguments() {
return new Object[][] {
{CollectionUtils.toMultiValueMap(
new LinkedCaseInsensitiveMap<>(8, Locale.ENGLISH))},
{new NettyHeadersAdapter(new DefaultHttpHeaders())},
{new TomcatHeadersAdapter(new MimeHeaders())},
{new UndertowHeadersAdapter(new HeaderMap())},
{new JettyHeadersAdapter(new HttpFields())}
};
}
@Override
public @NotNull CompletableFuture<ResponseInfo<String>> execute(
@NotNull RequestInfo<String> request,
@NotNull Executor longRunningTaskExecutor,
@NotNull ChannelHandlerContext ctx
) {
if (!EXPECTED_REQUEST_PAYLOAD.equals(request.getContent()))
throw new ApiException(MISSING_EXPECTED_REQ_PAYLOAD);
if (!EXPECTED_HEADER_VAL.equals(request.getHeaders().get(EXPECTED_HEADER_KEY)))
throw new ApiException(MISSING_EXPECTED_HEADER);
return CompletableFuture.completedFuture(
ResponseInfo.newBuilder(RESPONSE_PAYLOAD)
.withHeaders(
new DefaultHttpHeaders()
.set(TraceHeaders.TRACE_ID,
String.valueOf(request.getHeaders().get(TraceHeaders.TRACE_ID))
)
.set(TraceHeaders.SPAN_ID,
String.valueOf(request.getHeaders().get(TraceHeaders.SPAN_ID))
)
.set(TraceHeaders.PARENT_SPAN_ID,
String.valueOf(request.getHeaders().get(TraceHeaders.PARENT_SPAN_ID))
)
)
.build()
);
}
public static void trySaveRequest(final HttpServerExchange exchange, final byte[] buffer, int length) {
int maxSize = exchange.getUndertowOptions().get(UndertowOptions.MAX_BUFFERED_REQUEST_SIZE, UndertowOptions.DEFAULT_MAX_BUFFERED_REQUEST_SIZE);
if (maxSize > 0) {
if (length > maxSize) {
UndertowLogger.REQUEST_LOGGER.debugf("Request to %s was to large to save", exchange.getRequestURI());
return;//failed to save the request, we just return
}
//TODO: we should really be used pooled buffers
//TODO: we should probably limit the number of saved requests at any given time
HttpHeaders headers = new DefaultHttpHeaders();
for (String entry : exchange.getRequestHeaderNames()) {
if (entry.equals(HttpHeaderNames.CONTENT_LENGTH) ||
entry.equals(HttpHeaderNames.TRANSFER_ENCODING) ||
entry.equals(HttpHeaderNames.CONNECTION)) {
continue;
}
headers.set(entry, exchange.getRequestHeaders(entry));
}
SavedRequest request = new SavedRequest(buffer, length, exchange.getRequestMethod(), exchange.getRelativePath(), headers);
final ServletRequestContext sc = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
HttpSessionImpl session = sc.getCurrentServletContext().getSession(exchange, true);
Session underlyingSession;
if (System.getSecurityManager() == null) {
underlyingSession = session.getSession();
} else {
underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session));
}
underlyingSession.setAttribute(SESSION_KEY, request);
}
}
private void preamble(final ByteBuf buffer) {
while (buffer.isReadable()) {
final byte b = buffer.readByte();
if (subState >= 0) {
//handle the case of no preamble. In this case there is no CRLF
if (subState == Integer.MAX_VALUE) {
if (boundary[2] == b) {
subState = 2;
} else {
subState = 0;
}
}
if (b == boundary[subState]) {
subState++;
if (subState == boundary.length) {
subState = -1;
}
} else if (b == boundary[0]) {
subState = 1;
} else {
subState = 0;
}
} else if (subState == -1) {
if (b == CR) {
subState = -2;
}
} else if (subState == -2) {
if (b == LF) {
subState = 0;
state = 1;//preamble is done
headers = new DefaultHttpHeaders();
return;
} else {
subState = -1;
}
}
}
}
@BeforeClass
public static void setup() {
final BlockingHandler blockingHandler = new BlockingHandler();
DefaultServer.setRootHandler(blockingHandler);
blockingHandler.setRootHandler(new HttpHandler() {
@Override
public void handleRequest(final HttpServerExchange exchange) {
HttpHeaders trailers = new DefaultHttpHeaders();
exchange.putAttachment(HttpAttachments.RESPONSE_TRAILERS, trailers);
trailers.set("foo", "fooVal");
trailers.set("bar", "barVal");
exchange.writeAsync(message);
}
});
}
@Test
public void testBindByCookie() throws Exception {
SimpleSession session = new SimpleSession();
session.setId("test");
session.setExpired(false);
session.setAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY, true);
EasyMock
.expect(sessionDao.readSession("test"))
.andReturn(session)
// FIXME why does shiro load the session so many times????
.anyTimes();
sessionDao.update(session);
EasyMock
.expectLastCall()
.times(1);
replay();
DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/client");
DefaultHttpHeaders.addHeader(request, "Cookie", "irisAuthToken=test;");
handler.channelRead(context, request);
// an authenticated Client should have been bound
ClientFactory factory = ServiceLocator.getInstance(ClientFactory.class);
Client client = factory.get(channel);
assertNotNull(client);
assertTrue(client.isAuthenticated());
assertEquals("test", client.getSessionId());
verify();
}
@Test
public void testBindByAuthHeader() throws Exception {
SimpleSession session = new SimpleSession();
session.setId("test");
session.setExpired(false);
session.setAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY, true);
EasyMock
.expect(sessionDao.readSession("test"))
.andReturn(session)
// FIXME why does shiro load the session so many times????
.anyTimes();
sessionDao.update(session);
EasyMock
.expectLastCall()
.times(1);
replay();
DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/client");
DefaultHttpHeaders.addHeader(request, "Authorization", "test");
handler.channelRead(context, request);
// an authenticated Client should have been bound
ClientFactory factory = ServiceLocator.getInstance(ClientFactory.class);
Client client = factory.get(channel);
assertNotNull(client);
assertTrue(client.isAuthenticated());
assertEquals("test", client.getSessionId());
verify();
}
/**
* Tests reaction of NettyRequest when content size is less than the size specified in the headers.
* @throws Exception
*/
private void sizeInHeaderMoreThanContentTest() throws Exception {
List<HttpContent> httpContents = new ArrayList<HttpContent>();
ByteBuffer content = generateContent(httpContents);
HttpHeaders httpHeaders = new DefaultHttpHeaders();
httpHeaders.set(HttpHeaderNames.CONTENT_LENGTH, content.limit() + 1);
doHeaderAndContentSizeMismatchTest(httpHeaders, httpContents);
}
/** Return an Http1 Headers object based on the values in the underlying Http2Headers object. */
@Override
public HttpHeaders http1Headers(boolean isTrailer, boolean isRequest) {
try {
HttpHeaders headers = new DefaultHttpHeaders();
HttpConversionUtil.addHttp2ToHttpHeaders(
-1, delegate, headers, HttpVersion.HTTP_1_1, isTrailer, isRequest);
return headers;
} catch (Http2Exception e) {
throw new RuntimeException(e);
}
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
public DefaultHttpHeaders httpPut() {
DefaultHttpHeaders headers = new DefaultHttpHeaders(false);
for (int i = 0; i < httpNames.length; i++) {
headers.add(httpNames[i], httpValues[i]);
}
return headers;
}
@Test
public void testIsWebsocketUpgrade() {
HttpHeaders headers = new DefaultHttpHeaders();
assertFalse(WebSocketExtensionUtil.isWebsocketUpgrade(headers));
headers.add(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET);
assertFalse(WebSocketExtensionUtil.isWebsocketUpgrade(headers));
headers.add(HttpHeaderNames.CONNECTION, "Keep-Alive, Upgrade");
assertTrue(WebSocketExtensionUtil.isWebsocketUpgrade(headers));
}
/**
* Checks the case where no body needs to be returned but just a
* {@link RestResponseChannel#onResponseComplete(Exception)} is called on the server. This should return just
* response metadata.
*/
@Test
public void noResponseBodyTest() {
EmbeddedChannel channel = createEmbeddedChannel();
// with Transfer-Encoding:Chunked
HttpRequest httpRequest =
RestTestUtils.createRequest(HttpMethod.GET, TestingUri.ImmediateResponseComplete.toString(), null);
channel.writeInbound(httpRequest);
// There should be a response.
HttpResponse response = channel.readOutbound();
assertEquals("Unexpected response status", HttpResponseStatus.OK, response.status());
assertTrue("Response must say 'Transfer-Encoding : chunked'", HttpUtil.isTransferEncodingChunked(response));
// since this is Transfer-Encoding:chunked, there should be a LastHttpContent
assertTrue("Did not receive end marker", channel.readOutbound() instanceof LastHttpContent);
assertTrue("Channel should be alive", channel.isActive());
// with Content-Length set
HttpHeaders headers = new DefaultHttpHeaders();
headers.set(MockNettyMessageProcessor.CHUNK_COUNT_HEADER_NAME, 0);
httpRequest = RestTestUtils.createRequest(HttpMethod.GET, TestingUri.ImmediateResponseComplete.toString(), headers);
HttpUtil.setKeepAlive(httpRequest, false);
channel.writeInbound(httpRequest);
// There should be a response.
response = channel.readOutbound();
assertEquals("Response must have Content-Length set to 0", 0, HttpUtil.getContentLength(response, -1));
assertEquals("Unexpected response status", HttpResponseStatus.OK, response.status());
// since Content-Length is set, the response should be an instance of FullHttpResponse.
assertTrue("Response not instance of FullHttpResponse", response instanceof FullHttpResponse);
assertFalse("Channel should not be alive", channel.isActive());
}
/**
* Tests the invocation of DELAYED_CLOSE when post failures happen in {@link NettyResponseChannel}.
*/
@Test
public void completeRequestWithDelayedCloseTest() throws Exception {
Properties properties = new Properties();
long delayMs = 500;
properties.setProperty(NettyConfig.NETTY_SERVER_CLOSE_DELAY_TIMEOUT_MS, String.valueOf(delayMs));
NettyConfig nettyConfig = new NettyConfig(new VerifiableProperties(properties));
MockNettyMessageProcessor processor = new MockNettyMessageProcessor();
processor.setNettyConfig(nettyConfig);
ChunkedWriteHandler chunkedWriteHandler = new ChunkedWriteHandler();
EmbeddedChannel channel = new EmbeddedChannel(chunkedWriteHandler, processor);
RestServiceErrorCode REST_ERROR_CODE = RestServiceErrorCode.BadRequest;
String content = "@@[email protected]@@";
HttpHeaders httpHeaders = new DefaultHttpHeaders();
httpHeaders.set(MockNettyMessageProcessor.REST_SERVICE_ERROR_CODE_HEADER_NAME, REST_ERROR_CODE);
httpHeaders.set(MockNettyMessageProcessor.INCLUDE_EXCEPTION_MESSAGE_IN_RESPONSE_HEADER_NAME, "true");
HttpRequest httpRequest =
RestTestUtils.createFullRequest(HttpMethod.POST, TestingUri.OnResponseCompleteWithRestException.toString(),
httpHeaders, content.getBytes());
channel.writeInbound(httpRequest);
HttpResponse response = channel.readOutbound();
assertEquals("Unexpected response status", getExpectedHttpResponseStatus(REST_ERROR_CODE), response.status());
//channel should not be closed right away.
assertTrue("Channel closed on the server", channel.isActive());
//wait for delayed time * 2 times (to rule out timing out on border) and then check again.
Thread.sleep(delayMs * 2);
channel.runPendingTasks();
assertFalse("Channel not closed on the server", channel.isActive());
assertEquals("delayed close scheduled counter mismatch", 1,
processor.getNettyMetrics().delayedCloseScheduledCount.getCount());
assertEquals("delayed close executed counter mismatch", 1,
processor.getNettyMetrics().delayedCloseExecutedCount.getCount());
assertEquals("delayed close expired counter mismatch", 1,
processor.getNettyMetrics().delayedCloseActivatedCount.getCount());
}
@Test
public void extractCookies_returns_empty_set_if_no_cookies_defined() {
// given
FullHttpRequest nettyRequestMock = mock(FullHttpRequest.class);
doReturn(new DefaultHttpHeaders()).when(nettyRequestMock).headers();
doReturn(new DefaultHttpHeaders()).when(nettyRequestMock).trailingHeaders();
// when
Set<Cookie> extractedCookies = HttpUtils.extractCookies(nettyRequestMock);
// then
assertThat(extractedCookies, notNullValue());
assertThat(extractedCookies.isEmpty(), is(true));
}