Add base classes for ServerHttpRequest/Response impls
This commit is contained in:
parent
eedc90818f
commit
f8ef2e0220
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2015 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.http.server.reactive;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common base class for {@link ServerHttpRequest} implementations.
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
*/
|
||||||
|
public abstract class AbstractServerHttpRequest implements ServerHttpRequest {
|
||||||
|
|
||||||
|
private URI uri;
|
||||||
|
|
||||||
|
private HttpHeaders headers;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI getURI() {
|
||||||
|
if (this.uri == null) {
|
||||||
|
try {
|
||||||
|
this.uri = initUri();
|
||||||
|
}
|
||||||
|
catch (URISyntaxException ex) {
|
||||||
|
throw new IllegalStateException("Could not get URI: " + ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a URI that represents the request.
|
||||||
|
* Invoked lazily on the first call to {@link #getURI()} and then cached.
|
||||||
|
* @throws URISyntaxException
|
||||||
|
*/
|
||||||
|
protected abstract URI initUri() throws URISyntaxException;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpHeaders getHeaders() {
|
||||||
|
if (this.headers == null) {
|
||||||
|
this.headers = HttpHeaders.readOnlyHttpHeaders(initHeaders());
|
||||||
|
}
|
||||||
|
return this.headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the headers from the underlying request.
|
||||||
|
* Invoked lazily on the first call to {@link #getHeaders()} and then cached.
|
||||||
|
*/
|
||||||
|
protected abstract HttpHeaders initHeaders();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2015 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.http.server.reactive;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.reactivestreams.Publisher;
|
||||||
|
import reactor.Flux;
|
||||||
|
import reactor.Mono;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for {@link ServerHttpResponse} implementations.
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
*/
|
||||||
|
public abstract class AbstractServerHttpResponse implements ServerHttpResponse {
|
||||||
|
|
||||||
|
private final HttpHeaders headers;
|
||||||
|
|
||||||
|
private boolean headersWritten = false;
|
||||||
|
|
||||||
|
|
||||||
|
protected AbstractServerHttpResponse() {
|
||||||
|
this.headers = new HttpHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpHeaders getHeaders() {
|
||||||
|
return (this.headersWritten ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> setBody(Publisher<ByteBuffer> publisher) {
|
||||||
|
return Flux.from(publisher).lift(new WriteWithOperator<>(writeWithPublisher -> {
|
||||||
|
writeHeaders();
|
||||||
|
return setBodyInternal(writeWithPublisher);
|
||||||
|
})).after();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement this method to write to the underlying the response.
|
||||||
|
* @param publisher the publisher to write with
|
||||||
|
*/
|
||||||
|
protected abstract Mono<Void> setBodyInternal(Publisher<ByteBuffer> publisher);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeHeaders() {
|
||||||
|
if (!this.headersWritten) {
|
||||||
|
try {
|
||||||
|
writeHeadersInternal();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
this.headersWritten = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement this method to apply header changes from {@link #getHeaders()}
|
||||||
|
* to the underlying response. This method is protected from being called
|
||||||
|
* more than once.
|
||||||
|
*/
|
||||||
|
protected abstract void writeHeadersInternal();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -32,14 +32,10 @@ import org.springframework.util.Assert;
|
||||||
*
|
*
|
||||||
* @author Stephane Maldini
|
* @author Stephane Maldini
|
||||||
*/
|
*/
|
||||||
public class ReactorServerHttpRequest implements ServerHttpRequest {
|
public class ReactorServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
|
|
||||||
private final HttpChannel<Buffer, ?> channel;
|
private final HttpChannel<Buffer, ?> channel;
|
||||||
|
|
||||||
private URI uri;
|
|
||||||
|
|
||||||
private HttpHeaders headers;
|
|
||||||
|
|
||||||
|
|
||||||
public ReactorServerHttpRequest(HttpChannel<Buffer, ?> request) {
|
public ReactorServerHttpRequest(HttpChannel<Buffer, ?> request) {
|
||||||
Assert.notNull("'request' must not be null.");
|
Assert.notNull("'request' must not be null.");
|
||||||
|
|
@ -57,27 +53,17 @@ public class ReactorServerHttpRequest implements ServerHttpRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getURI() {
|
protected URI initUri() throws URISyntaxException {
|
||||||
if (this.uri == null) {
|
return new URI(this.channel.uri());
|
||||||
try {
|
|
||||||
this.uri = new URI(this.channel.uri());
|
|
||||||
}
|
|
||||||
catch (URISyntaxException ex) {
|
|
||||||
throw new IllegalStateException("Could not get URI: " + ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.uri;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
protected HttpHeaders initHeaders() {
|
||||||
if (this.headers == null) {
|
HttpHeaders headers = new HttpHeaders();
|
||||||
this.headers = new HttpHeaders();
|
for (String name : this.channel.headers().names()) {
|
||||||
for (String name : this.channel.headers().names()) {
|
headers.put(name, this.channel.headers().getAll(name));
|
||||||
this.headers.put(name, this.channel.headers().getAll(name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this.headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import reactor.io.buffer.Buffer;
|
||||||
import reactor.io.net.http.HttpChannel;
|
import reactor.io.net.http.HttpChannel;
|
||||||
import reactor.io.net.http.model.Status;
|
import reactor.io.net.http.model.Status;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
|
@ -34,19 +33,14 @@ import org.springframework.util.Assert;
|
||||||
* @author Stephane Maldini
|
* @author Stephane Maldini
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
public class ReactorServerHttpResponse implements ServerHttpResponse {
|
public class ReactorServerHttpResponse extends AbstractServerHttpResponse {
|
||||||
|
|
||||||
private final HttpChannel<?, Buffer> channel;
|
private final HttpChannel<?, Buffer> channel;
|
||||||
|
|
||||||
private final HttpHeaders headers;
|
|
||||||
|
|
||||||
private boolean headersWritten = false;
|
|
||||||
|
|
||||||
|
|
||||||
public ReactorServerHttpResponse(HttpChannel<?, Buffer> response) {
|
public ReactorServerHttpResponse(HttpChannel<?, Buffer> response) {
|
||||||
Assert.notNull("'response' must not be null.");
|
Assert.notNull("'response' must not be null.");
|
||||||
this.channel = response;
|
this.channel = response;
|
||||||
this.headers = new HttpHeaders();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -60,29 +54,16 @@ public class ReactorServerHttpResponse implements ServerHttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
|
||||||
return (this.headersWritten ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> setBody(Publisher<ByteBuffer> publisher) {
|
|
||||||
return Flux.from(publisher).lift(new WriteWithOperator<>(this::setBodyInternal)).after();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Mono<Void> setBodyInternal(Publisher<ByteBuffer> publisher) {
|
protected Mono<Void> setBodyInternal(Publisher<ByteBuffer> publisher) {
|
||||||
writeHeaders();
|
return Mono.from(this.channel.writeWith(Flux.from(publisher).map(Buffer::new)));
|
||||||
return Mono.from(getReactorChannel().writeWith(Flux.from(publisher).map(Buffer::new)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeHeaders() {
|
protected void writeHeadersInternal() {
|
||||||
if (!this.headersWritten) {
|
for (String name : getHeaders().keySet()) {
|
||||||
for (String name : this.headers.keySet()) {
|
for (String value : getHeaders().get(name)) {
|
||||||
for (String value : this.headers.get(name)) {
|
this.channel.responseHeaders().add(name, value);
|
||||||
this.channel.responseHeaders().add(name, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.headersWritten = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,10 @@ import org.springframework.util.Assert;
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @author Stephane Maldini
|
* @author Stephane Maldini
|
||||||
*/
|
*/
|
||||||
public class RxNettyServerHttpRequest implements ServerHttpRequest {
|
public class RxNettyServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
|
|
||||||
private final HttpServerRequest<ByteBuf> request;
|
private final HttpServerRequest<ByteBuf> request;
|
||||||
|
|
||||||
private URI uri;
|
|
||||||
|
|
||||||
private HttpHeaders headers;
|
|
||||||
|
|
||||||
|
|
||||||
public RxNettyServerHttpRequest(HttpServerRequest<ByteBuf> request) {
|
public RxNettyServerHttpRequest(HttpServerRequest<ByteBuf> request) {
|
||||||
Assert.notNull("'request', request must not be null.");
|
Assert.notNull("'request', request must not be null.");
|
||||||
|
|
@ -61,27 +57,17 @@ public class RxNettyServerHttpRequest implements ServerHttpRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getURI() {
|
protected URI initUri() throws URISyntaxException {
|
||||||
if (this.uri == null) {
|
return new URI(this.getRxNettyRequest().getUri());
|
||||||
try {
|
|
||||||
this.uri = new URI(this.getRxNettyRequest().getUri());
|
|
||||||
}
|
|
||||||
catch (URISyntaxException ex) {
|
|
||||||
throw new IllegalStateException("Could not get URI: " + ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.uri;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
protected HttpHeaders initHeaders() {
|
||||||
if (this.headers == null) {
|
HttpHeaders headers = new HttpHeaders();
|
||||||
this.headers = new HttpHeaders();
|
for (String name : this.getRxNettyRequest().getHeaderNames()) {
|
||||||
for (String name : this.getRxNettyRequest().getHeaderNames()) {
|
headers.put(name, this.getRxNettyRequest().getAllHeaderValues(name));
|
||||||
this.headers.put(name, this.getRxNettyRequest().getAllHeaderValues(name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this.headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -36,19 +36,14 @@ import org.springframework.util.Assert;
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @author Stephane Maldini
|
* @author Stephane Maldini
|
||||||
*/
|
*/
|
||||||
public class RxNettyServerHttpResponse implements ServerHttpResponse {
|
public class RxNettyServerHttpResponse extends AbstractServerHttpResponse {
|
||||||
|
|
||||||
private final HttpServerResponse<?> response;
|
private final HttpServerResponse<?> response;
|
||||||
|
|
||||||
private final HttpHeaders headers;
|
|
||||||
|
|
||||||
private boolean headersWritten = false;
|
|
||||||
|
|
||||||
|
|
||||||
public RxNettyServerHttpResponse(HttpServerResponse<?> response) {
|
public RxNettyServerHttpResponse(HttpServerResponse<?> response) {
|
||||||
Assert.notNull("'response', response must not be null.");
|
Assert.notNull("'response', response must not be null.");
|
||||||
this.response = response;
|
this.response = response;
|
||||||
this.headers = new HttpHeaders();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -62,17 +57,7 @@ public class RxNettyServerHttpResponse implements ServerHttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
|
||||||
return (this.headersWritten ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> setBody(Publisher<ByteBuffer> publisher) {
|
|
||||||
return Flux.from(publisher).lift(new WriteWithOperator<>(this::setBodyInternal)).after();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Mono<Void> setBodyInternal(Publisher<ByteBuffer> publisher) {
|
protected Mono<Void> setBodyInternal(Publisher<ByteBuffer> publisher) {
|
||||||
writeHeaders();
|
|
||||||
Observable<byte[]> content = RxJava1Converter.from(publisher).map(this::toBytes);
|
Observable<byte[]> content = RxJava1Converter.from(publisher).map(this::toBytes);
|
||||||
Observable<Void> completion = getRxNettyResponse().writeBytes(content);
|
Observable<Void> completion = getRxNettyResponse().writeBytes(content);
|
||||||
return RxJava1Converter.from(completion).after();
|
return RxJava1Converter.from(completion).after();
|
||||||
|
|
@ -85,13 +70,10 @@ public class RxNettyServerHttpResponse implements ServerHttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeHeaders() {
|
protected void writeHeadersInternal() {
|
||||||
if (!this.headersWritten) {
|
for (String name : getHeaders().keySet()) {
|
||||||
for (String name : this.headers.keySet()) {
|
for (String value : getHeaders().get(name))
|
||||||
for (String value : this.headers.get(name))
|
|
||||||
this.response.addHeader(name, value);
|
this.response.addHeader(name, value);
|
||||||
}
|
|
||||||
this.headersWritten = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,14 +39,10 @@ import org.springframework.util.StringUtils;
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
public class ServletServerHttpRequest implements ServerHttpRequest {
|
public class ServletServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
|
|
||||||
private final HttpServletRequest request;
|
private final HttpServletRequest request;
|
||||||
|
|
||||||
private URI uri;
|
|
||||||
|
|
||||||
private HttpHeaders headers;
|
|
||||||
|
|
||||||
private final Flux<ByteBuffer> requestBodyPublisher;
|
private final Flux<ByteBuffer> requestBodyPublisher;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -68,62 +64,48 @@ public class ServletServerHttpRequest implements ServerHttpRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getURI() {
|
protected URI initUri() throws URISyntaxException {
|
||||||
if (this.uri == null) {
|
return new URI(getServletRequest().getScheme(), null,
|
||||||
try {
|
getServletRequest().getServerName(),
|
||||||
this.uri = new URI(getServletRequest().getScheme(), null,
|
getServletRequest().getServerPort(),
|
||||||
getServletRequest().getServerName(),
|
getServletRequest().getRequestURI(),
|
||||||
getServletRequest().getServerPort(),
|
getServletRequest().getQueryString(), null);
|
||||||
getServletRequest().getRequestURI(),
|
|
||||||
getServletRequest().getQueryString(), null);
|
|
||||||
}
|
|
||||||
catch (URISyntaxException ex) {
|
|
||||||
throw new IllegalStateException("Could not get HttpServletRequest URI: " + ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.uri;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
protected HttpHeaders initHeaders() {
|
||||||
if (this.headers == null) {
|
HttpHeaders headers = new HttpHeaders();
|
||||||
this.headers = new HttpHeaders();
|
for (Enumeration<?> names = getServletRequest().getHeaderNames(); names.hasMoreElements(); ) {
|
||||||
for (Enumeration<?> names = getServletRequest().getHeaderNames(); names.hasMoreElements(); ) {
|
String name = (String) names.nextElement();
|
||||||
String headerName = (String) names.nextElement();
|
for (Enumeration<?> values = getServletRequest().getHeaders(name); values.hasMoreElements(); ) {
|
||||||
for (Enumeration<?> headerValues = getServletRequest().getHeaders(headerName);
|
headers.add(name, (String) values.nextElement());
|
||||||
headerValues.hasMoreElements(); ) {
|
|
||||||
String headerValue = (String) headerValues.nextElement();
|
|
||||||
this.headers.add(headerName, headerValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// HttpServletRequest exposes some headers as properties: we should include those if not already present
|
|
||||||
MediaType contentType = this.headers.getContentType();
|
|
||||||
if (contentType == null) {
|
|
||||||
String requestContentType = getServletRequest().getContentType();
|
|
||||||
if (StringUtils.hasLength(requestContentType)) {
|
|
||||||
contentType = MediaType.parseMediaType(requestContentType);
|
|
||||||
this.headers.setContentType(contentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (contentType != null && contentType.getCharSet() == null) {
|
|
||||||
String requestEncoding = getServletRequest().getCharacterEncoding();
|
|
||||||
if (StringUtils.hasLength(requestEncoding)) {
|
|
||||||
Charset charSet = Charset.forName(requestEncoding);
|
|
||||||
Map<String, String> params = new LinkedCaseInsensitiveMap<>();
|
|
||||||
params.putAll(contentType.getParameters());
|
|
||||||
params.put("charset", charSet.toString());
|
|
||||||
MediaType newContentType = new MediaType(contentType.getType(), contentType.getSubtype(), params);
|
|
||||||
this.headers.setContentType(newContentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.headers.getContentLength() == -1) {
|
|
||||||
int requestContentLength = getServletRequest().getContentLength();
|
|
||||||
if (requestContentLength != -1) {
|
|
||||||
this.headers.setContentLength(requestContentLength);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.headers;
|
MediaType contentType = headers.getContentType();
|
||||||
|
if (contentType == null) {
|
||||||
|
String requestContentType = getServletRequest().getContentType();
|
||||||
|
if (StringUtils.hasLength(requestContentType)) {
|
||||||
|
contentType = MediaType.parseMediaType(requestContentType);
|
||||||
|
headers.setContentType(contentType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (contentType != null && contentType.getCharSet() == null) {
|
||||||
|
String encoding = getServletRequest().getCharacterEncoding();
|
||||||
|
if (StringUtils.hasLength(encoding)) {
|
||||||
|
Charset charset = Charset.forName(encoding);
|
||||||
|
Map<String, String> params = new LinkedCaseInsensitiveMap<>();
|
||||||
|
params.putAll(contentType.getParameters());
|
||||||
|
params.put("charset", charset.toString());
|
||||||
|
headers.setContentType(new MediaType(contentType.getType(), contentType.getSubtype(), params));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (headers.getContentLength() == -1) {
|
||||||
|
int contentLength = getServletRequest().getContentLength();
|
||||||
|
if (contentLength != -1) {
|
||||||
|
headers.setContentLength(contentLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,8 @@ import java.util.function.Function;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.reactivestreams.Publisher;
|
import org.reactivestreams.Publisher;
|
||||||
import reactor.Flux;
|
|
||||||
import reactor.Mono;
|
import reactor.Mono;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
@ -37,16 +35,12 @@ import org.springframework.util.Assert;
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
public class ServletServerHttpResponse implements ServerHttpResponse {
|
public class ServletServerHttpResponse extends AbstractServerHttpResponse {
|
||||||
|
|
||||||
private final HttpServletResponse response;
|
private final HttpServletResponse response;
|
||||||
|
|
||||||
private final Function<Publisher<ByteBuffer>, Mono<Void>> responseBodyWriter;
|
private final Function<Publisher<ByteBuffer>, Mono<Void>> responseBodyWriter;
|
||||||
|
|
||||||
private final HttpHeaders headers;
|
|
||||||
|
|
||||||
private boolean headersWritten = false;
|
|
||||||
|
|
||||||
|
|
||||||
public ServletServerHttpResponse(HttpServletResponse response,
|
public ServletServerHttpResponse(HttpServletResponse response,
|
||||||
Function<Publisher<ByteBuffer>, Mono<Void>> responseBodyWriter) {
|
Function<Publisher<ByteBuffer>, Mono<Void>> responseBodyWriter) {
|
||||||
|
|
@ -55,7 +49,6 @@ public class ServletServerHttpResponse implements ServerHttpResponse {
|
||||||
Assert.notNull(responseBodyWriter, "'responseBodyWriter' must not be null");
|
Assert.notNull(responseBodyWriter, "'responseBodyWriter' must not be null");
|
||||||
this.response = response;
|
this.response = response;
|
||||||
this.responseBodyWriter = responseBodyWriter;
|
this.responseBodyWriter = responseBodyWriter;
|
||||||
this.headers = new HttpHeaders();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -69,38 +62,25 @@ public class ServletServerHttpResponse implements ServerHttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
|
||||||
return (this.headersWritten ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> setBody(final Publisher<ByteBuffer> publisher) {
|
|
||||||
return Flux.from(publisher).lift(new WriteWithOperator<>(this::setBodyInternal)).after();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Mono<Void> setBodyInternal(Publisher<ByteBuffer> publisher) {
|
protected Mono<Void> setBodyInternal(Publisher<ByteBuffer> publisher) {
|
||||||
writeHeaders();
|
|
||||||
return this.responseBodyWriter.apply(publisher);
|
return this.responseBodyWriter.apply(publisher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeHeaders() {
|
protected void writeHeadersInternal() {
|
||||||
if (!this.headersWritten) {
|
for (Map.Entry<String, List<String>> entry : getHeaders().entrySet()) {
|
||||||
for (Map.Entry<String, List<String>> entry : this.headers.entrySet()) {
|
String headerName = entry.getKey();
|
||||||
String headerName = entry.getKey();
|
for (String headerValue : entry.getValue()) {
|
||||||
for (String headerValue : entry.getValue()) {
|
this.response.addHeader(headerName, headerValue);
|
||||||
this.response.addHeader(headerName, headerValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
MediaType contentType = this.headers.getContentType();
|
}
|
||||||
if (this.response.getContentType() == null && contentType != null) {
|
MediaType contentType = getHeaders().getContentType();
|
||||||
this.response.setContentType(contentType.toString());
|
if (this.response.getContentType() == null && contentType != null) {
|
||||||
}
|
this.response.setContentType(contentType.toString());
|
||||||
Charset charset = (contentType != null ? contentType.getCharSet() : null);
|
}
|
||||||
if (this.response.getCharacterEncoding() == null && charset != null) {
|
Charset charset = (contentType != null ? contentType.getCharSet() : null);
|
||||||
this.response.setCharacterEncoding(charset.name());
|
if (this.response.getCharacterEncoding() == null && charset != null) {
|
||||||
}
|
this.response.setCharacterEncoding(charset.name());
|
||||||
this.headersWritten = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,14 +35,10 @@ import org.springframework.util.Assert;
|
||||||
* @author Marek Hawrylczak
|
* @author Marek Hawrylczak
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
public class UndertowServerHttpRequest implements ServerHttpRequest {
|
public class UndertowServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
|
|
||||||
private final HttpServerExchange exchange;
|
private final HttpServerExchange exchange;
|
||||||
|
|
||||||
private URI uri;
|
|
||||||
|
|
||||||
private HttpHeaders headers;
|
|
||||||
|
|
||||||
private final Flux<ByteBuffer> body;
|
private final Flux<ByteBuffer> body;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -64,31 +60,19 @@ public class UndertowServerHttpRequest implements ServerHttpRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getURI() {
|
protected URI initUri() throws URISyntaxException {
|
||||||
if (this.uri == null) {
|
return new URI(this.exchange.getRequestScheme(), null,
|
||||||
try {
|
this.exchange.getHostName(), this.exchange.getHostPort(),
|
||||||
return new URI(this.getUndertowExchange().getRequestScheme(), null,
|
this.exchange.getRequestURI(), this.exchange.getQueryString(), null);
|
||||||
this.getUndertowExchange().getHostName(),
|
|
||||||
this.getUndertowExchange().getHostPort(),
|
|
||||||
this.getUndertowExchange().getRequestURI(),
|
|
||||||
this.getUndertowExchange().getQueryString(), null);
|
|
||||||
}
|
|
||||||
catch (URISyntaxException ex) {
|
|
||||||
throw new IllegalStateException("Could not get URI: " + ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.uri;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
protected HttpHeaders initHeaders() {
|
||||||
if (this.headers == null) {
|
HttpHeaders headers = new HttpHeaders();
|
||||||
this.headers = new HttpHeaders();
|
for (HeaderValues values : this.getUndertowExchange().getRequestHeaders()) {
|
||||||
for (HeaderValues values : this.getUndertowExchange().getRequestHeaders()) {
|
headers.put(values.getHeaderName().toString(), values);
|
||||||
this.headers.put(values.getHeaderName().toString(), values);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this.headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,8 @@ import java.util.function.Function;
|
||||||
import io.undertow.server.HttpServerExchange;
|
import io.undertow.server.HttpServerExchange;
|
||||||
import io.undertow.util.HttpString;
|
import io.undertow.util.HttpString;
|
||||||
import org.reactivestreams.Publisher;
|
import org.reactivestreams.Publisher;
|
||||||
import reactor.Flux;
|
|
||||||
import reactor.Mono;
|
import reactor.Mono;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
|
@ -37,16 +35,12 @@ import org.springframework.util.Assert;
|
||||||
* @author Marek Hawrylczak
|
* @author Marek Hawrylczak
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
public class UndertowServerHttpResponse implements ServerHttpResponse {
|
public class UndertowServerHttpResponse extends AbstractServerHttpResponse {
|
||||||
|
|
||||||
private final HttpServerExchange exchange;
|
private final HttpServerExchange exchange;
|
||||||
|
|
||||||
private final Function<Publisher<ByteBuffer>, Mono<Void>> responseBodyWriter;
|
private final Function<Publisher<ByteBuffer>, Mono<Void>> responseBodyWriter;
|
||||||
|
|
||||||
private final HttpHeaders headers;
|
|
||||||
|
|
||||||
private boolean headersWritten = false;
|
|
||||||
|
|
||||||
|
|
||||||
public UndertowServerHttpResponse(HttpServerExchange exchange,
|
public UndertowServerHttpResponse(HttpServerExchange exchange,
|
||||||
Function<Publisher<ByteBuffer>, Mono<Void>> responseBodyWriter) {
|
Function<Publisher<ByteBuffer>, Mono<Void>> responseBodyWriter) {
|
||||||
|
|
@ -55,7 +49,6 @@ public class UndertowServerHttpResponse implements ServerHttpResponse {
|
||||||
Assert.notNull(responseBodyWriter, "'responseBodyWriter' must not be null");
|
Assert.notNull(responseBodyWriter, "'responseBodyWriter' must not be null");
|
||||||
this.exchange = exchange;
|
this.exchange = exchange;
|
||||||
this.responseBodyWriter = responseBodyWriter;
|
this.responseBodyWriter = responseBodyWriter;
|
||||||
this.headers = new HttpHeaders();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -70,28 +63,15 @@ public class UndertowServerHttpResponse implements ServerHttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
|
||||||
return (this.headersWritten ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> setBody(Publisher<ByteBuffer> publisher) {
|
|
||||||
return Flux.from(publisher).lift(new WriteWithOperator<>(this::setBodyInternal)).after();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Mono<Void> setBodyInternal(Publisher<ByteBuffer> publisher) {
|
protected Mono<Void> setBodyInternal(Publisher<ByteBuffer> publisher) {
|
||||||
writeHeaders();
|
|
||||||
return this.responseBodyWriter.apply(publisher);
|
return this.responseBodyWriter.apply(publisher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeHeaders() {
|
protected void writeHeadersInternal() {
|
||||||
if (!this.headersWritten) {
|
for (Map.Entry<String, List<String>> entry : getHeaders().entrySet()) {
|
||||||
for (Map.Entry<String, List<String>> entry : this.headers.entrySet()) {
|
HttpString headerName = HttpString.tryFromString(entry.getKey());
|
||||||
HttpString headerName = HttpString.tryFromString(entry.getKey());
|
this.exchange.getResponseHeaders().addAll(headerName, entry.getValue());
|
||||||
this.exchange.getResponseHeaders().addAll(headerName, entry.getValue());
|
|
||||||
}
|
|
||||||
this.headersWritten = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue