Browse Source
There is a natural way to implement ServerHttpMessage[Reader|Writer] from [Encoder|Decoder]HttpMessageWriter by resolving hints first via a protected method and then delegating to the regular read or write. There is no downside either since it does not prevent [Encoder|Decoder]HttpMessageWriter from being used for both client and server scenarios while they're more useful. As a positive side effect AbstractServerHttpMessage[Reader|Writer] can be removed further simplfications can be made (in a future commit) to accept ServerHttpMessageWriter for configuration purposes on the server side and remove instanceof checks for ServerHttpMessageWriter.pull/1363/head
7 changed files with 104 additions and 239 deletions
@ -1,107 +0,0 @@
@@ -1,107 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2016 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.codec; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import reactor.core.publisher.Flux; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
import org.springframework.core.MethodParameter; |
||||
import org.springframework.core.ResolvableType; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.http.ReactiveHttpInputMessage; |
||||
import org.springframework.http.server.reactive.ServerHttpRequest; |
||||
import org.springframework.http.server.reactive.ServerHttpResponse; |
||||
|
||||
/** |
||||
* {@link HttpMessageReader} wrapper that implements {@link ServerHttpMessageReader} in order |
||||
* to allow providing hints to the nested {@code reader} or setting the response status for |
||||
* example, by implementing {@link #resolveReadHints(ResolvableType, ResolvableType, ServerHttpRequest)}. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 5.0 |
||||
*/ |
||||
public abstract class AbstractServerHttpMessageReader<T> implements ServerHttpMessageReader<T> { |
||||
|
||||
private HttpMessageReader<T> reader; |
||||
|
||||
|
||||
public AbstractServerHttpMessageReader(HttpMessageReader<T> reader) { |
||||
this.reader = reader; |
||||
} |
||||
|
||||
@Override |
||||
public boolean canRead(ResolvableType elementType, MediaType mediaType) { |
||||
return this.reader.canRead(elementType, mediaType); |
||||
} |
||||
|
||||
@Override |
||||
public Flux<T> read(ResolvableType elementType, ReactiveHttpInputMessage inputMessage, Map<String, Object> hints) { |
||||
return this.reader.read(elementType, inputMessage, hints); |
||||
} |
||||
|
||||
@Override |
||||
public Mono<T> readMono(ResolvableType elementType, ReactiveHttpInputMessage inputMessage, Map<String, Object> hints) { |
||||
return this.reader.readMono(elementType, inputMessage, hints); |
||||
} |
||||
|
||||
@Override |
||||
public List<MediaType> getReadableMediaTypes() { |
||||
return this.reader.getReadableMediaTypes(); |
||||
} |
||||
|
||||
@Override |
||||
public Flux<T> read(ResolvableType streamType, ResolvableType elementType, |
||||
ServerHttpRequest request, ServerHttpResponse response, Map<String, Object> hints) { |
||||
|
||||
Map<String, Object> mergedHints = new HashMap<>(hints); |
||||
mergedHints.putAll(resolveReadHints(streamType, elementType, request)); |
||||
|
||||
return (this.reader instanceof ServerHttpMessageReader ? |
||||
((ServerHttpMessageReader<T>)this.reader).read(streamType, elementType, request, response, mergedHints) : |
||||
this.read(elementType, request, mergedHints)); |
||||
} |
||||
|
||||
@Override |
||||
public Mono<T> readMono(ResolvableType streamType, ResolvableType elementType, |
||||
ServerHttpRequest request, ServerHttpResponse response, Map<String, Object> hints) { |
||||
|
||||
Map<String, Object> mergedHints = new HashMap<>(hints); |
||||
mergedHints.putAll(resolveReadHints(streamType, elementType, request)); |
||||
|
||||
return (this.reader instanceof ServerHttpMessageReader ? |
||||
((ServerHttpMessageReader<T>)this.reader).readMono(streamType, elementType, request, response, mergedHints) : |
||||
this.readMono(elementType, request, mergedHints)); |
||||
} |
||||
|
||||
/** |
||||
* Invoked before reading the request to resolve hints by |
||||
* {@link #read(ResolvableType, ResolvableType, ServerHttpRequest, ServerHttpResponse, Map)}. |
||||
* |
||||
* @param streamType the original type used for the method return value. For annotation |
||||
* based controllers, the {@link MethodParameter} is available via {@link ResolvableType#getSource()}. |
||||
* @param elementType the stream element type to process |
||||
* @param request the current HTTP request |
||||
* @return Additional information about how to write the body |
||||
*/ |
||||
protected abstract Map<String, Object> resolveReadHints(ResolvableType streamType, |
||||
ResolvableType elementType, ServerHttpRequest request); |
||||
|
||||
} |
||||
@ -1,93 +0,0 @@
@@ -1,93 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2016 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.codec; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.reactivestreams.Publisher; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
import org.springframework.core.MethodParameter; |
||||
import org.springframework.core.ResolvableType; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.http.ReactiveHttpOutputMessage; |
||||
import org.springframework.http.server.reactive.ServerHttpRequest; |
||||
import org.springframework.http.server.reactive.ServerHttpResponse; |
||||
|
||||
/** |
||||
* {@link HttpMessageWriter} wrapper that implements {@link ServerHttpMessageWriter} in order |
||||
* to allow providing hints to the nested {@code writer} or setting the response status for |
||||
* example, by implementing {@link #resolveWriteHints(ResolvableType, ResolvableType, MediaType, ServerHttpRequest)}. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 5.0 |
||||
*/ |
||||
public abstract class AbstractServerHttpMessageWriter<T> implements ServerHttpMessageWriter<T> { |
||||
|
||||
private HttpMessageWriter<T> writer; |
||||
|
||||
|
||||
public AbstractServerHttpMessageWriter(HttpMessageWriter<T> writer) { |
||||
this.writer = writer; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public boolean canWrite(ResolvableType elementType, MediaType mediaType) { |
||||
return this.writer.canWrite(elementType, mediaType); |
||||
} |
||||
|
||||
@Override |
||||
public List<MediaType> getWritableMediaTypes() { |
||||
return this.writer.getWritableMediaTypes(); |
||||
} |
||||
|
||||
@Override |
||||
public Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType elementType, |
||||
MediaType mediaType, ReactiveHttpOutputMessage outputMessage, Map<String, Object> hints) { |
||||
return this.writer.write(inputStream, elementType, mediaType, outputMessage, hints); |
||||
} |
||||
|
||||
@Override |
||||
public Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType streamType, ResolvableType elementType, |
||||
MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response, Map<String, Object> hints) { |
||||
|
||||
Map<String, Object> mergedHints = new HashMap<>(hints); |
||||
mergedHints.putAll(resolveWriteHints(streamType, elementType, mediaType, request)); |
||||
return (this.writer instanceof ServerHttpMessageWriter ? |
||||
((ServerHttpMessageWriter<T>)this.writer).write(inputStream, streamType, |
||||
elementType, mediaType, request, response, mergedHints) : |
||||
this.writer.write(inputStream, elementType, mediaType, response, mergedHints)); |
||||
} |
||||
|
||||
/** |
||||
* Invoked before writing the response to resolve hints by |
||||
* {@link #write(Publisher, ResolvableType, ResolvableType, MediaType, ServerHttpRequest, ServerHttpResponse, Map)}. |
||||
* @param streamType the original type used for the method return value. For annotation |
||||
* based controllers, the {@link MethodParameter} is available via {@link ResolvableType#getSource()}. |
||||
* @param elementType the stream element type to process |
||||
* @param mediaType the content type to use when writing. May be {@code null} to |
||||
* indicate that the default content type of the converter must be used. |
||||
* @param request the current HTTP request |
||||
* @return additional information about how to write the body |
||||
*/ |
||||
protected abstract Map<String, Object> resolveWriteHints(ResolvableType streamType, ResolvableType elementType, |
||||
MediaType mediaType, ServerHttpRequest request); |
||||
|
||||
} |
||||
Loading…
Reference in new issue