Merge branch '5.1.x'

This commit is contained in:
Rossen Stoyanchev 2019-09-12 21:17:00 +01:00
commit 7194261961
12 changed files with 139 additions and 29 deletions

View File

@ -246,6 +246,17 @@ public abstract class AbstractListenerWriteFlushProcessor<T> implements Processo
super.onSubscribe(processor, subscription);
}
}
@Override
public <T> void onComplete(AbstractListenerWriteFlushProcessor<T> processor) {
// This can happen on (very early) completion notification from container..
if (processor.changeState(this, COMPLETED)) {
processor.resultPublisher.publishComplete();
}
else {
processor.state.get().onComplete(processor);
}
}
},
REQUESTED {

View File

@ -322,6 +322,12 @@ public abstract class AbstractListenerWriteProcessor<T> implements Processor<T,
super.onSubscribe(processor, subscription);
}
}
@Override
public <T> void onComplete(AbstractListenerWriteProcessor<T> processor) {
// This can happen on (very early) completion notification from container..
processor.changeStateToComplete(this);
}
},
REQUESTED {

View File

@ -259,8 +259,13 @@ public abstract class AbstractServerHttpResponse implements ServerHttpResponse {
protected abstract void applyStatusCode();
/**
* Apply header changes from {@link #getHeaders()} to the underlying response.
* This method is called once only.
* Invoked when the response is getting committed allowing sub-classes to
* make apply header values to the underlying response.
* <p>Note that most sub-classes use an {@link HttpHeaders} instance that
* wraps an adapter to the native response headers such that changes are
* propagated to the underlying response on the go. That means this callback
* is typically not used other than for specialized updates such as setting
* the contentType or characterEncoding fields in a Servlet response.
*/
protected abstract void applyHeaders();

View File

@ -102,8 +102,15 @@ public class JettyHttpHandlerAdapter extends ServletHttpHandlerAdapter {
@Override
protected void applyHeaders() {
MediaType contentType = getHeaders().getContentType();
HttpServletResponse response = getNativeResponse();
MediaType contentType = null;
try {
contentType = getHeaders().getContentType();
}
catch (Exception ex) {
String rawContentType = getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
response.setContentType(rawContentType);
}
if (response.getContentType() == null && contentType != null) {
response.setContentType(contentType.toString());
}

View File

@ -119,7 +119,14 @@ class ServletServerHttpResponse extends AbstractListenerServerHttpResponse {
this.response.addHeader(headerName, headerValue);
}
});
MediaType contentType = getHeaders().getContentType();
MediaType contentType = null;
try {
contentType = getHeaders().getContentType();
}
catch (Exception ex) {
String rawContentType = getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
this.response.setContentType(rawContentType);
}
if (this.response.getContentType() == null && contentType != null) {
this.response.setContentType(contentType.toString());
}
@ -127,6 +134,10 @@ class ServletServerHttpResponse extends AbstractListenerServerHttpResponse {
if (this.response.getCharacterEncoding() == null && charset != null) {
this.response.setCharacterEncoding(charset.name());
}
long contentLength = getHeaders().getContentLength();
if (contentLength != -1) {
this.response.setContentLengthLong(contentLength);
}
}
@Override

View File

@ -205,7 +205,14 @@ public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
@Override
protected void applyHeaders() {
HttpServletResponse response = getNativeResponse();
MediaType contentType = getHeaders().getContentType();
MediaType contentType = null;
try {
contentType = getHeaders().getContentType();
}
catch (Exception ex) {
String rawContentType = getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
response.setContentType(rawContentType);
}
if (response.getContentType() == null && contentType != null) {
response.setContentType(contentType.toString());
}

View File

@ -248,7 +248,7 @@ public abstract class OncePerRequestFilter extends GenericFilterBean {
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
doFilter(request, response, filterChain);
filterChain.doFilter(request, response);
}
}

View File

@ -168,9 +168,10 @@ public class OncePerRequestFilterTests {
@Override
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) {
FilterChain filterChain) throws ServletException, IOException {
this.didFilterNestedErrorDispatch = true;
super.doFilterNestedErrorDispatch(request, response, filterChain);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -33,7 +33,9 @@ import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.server.reactive.AbstractServerHttpRequest;
import org.springframework.http.server.reactive.AbstractServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.reactive.socket.HandshakeInfo;
@ -145,8 +147,8 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Life
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
HttpServletRequest servletRequest = getHttpServletRequest(request);
HttpServletResponse servletResponse = getHttpServletResponse(response);
HttpServletRequest servletRequest = getNativeRequest(request);
HttpServletResponse servletResponse = getNativeResponse(response);
HandshakeInfo handshakeInfo = handshakeInfoFactory.get();
DataBufferFactory factory = response.bufferFactory();
@ -174,14 +176,30 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Life
return Mono.empty();
}
private HttpServletRequest getHttpServletRequest(ServerHttpRequest request) {
Assert.isInstanceOf(AbstractServerHttpRequest.class, request);
return ((AbstractServerHttpRequest) request).getNativeRequest();
private static HttpServletRequest getNativeRequest(ServerHttpRequest request) {
if (request instanceof AbstractServerHttpRequest) {
return ((AbstractServerHttpRequest) request).getNativeRequest();
}
else if (request instanceof ServerHttpRequestDecorator) {
return getNativeRequest(((ServerHttpRequestDecorator) request).getDelegate());
}
else {
throw new IllegalArgumentException(
"Couldn't find HttpServletRequest in " + request.getClass().getName());
}
}
private HttpServletResponse getHttpServletResponse(ServerHttpResponse response) {
Assert.isInstanceOf(AbstractServerHttpResponse.class, response);
return ((AbstractServerHttpResponse) response).getNativeResponse();
private static HttpServletResponse getNativeResponse(ServerHttpResponse response) {
if (response instanceof AbstractServerHttpResponse) {
return ((AbstractServerHttpResponse) response).getNativeResponse();
}
else if (response instanceof ServerHttpResponseDecorator) {
return getNativeResponse(((ServerHttpResponseDecorator) response).getDelegate());
}
else {
throw new IllegalArgumentException(
"Couldn't find HttpServletResponse in " + response.getClass().getName());
}
}
private void startLazily(HttpServletRequest request) {

View File

@ -25,6 +25,7 @@ import reactor.netty.http.server.HttpServerResponse;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.server.reactive.AbstractServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.socket.HandshakeInfo;
import org.springframework.web.reactive.socket.WebSocketHandler;
@ -73,7 +74,7 @@ public class ReactorNettyRequestUpgradeStrategy implements RequestUpgradeStrateg
@Nullable String subProtocol, Supplier<HandshakeInfo> handshakeInfoFactory) {
ServerHttpResponse response = exchange.getResponse();
HttpServerResponse reactorResponse = ((AbstractServerHttpResponse) response).getNativeResponse();
HttpServerResponse reactorResponse = getNativeResponse(response);
HandshakeInfo handshakeInfo = handshakeInfoFactory.get();
NettyDataBufferFactory bufferFactory = (NettyDataBufferFactory) response.bufferFactory();
@ -87,4 +88,17 @@ public class ReactorNettyRequestUpgradeStrategy implements RequestUpgradeStrateg
});
}
private static HttpServerResponse getNativeResponse(ServerHttpResponse response) {
if (response instanceof AbstractServerHttpResponse) {
return ((AbstractServerHttpResponse) response).getNativeResponse();
}
else if (response instanceof ServerHttpResponseDecorator) {
return getNativeResponse(((ServerHttpResponseDecorator) response).getDelegate());
}
else {
throw new IllegalArgumentException(
"Couldn't find native response in " + response.getClass().getName());
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -33,7 +33,9 @@ import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.server.reactive.AbstractServerHttpRequest;
import org.springframework.http.server.reactive.AbstractServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.reactive.socket.HandshakeInfo;
@ -131,8 +133,8 @@ public class TomcatRequestUpgradeStrategy implements RequestUpgradeStrategy {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
HttpServletRequest servletRequest = getHttpServletRequest(request);
HttpServletResponse servletResponse = getHttpServletResponse(response);
HttpServletRequest servletRequest = getNativeRequest(request);
HttpServletResponse servletResponse = getNativeResponse(response);
HandshakeInfo handshakeInfo = handshakeInfoFactory.get();
DataBufferFactory bufferFactory = response.bufferFactory();
@ -156,14 +158,30 @@ public class TomcatRequestUpgradeStrategy implements RequestUpgradeStrategy {
return Mono.empty();
}
private HttpServletRequest getHttpServletRequest(ServerHttpRequest request) {
Assert.isInstanceOf(AbstractServerHttpRequest.class, request, "ServletServerHttpRequest required");
return ((AbstractServerHttpRequest) request).getNativeRequest();
private static HttpServletRequest getNativeRequest(ServerHttpRequest request) {
if (request instanceof AbstractServerHttpRequest) {
return ((AbstractServerHttpRequest) request).getNativeRequest();
}
else if (request instanceof ServerHttpRequestDecorator) {
return getNativeRequest(((ServerHttpRequestDecorator) request).getDelegate());
}
else {
throw new IllegalArgumentException(
"Couldn't find HttpServletRequest in " + request.getClass().getName());
}
}
private HttpServletResponse getHttpServletResponse(ServerHttpResponse response) {
Assert.isInstanceOf(AbstractServerHttpResponse.class, response, "ServletServerHttpResponse required");
return ((AbstractServerHttpResponse) response).getNativeResponse();
private static HttpServletResponse getNativeResponse(ServerHttpResponse response) {
if (response instanceof AbstractServerHttpResponse) {
return ((AbstractServerHttpResponse) response).getNativeResponse();
}
else if (response instanceof ServerHttpResponseDecorator) {
return getNativeResponse(((ServerHttpResponseDecorator) response).getDelegate());
}
else {
throw new IllegalArgumentException(
"Couldn't find HttpServletResponse in " + response.getClass().getName());
}
}
private WsServerContainer getContainer(HttpServletRequest request) {

View File

@ -33,6 +33,7 @@ import reactor.core.publisher.Mono;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.server.reactive.AbstractServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.reactive.socket.HandshakeInfo;
@ -55,9 +56,7 @@ public class UndertowRequestUpgradeStrategy implements RequestUpgradeStrategy {
public Mono<Void> upgrade(ServerWebExchange exchange, WebSocketHandler handler,
@Nullable String subProtocol, Supplier<HandshakeInfo> handshakeInfoFactory) {
ServerHttpRequest request = exchange.getRequest();
Assert.isInstanceOf(AbstractServerHttpRequest.class, request);
HttpServerExchange httpExchange = ((AbstractServerHttpRequest) request).getNativeRequest();
HttpServerExchange httpExchange = getNativeRequest(exchange.getRequest());
Set<String> protocols = (subProtocol != null ? Collections.singleton(subProtocol) : Collections.emptySet());
Hybi13Handshake handshake = new Hybi13Handshake(protocols, false);
@ -77,6 +76,19 @@ public class UndertowRequestUpgradeStrategy implements RequestUpgradeStrategy {
return Mono.empty();
}
private static HttpServerExchange getNativeRequest(ServerHttpRequest request) {
if (request instanceof AbstractServerHttpRequest) {
return ((AbstractServerHttpRequest) request).getNativeRequest();
}
else if (request instanceof ServerHttpRequestDecorator) {
return getNativeRequest(((ServerHttpRequestDecorator) request).getDelegate());
}
else {
throw new IllegalArgumentException(
"Couldn't find HttpServerExchange in " + request.getClass().getName());
}
}
private class DefaultCallback implements WebSocketConnectionCallback {