Commit Graph

495 Commits

Author SHA1 Message Date
Rossen Stoyanchev
d7a43d2003 Polish tests 2016-07-07 23:04:27 -04:00
Rossen Stoyanchev
7534092ef3 Comprensive support for empty request body
This commit adds support for handling an empty request body with both
HttpEntity where the body is not required and with @RequestBody where
the body is required depending on the annotation's required flag.

If the body is an explicit type (e.g. String, HttpEntity<String>) and
the body is required an exception is raised before the method is even
invoked or otherwise the body is passed in as null.

If the body is declared as an async type (e.g. Mono<String>,
HttpEntity<Mono<String>>) and is required, the error will flow through
the async type. If not required, the async type will be passed with no
values (i.e. empty).

A notable exception is rx.Single which can only have one value or one
error and cannot be empty. As a result currently the use of rx.Single
to represent the request body in any form effectively implies the body
is required.
2016-07-07 15:58:06 -04:00
Rossen Stoyanchev
a584311178 Fix StringDecoder#decodeToMono issue with empty input
Before this change decodeToMono always created a StringBuilder to
aggregate resulting in an "" (empty string) rather than an empty
Mono for an empty input stream.

Now we aggregate in the DataBuffer instead and then decode to String.
2016-07-07 15:58:06 -04:00
Rossen Stoyanchev
1e1e2f8b1b Support HttpEntity method arguments
The RequestBodyArgumentResolver has been refactored to have a shared
base class and tests with the new HttpEntityMethodArgumentResolver.

An HttpEntity argument is not expected to have an async wrapper because
the request headers are available immediately. The body however can be
asynchronous, e.g. HttpEntity<Flux<String>>.
2016-07-07 15:58:06 -04:00
Brian Clozel
4c3c54463c Upgrade build to Spring 5.0.0-BUILD-SNAPSHOT
* update bean validation API version
* MethodParameter now validates indices, see 39e3f2ebf6
* `getCharSet()` is now `getCharset()`
2016-07-07 18:11:04 +02:00
Rossen Stoyanchev
9cc01fc185 Add @RequestBody tests 2016-07-06 14:10:51 -04:00
Rossen Stoyanchev
54bfbbc607 Rename decodeOne->decodeToMono and readOne->readMono 2016-07-06 12:38:05 -04:00
Rossen Stoyanchev
9ee4f6ee30 Polish tests 2016-07-06 08:59:46 -04:00
Arjen Poutsma
b0de99bc8c Refactor ResponseBodySubscriber to Processor
This commit changes the AbstractResponseBodySubscriber into a
AbstractResponseBodyProcessor<DataBuffer, Void>, so that the processor
can be used as a return value for writeWith.

Additional, this commit no longer closes the response after an eror
occurred.

This fixes #59.
2016-07-06 13:18:42 +02:00
Rossen Stoyanchev
55193194c2 Polish tests 2016-07-05 20:39:56 -04:00
Rossen Stoyanchev
9c438a8f78 Fix failing test 2016-07-05 18:20:31 -04:00
Rossen Stoyanchev
33b6dca2a6 Polish tests 2016-07-05 18:14:47 -04:00
Rossen Stoyanchev
7af7a55ede Polish and simplify JacksonJsonEncoder 2016-07-05 12:02:47 -04:00
Rossen Stoyanchev
2068f667f3 Expose getStatusCode from ServerHttpResponse 2016-07-05 11:10:36 -04:00
Sebastien Deleuze
8690464a9b Remove @Ignore on streamResult() test
This test was fixed by previous commit that allows to
JSON encode correctly streams with more than 2 elements.
2016-07-04 15:51:44 +02:00
Sebastien Deleuze
7ed03d01c6 Fix JacksonJsonEncoder for streams with more than 2 elements 2016-07-04 15:45:32 +02:00
Sebastien Deleuze
c1518c3fde Avoid exception while setting the status code of a committed response
Before this commit, it was not possible to set the status code of an
HTTP response without throwing an exception if it was already
committed. The consequence was a lot of errors in the logs for long
lived HTTP exchanges like Server-Sent Events for example.

After this commit, ServerHttpResponse#setStatusCode() returns
true if the operation succeeded and false if the status code has not
been set because the response has already been committed.

