`PathPatternParser` is now thread-safe and creates a new internal parser
for each `parse` call, since this operation is cheap.
This commit removes the `ThreadLocal` based instances of
`PathPatternParser` in `ParsingPathMatcher` which are not required
anymore.
Issue: SPR-15246
With this change the original PathPatternParser is renamed
InternalPathPatternParser and a new PathPatternParser class is added.
This new PathPatternParser class is a very simple thread-safe wrapper for
the InternalPathPatternParser. It achieves this by creating a new
InternalPathPatternParser for each new parse request. This follows the
model used for SpEL parsing.
Prior to this commit, the `ShallowEtagHeaderFilter` could participate in
the response and set its ETag/Content-Length headers, even for HEAD
requests. Since the response body is empty, the filter implementation
would set a `"Content-Length: 0"`.
The RFC states that responses to HEAD requests should exhibit identical
response headers to GET (with the possible exception of payload related
headers such as Content-Length.
With this commit, `ShallowEtagHeaderFilter` now ignores HEAD requests
since the proper values may be set already for payload related headers
by the handler. The filter has no way to generate a proper ETag value
nor calculate the content length without the actual body.
Issue: SPR-15261
The first fix for issue 15264 covered the case of using a single
variable (the case mentioned in the bug report). However, when
more than one variable is used a different PathElement is built.
This RegexPathElement needs a similar change that checks the
path includes data to bind.
Issue: SPR-15264
This commit checks that a "Content-Length" request header isn't already
present before adding one in `Netty4ClientHttpRequestFactory`.
`HttpMessageConverter` implementations can write that request header so
the Netty request factory should only write that value when the header
is missing.
If that header is not written (and since we're not dealing with
the HTTP exchange in a chunked-based fashion), the HTTP client might not
send the request body at all.
Issue: SPR-15241
This commit ensures that the `PathPatternParser` and the associated
cache map are used in a threadsafe fashion, since the PathMatcher
instance can be used for concurrent requests.
Issue: SPR-15246
This commit reduces the exposition of `PathPattern` instances throughout
the `HandlerMapping` API and removes some methods from its public API.
Issue: SPR-14544
Since the introduction of `PathPatternRegistry`, the various path match
configuration flags are no longer needed in several places and that
configuration can live in the registry itself.
Issue: SPR-14544
This commit adds the new `PathPatternRegistry`, which holds a
sorted set of `PathPattern`s and allows for searching/adding patterns
This registry is being used in `HandlerMapping` implementations and
separates path pattern parsing/matching logic from the rest. Directly
using `PathPattern` instances should improve the performance of those
`HandlerMapping` implementations, since the parsing and generation of
pattern variants (trailing slash, suffix patterns, etc) is done only
once.
Issue: SPR-14544
Without this change the /{*foobar} and /** path elements were
not correctly enforcing that the first character they encounter
must be a separator. This problem was introduced when adjusting
the generated path element chains for these constructs. Originally
the generated chain included a SeparatorPathElement but in order for
these to match 'nothing' (i.e. /foo matches /foo/{*foobar}) the separator
path element was removed, so the separator enforcement needed moving
into the CaptureTheRestPathElement and WildcardTheRestPathElement.
Issue: SPR-14544
This commit introduces a PathPatternParser which parses request pattern
strings into PathPattern objects which can then be used to fast
match incoming string paths. The parser and matching supports the syntax
as described in SPR-14544. The code is optimized around the common usages
of request patterns and is designed to create very little transient
garbage when matching.
Issue: SPR-14544
Before this change the write Publisher was saved and Mono.empty()
returned from the write metohd which did not properly implement
the write contract since no writing ("consuming") was done.
This can be a problem in some cases. For example the request may appear
to succeed even if the publisher produces an error later when
subscribed to later after request handling completes.
This commit introduces a writeHandler function in the mock request and
response. By default it "writes" by consuming the content immediately,
which allows it to return a Mono<Void> that properly reflects when
writing is done, and it also caches the data so it may be replayed
later for test assertions.
For streaming scenario a custom writeHandler may be registered which
allows the custom handling to determine how long to stream before
cancelling so request handling may complete.
Issue: SPR-14590
This commit introduces JSON streaming support which
consists of serializing HTTP request with
application/stream+json media type as line delimited JSON.
It also optimize Flux serialization for application/json by
using flux.collectList() and a single Jackson invocation
instead of one call per element previous strategy.
This change result in a x4 throughput improvement
for collection with a lot of small elements.
Issues: SPR-15095, SPR-15104
The base URI is ignored for requests that include a host.
WebClient exposes UriBuilder (rather than UriBuilderFactory) for
per-request URI building based on the base URI. That provides
full control to add or replace components of the base URI.
This commit removes the use of SocketUtils#findAvailableTcpPort in
favor of letting servers pick a dynamic port by specifying port 0.
This should make integration tests more stable because the port is
chosen at the place where it needs to be used. It gives servers a
chance to try to open a socket on some port and start using the socket
if successful.