In term of implementation, that makes status code managed
consistently with headers and cookies:
AbstractServerHttpResponse#setStatusCode() stores the status
code that will be effectively set later in the response lifecycle by
the HTTP server via AbstractServerHttpResponse#writeStatusCode()
when the response will be committed.
2016-07-04 13:16:19 +02:00
Sebastien Deleuze
b7b6704c7e Support rx.Completable 2016-07-04 11:05:49 +02:00
Sebastien Deleuze
f254680f29 Remove unused imports 2016-07-04 10:06:02 +02:00
Sebastien Deleuze
0f01729b27 Allow to configure Tomcat baseDir
This commit also set Tomcat baseDir to java.io.tmpdir for
integration tests in order to avoid creation of temporary directories
in the project root.
2016-07-04 09:52:39 +02:00
Sebastien Deleuze
b7b0313c21 Speed up RequestMappingIntegrationTests
Reactor Core + Spring Reactive now handle correctly
shorter interval for the stream result test.
2016-07-04 08:45:47 +02:00
Rossen Stoyanchev
8c76581442 Provide rich type information to ConversionService
When using the ConversionService to check and bridge to and from
reactive types we now generallly provide the full type information
available from method signatures. However that full type information
is not always necessary such as when we perform additional checks on
the generics of the reactive type (e.g. Mono<ResponseEntity>).

This allows us to switch to use DefaultFormattingConversionService
instead of GenericConversionService while also ensuring that the
CollectionToObjectConverter doesn't think it can convert List<?> to
any reactive type.

The ObjectToObjectConverter can also interfere because it is smart
enough to find the "from(Publisher<?>)" method on Flux and Mono.
To make up for that on the response side we now check if a type
is assignable to Publisher first in which case it is a simple cast.

In turn that means we don't need a PublisherToFluxConverter which can
be problematic in its own right because it can convert from Mono to
Flux which technically doesn't lose data but switches stream semantics.

Issue: #124, #128
2016-07-03 21:55:32 -04:00
Rossen Stoyanchev
fb2e796048 HandlerResult now requires MethodParameter as input
HandlerAdapter's should always be able to provide a MethodParameter
which in turn ensures that HandlerResultHandler's have full type
information from method declarations.

This commit also introduces ResolvableMethod for use in tests to make
it easy to obtain MethodParameter return types.

Issue: #128
2016-07-03 21:54:20 -04:00
Rossen Stoyanchev
df64262db6 Complete reactive conversion support refactoring
This commit ensures stream semantics (Flux vs Mono) are adhered to also
on the target side.
2016-07-01 17:42:36 -04:00
Sebastien Deleuze
917a2fb9d0 Add Decoder#decodeOne()
This commit adds a Decoder#decodeOne() method in order
to handle correctly the streaming versus one value
deserialization based on the type provided by the user.

For example, if a List parameter is provided in a controller
method, Jackson will be called once, while if the user provides
a Flux or an Observable parameter, Jackson will be called for
each element.
2016-07-01 17:42:36 -04:00
Sebastien Deleuze
12d7b78169 Refactor reactive type conversion support
This commit replaces Reactive Streams converters for RxJava1 and
CompletableFuture with Reactor specific ones. The results in conversion
that preserves stream semantics, i.e. Mono vs Flux.

For example this is allowed:
Flux -> Observable
Mono -> Single
Mono -> CompletableFuture

This is not allowed:
Flux -> Single
Mono -> Observable
Flux -> CompletableFuture

As a result it is now possible to check through the ConversionService
if a target type to convert to is a stream of many or of one which is
useful for decoding purposes.

The commit also adds PublisherToFluxConverter to allow conversion from
raw Publisher to Flux. The reverse is not necessary since Flux is a
Publisher and it's a no-op conversion.
2016-07-01 17:41:37 -04:00
Rossen Stoyanchev
952395192f Collapse core.codec and core.codec.support into one 2016-06-30 16:12:36 -04:00
Rossen Stoyanchev
4e2802338a Add MockWebSessionManager 2016-06-30 15:53:58 -04:00
Rossen Stoyanchev
39253b314a Fix tests by moving JAXB2 types back into sub-package 2016-06-30 14:09:09 -04:00
Rossen Stoyanchev
6d089cdc08 Move remaining JAXB2 test files from core to http 2016-06-30 13:48:41 -04:00
Sebastien Deleuze
b115f1885d Move JSON and XML codecs to org.springframework.http.codec 2016-06-30 17:01:50 +02:00
Arjen Poutsma
1d48e7c5b9 Allow to set response status on Undertow
Refactored Undertow support to register a response listener only when
the body is written to, as opposed to registering it at startup. The
reason for this is that getting the response channel from the
HttpServerExchange commits the status and response, making it impossible
to change them after the fact.

Fixed issue #119.
2016-06-30 15:27:08 +02:00
Rossen Stoyanchev
e9d8152ab2 Port fix for SPR-14397
This is a port of the following commit, adapted for Java 8+:
89396ff01f
2016-06-29 17:34:45 -04:00
Sebastien Deleuze
1f2fbba89b Make JsonObjectDecoder mandatory in JacksonJsonDecoder 2016-06-29 10:34:46 +02:00
Sebastien Deleuze
13b6f4fee4 Add SseEventEncoder to WebReactiveConfiguration 2016-06-28 11:11:45 +02:00
Rossen Stoyanchev
67175005e3 Add failing Jackson-related response body tests 2016-06-27 09:01:22 -04:00
Rossen Stoyanchev
699b057126 ResponseBodyResultHandler ignores ResponseEntity
Currently ResponseEntityResultHandler is ordered lower than
ResponseBodyResultHandler by default whch means a ResponseEntity
should not be picked by the ResponseBodyResultHandler.

However as it is easy to have both ResponseEntity and @ResponseBody
e.g. in @RestControler (or even by mistake) and in general it makes
sense for ResponseBodyResultHandler to explicitly recognize and
ignore the ResponseEntity return type.
2016-06-27 09:00:46 -04:00
Sebastien Deleuze
c24b504a07 Speedup flushing tests 2016-06-27 08:59:24 +02:00
Rossen Stoyanchev
0ff7df8b5c Improve default content type handling
We now also check the default content type if the content type is
application/octet-stream as we do today.

Uncommented failing test that now passes.
2016-06-24 18:14:11 -04:00
Rossen Stoyanchev
95751acb33 Support async wrappers for ResponseEntity
Before this commit only ResponseEntity with async body was supported,
e.g. ResponseEntity<Mono<String>>

This commit also adds suppport for an asyn wrapper around,
e.g. Mono<ResponseEntity<String>.
2016-06-24 17:17:17 -04:00
Rossen Stoyanchev
49bb83c0ec Refactor view resolution tests 2016-06-24 15:39:45 -04:00
Rossen Stoyanchev
cae8800183 Refactor @ResponseBody and ResponseEntity tests
Introduce separate test classes for each base class in the hierarchy
above @ResponseBody and ResponseEntity result handlers.

Also start porting existing unit test cases for @ResponseBody and
ResponseEntity return value handlers.
2016-06-24 13:25:41 -04:00
Sebastien Deleuze
e6a0b39df5 Remove SseHttpMessageConverter
CodecHttpMessageConverter is now suitable for SSE since it now
handles default content type.
2016-06-24 17:11:29 +02:00
Arjen Poutsma
52325a21ff Fixed Undertow flush support
Reactored Servlet 3.1 and Undertow response support into an
AbstractResponseBodySubscriber that uses an internal state machine,
making thread-safity a lot easier.
2016-06-24 15:28:12 +02:00
Sebastien Deleuze
6b3d5f1bc5 Turn FlushingDataBuffer to an empty DataBuffer 2016-06-24 15:28:12 +02:00
Sebastien Deleuze
3c80c19c19 Take in account Rossen and Arjen feedbacks 2016-06-24 15:28:12 +02:00
Sebastien Deleuze
9004812231 Add Server-Sent Events support
Flux<SseEvent> is Spring Web Reactive equivalent to Spring MVC
SseEmitter type. It allows to send Server-Sent Events in a reactive way.
Sending Flux<String> or Flux<Pojo> is equivalent to sending
Flux<SseEvent> with the data property set to the String or
Pojo value. For example:

@RestController
public class SseController {

	@RequestMapping("/sse/string")
	Flux<String> string() {
		return Flux.interval(Duration.ofSeconds(1)).map(l -> "foo " + l);
	}

	@RequestMapping("/sse/person")
	Flux<Person> person() {
		return Flux.interval(Duration.ofSeconds(1)).map(l -> new Person(Long.toString(l), "foo", "bar"));
	}

	@RequestMapping("/sse-raw")
	Flux<SseEvent> sse() {
		return Flux.interval(Duration.ofSeconds(1)).map(l -> {
			SseEvent event = new SseEvent();
			event.setId(Long.toString(l));
			event.setData("foo\nbar");
			event.setComment("bar\nbaz");
			return event;
		});
	}
}
2016-06-24 15:27:26 +02:00
Sebastien Deleuze
aeb35787d7 Add flushing support
This commit add flushing support thanks to the FlushingDataBuffer
wrapper that allows to identify the elements that should trigger a
flush.
2016-06-24 15:23:26 +02:00
Rossen Stoyanchev
9aa6f5caac Add support for ResponseEntity result handling 2016-06-21 17:27:52 -04:00
Sebastien Deleuze
b5ec47d360 Polishing 2016-06-20 17:10:31 +02:00