Commit Graph

746 Commits

Author SHA1 Message Date
Stephane Landelle
5692c1e945 RFC6265 cookies support
Motivation:

Currently Netty supports a weird implementation of RFC 2965.
First, this RFC has been deprecated by RFC 6265 and nobody on the
internet use this format.

Then, there's a confusion between client side and server side encoding
and decoding.

Typically, clients should only send name=value pairs.

This PR introduces RFC 6265 support, but keeps on supporting RFC 2965 in
the sense that old unused fields are simply ignored, and Cookie fields
won't be populated. Deprecated fields are comment, commentUrl, version,
discard and ports.

It also provides a mechanism for safe server-client-server roundtrip, as
User-Agents are not supposed to interpret cookie values but return them
as-is (e.g. if Set-Cookie contained a quoted value, it should be sent
back in the Cookie header in quoted form too).

Also, there are performance gains to be obtained by not allocating the
attribute name Strings, as we only want to match them to find which POJO
field to populate.

Modifications:

- New RFC6265ClientCookieEncoder/Decoder and
  RFC6265ServerCookieEncoder/Decoder pairs that live alongside old
  CookieEncoder/Decoder pair to not break backward compatibility.
- New Cookie.rawValue field, used for lossless server-client-server
  roundtrip.

Result:

RFC 6265 support.
Clean separation of client and server side.

Decoder performance gain:

Benchmark                     Mode  Samples        Score        Error
Units
parseOldClientDecoder        thrpt       20  2070169,228 ± 105044,970
ops/s
parseRFC6265ClientDecoder    thrpt       20  2954015,476 ± 126670,633
ops/s

This commit closes #3221 and #1406.
2015-01-21 19:12:09 +09:00
Norman Maurer
f10f97d6c7 Fix compilation error introduced by 7f907e8c2a 2015-01-16 16:48:15 +01:00
Frederic Bregier
cbc54f9145 Accept ';' '\\"' in the filename of HTTP Content-Disposition header
Motivation:
HttpPostMultipartRequestDecoder threw an ArrayIndexOutOfBoundsException
when trying to decode Content-Disposition header with filename
containing ';' or protected \\".
See issue #3326 and #3327.

Modifications:
Added splitMultipartHeaderValues method which cares about quotes, and
use it in splitMultipartHeader method, instead of StringUtils.split.

Result:
Filenames can contain semicolons and protected \\".
2015-01-16 13:54:43 +01:00
Trustin Lee
79450e081b Avoid unnecessary string conversion where possible
Motivation:

HttpResponseStaus, HttpMethod and HttpVersion have methods that return
AsciiString.  There's no need for object-to-string conversion.

Modifications:

Use codeAsText(), name(), text() instead of setInt() and setObject()

Result:

Efficiency
2015-01-11 12:45:49 +09:00
Trustin Lee
bec2fbcac4 Remove static imports and inner class imports for disambiguation 2015-01-11 12:44:10 +09:00
Jeff Pinner
4fa0ed980f SPDY: fix support for pushed resources in SpdyHttpEncoder
Motivation:

The SpdyHttpDecoder was modified to support pushed resources that are
divided into multiple frames. The decoder accepts a pushed
SpdySynStreamFrame containing the request headers, followed by a
SpdyHeadersFrame containing the response headers.

Modifications:

This commit modifies the SpdyHttpEncoder so that it encodes pushed
resources in a format that the SpdyHttpDecoder can decode. The encoder
will accept an HttpRequest object containing the request headers,
followed by an HttpResponse object containing the response headers.

Result:

The SpdyHttpEncoder will create a SpdySynStreamFrame followed by a
SpdyHeadersFrame when sending pushed resources.
2015-01-11 12:12:23 +09:00
Frederic Bregier
50315f28c2 Fix for Issue #3308 related to slice missing retain
Motivations:
It seems that slicing a buffer and using this slice to write to CTX will
decrease the initial refCnt to 0, while the original buffer is not yet
fully used (not empty).

Modifications:
As suggested in the ticket and tested, when the currentBuffer is sliced
since it will still be used later on, the currentBuffer is retained.

Add a test case for this issue.

Result:
The currentBuffer still has its correct refCnt when reaching the last
write (not sliced) of 1 and therefore will be released correctly.
The exception does no more occur.

This fix should be applied to all branches >= 4.0.
2015-01-06 21:04:08 +01:00
Trustin Lee
4c258a8828 Fix a compilation error
Thanks to @jknair
2014-12-31 21:42:08 +09:00
Trustin Lee
24c6b599c4 Make sure AggregatedFullHttpMessage.trailingHeaders() return non-null
When handling an oversized message, HttpObjectAggregator does not wait
until the last chunk is received to produce the failed message, making
AggregatedFullHttpMessage.trailingHeaders() return null.
2014-12-31 19:26:44 +09:00
Trustin Lee
befe4ca2e3 Implement toString() for all HttpMessage implementations
Related: #3019

Motivation:

We have multiple (Full)HttpRequest/Response implementations and only
some of them implements toString() properly.

Modifications:

- Add the reusable string converter for HttpMessages to HttpMessageUtil
- Implement toString() of (Full)HttpRequest/Response implementations
  properly using HttpMessageUtil

Result:

Prettier string representation is returned by HttpMessage
implementations.
2014-12-31 18:32:48 +09:00
Norman Maurer
1ed8a120c1 Allow to override how headers are encoded
Motivation:

Even if its against the HTTP RFC there are situations where it may be useful to use other chars then US_ASCII in the headers. We should allow to make it possible by allow the user to override the how headers are encoded.

Modifications:

- Add encodeHeaders(...) method and so allow to override it.

Result:

It's now possible to encode headers with other charset then US_ASCII by just extend the encoder and override the encodeHeaders(...) method.
2014-12-26 15:17:35 +01:00
Scott Mitchell
19f6b420a9 Headers set/add timeMillis for master branch
Motivation:
Commit eb0e127ee9 was designed for the 4.1 branch.  The 5.0 branch had a few additional classes which required updates to get the new timeMillis methods for all the header classes.

Modifications:
Update the *Headers interfaces/classes that were not updated in the 4.1 branch.

Result:
All *Headers interfaces support set/add timeMillis methods.
2014-12-26 16:01:41 +09:00
Jeff Beck
20f5974f01 HttpObjectAggregator only set Content-Length is not already set.
Motivation:

HEAD requests will have a Content-Length set that doesn't match the
actual length. So we only want to set Content-Length header if it isn't
already set.

Modifications:

If check around setting the Content-Length.

Result:

A HEAD request will no correctly return the specified Content-Length
instead of the body length.
2014-12-25 20:44:47 +01:00
Leonardo Freitas Gomes
75aa8475e1 Motivation: Sonar points out an equals comparison, where the types compared are different and don't share any common parent http://clinker.netty.io/sonar/drilldown/issues/io.netty:netty-parent:master?severity=CRITICAL#
Modifications:
Converted AsciiString into a String by calling toString() method before comparing with equals(). Also added a unit-test to show that it works.

Result:
Major violation is gone. Code is correct.
2014-12-16 06:59:48 +01:00
zcourts
a7a1b8e561 ensure getRawQuery is not null before appending
Motivation:

without this check then given a URI with path /path the resulting URL will be /path?null=

Modifications:

check that getRawQuery doesn't return null and only append if not

Result:

urls of the form /path will not have a null?= appended
2014-12-16 06:39:28 +01:00
Norman Maurer
99a703be88 Revert "Suppress channelReadComplete until MessageAggregator completes aggregating a message. https://github.com/netty/netty/issues/3168"
This reverts commit cb95a1331d.
2014-12-13 09:19:04 +01:00
Sam Young
cb95a1331d Suppress channelReadComplete until MessageAggregator completes aggregating a message. https://github.com/netty/netty/issues/3168
Motivation:
This fixes issue 3168 where HttpObjectAggregator does not suppress
channelReadComplete() when aggregation is not yet finished.

Modifications:
Ignore channelReadComplete until a message completes aggregation.
MessageAggregator currently tracks the currentMessage being aggregated.
This variable transitions to non-null when aggregation begins and back
to null when aggregation completes or fails. When the currentMessage is
null, it is safe to issue a channelReadComplete because the
corresponding channelRead will have completed aggregation.

Result:
channelReadComplete will only fire one time on each completed message
aggregation.
2014-12-13 07:58:19 +01:00
Frederic Bregier
cb6646da13 Fix AbstractDiskHttpData int conversion from long
Motivations:
The chunkSize might be oversized after comparison (size being > of int
capacity) if file size is bigger than an integer.

Modifications:
Change it to long.

Result:
There is no more int oversized.

Same fix for 4.1 and Master
2014-12-08 07:18:09 +01:00
Scott Mitchell
eb0e127ee9 Headers set/add/contains timeMillis methods
Motivation:
The new Headers interface contains methods to getTimeMillis but no add/set/contains variants.  These should be added for consistency.

Modifications:
- Add three new methods: addTimeMillis, setTimeMillis, containsTimeMillis to the Headers interface.
- Add a new method to the Headers.ValueConverter interface: T convertTimeMillis(long)
- Bring these new interfaces up the class hierarchy

Result:
All Headers classes have setters/getters for timeMillis.
2014-12-06 22:40:45 +09:00
Trustin Lee
97bf8a6d61 Change the type of HTTP string properties to AsciiString
Related: #3132

Motivation:

Changing the type of the string properties of HttpVersion and
HttpResponseStatus to AsciiString will give us the performance advantage
when encoding it into the wire.

Modifications:

- Change the type of the following properties to AsciiString:
  - HttpVersion.protocolName()
  - HttpVersion.text()
  - HttpResponseStatus.reasonPhrase()
- Inline their respective encode() methods because they are used only in
  the encoders.
- Fix the test failures incurred by the changes above

Result:

Getting close to the machine
2014-12-06 18:42:58 +09:00
Trustin Lee
377ef31bb1 Change the type of HttpMethod.name() to AsciiString
Related: #3132

Motivation:

Changing the type of HttpMethod.name() gives us the performance
advantage when encoding it into the wire.

Modifications:

- Change the type of HttpMethod.name()
- Inline HttpMethod.encode() because it's used only in a single place
  and it's trivial.

Result:

Getting close to the machine
2014-12-06 18:09:27 +09:00
Scott Mitchell
a8e5fb12fa HTTP/2 Draft 15
Motivation:
A new draft of the HTTP/2 spec has been released.

Modifications:
Make updates as defined in https://tools.ietf.org/html/draft-ietf-httpbis-http2-15

Result:
HTTP/2 codec is draft 15 compliant.
2014-11-23 13:00:00 -05:00
Scott Mitchell
95540bd49e HTTP Client Upgrade Handler Compare Issue
Motivation:
The HttpClientUpgradeHandler attempts to compare a supported codec against the input codec but the comparison logic is reversed.

Modification:
Negate the logic in HttpClientUpgradeHandler so an error is detected in the error condition.

Result:
HttpClientUpgradeHandler should not fail the upgrade when the input protocol is valid.
2014-11-22 15:55:24 +01:00
Trustin Lee
87537ce397 Add HttpStatusClass
Related: #3157

Motivation:

It should be convenient to have an easy way to classify an
HttpResponseStatus based on the first digit of the HTTP status code, as
defined in the RFC 2616:

- Information 1xx
- Success 2xx
- Redirection 3xx
- Client Error 4xx
- Server Error 5xx

Modification:

- Add HttpStatusClass
- Add HttpResponseStatus.codeClass() that returns the class of the HTTP
  status code
- Remove HttpResponseStatus.isInformational()

Result:

It's easier to determine the class of an HTTP status
2014-11-21 10:54:52 +09:00
Trustin Lee
5f8483646b Clean up 000d3a55c5
- Rename httpResponseStatus() to newStatus()
  - Move newStatus up so that static methods are grouped together
- Rename codeAsString to codeAsText
2014-11-20 19:08:16 +09:00
Daniel Bevenius
000d3a55c5 Adding codeAsText to HttpResponseStatus.
Motivation:
I found myself writing AsciiString constants in my code for
response statuses and thought that perhaps it might be nice to have
them defined by Netty instead.

Modifications:
Adding codeAsText to HttpResponseStatus that returns the status code as
AsciiText.

In addition, added the 421 Misdirected Request response code from
https://tools.ietf.org/html/draft-ietf-httpbis-http2-15#section-9.1.2

This response header was renamed in draft 15:
https://tools.ietf.org/html/draft-ietf-httpbis-http2-15#appendix-A.1
But the code itself was not changed, and I thought using the latest would
be better.

Result:
It is now possible to specify a status like this:
new DefaultHttp2Headers().status(HttpResponseStatus.OK.codeAsText());
2014-11-20 19:05:46 +09:00
Idel Pivnitskiy
9465db25ba Small performance improvements
Motivation:

Found performance issues via FindBugs and PMD.

Modifications:

- Removed unnecessary boxing/unboxing operations in DefaultTextHeaders.convertToInt(CharSequence) and DefaultTextHeaders.convertToLong(CharSequence). A boxed primitive is created from a string, just to extract the unboxed primitive value.
- Added a static modifier for DefaultHttp2Connection.ParentChangedEvent class. This class is an inner class, but does not use its embedded reference to the object which created it. This reference makes the instances of the class larger, and may keep the reference to the creator object alive longer than necessary.
- Added a static compiled Pattern to avoid compile it each time it is used when we need to replace some part of authority.
- Improved using of StringBuilders.

Result:

Performance improvements.
2014-11-19 23:44:25 -05:00
Jeff Pinner
3868645d7d SPDY: add support for pushed resources in SpdyHttpDecoder
Motivation:

The SPDY/3.1 spec does not adequate describe how to push resources
from the server. This was solidified in the HTTP/2 drafts by dividing
the push into two frames, a PushPromise containing the request,
followed by a Headers frame containing the response.

Modifications:

This commit modifies the SpdyHttpDecoder to support pushed resources
that are divided into multiple frames. The decoder will accept a
pushed SpdySynStreamFrame containing the request headers, followed by
a SpdyHeadersFrame containing the response headers.

Result:

The SpdyHttpDecoder will create an HttpRequest object followed by an
HttpResponse object when receiving pushed resources.
2014-11-15 21:47:43 +01:00
Roelof Naude
d220afa885 Cater for empty response bodies when performing response compression.
Motivation:
RFC 2616, 4.3 Message Body states that:
All 1xx (informational), 204 (no content), and 304 (not modified) responses MUST NOT include a
message-body. All other responses do include a message-body, although it MAY be of zero length.

Modifications:
HttpContentEncoder was previously modified to cater for HTTP 100 responses. This check is enhanced to
include HTTP 204 and 304 responses.

Result:
Empty response bodies will not be modified to include the compression footer. This footer messed with Chrome's
response parsing leading to "hanging" requests.
2014-11-13 08:02:54 +01:00
Idel Pivnitskiy
b2ca2148f9 Rewrite HttpObjectDecoder to make use of proper state machine
Motivation:

HttpObjectDecoder extended ReplayDecoder which is slightly slower then ByteToMessageDecoder.

Modifications:

- Changed super class of HttpObjectDecoder from ReplayDecoder to ByteToMessageDecoder.
- Rewrote decode() method of HttpObjectDecoder to use proper state machine.
- Changed private methods HeaderParser.parse(ByteBuf), readHeaders(ByteBuf) and readTrailingHeaders(ByteBuf), skipControlCharacters(ByteBuf) to consider available bytes.
- Set HeaderParser and LineParser as static inner classes.
- Replaced not safe actualReadableBytes() with buffer.readableBytes().

Result:

Improved performance of HttpObjectDecoder by approximately 177%.
2014-11-12 14:20:38 +01:00
Scott Mitchell
685075f1a0 HTTP/2 Data Compressor
Motivation:
The HTTP/2 codec currently does not provide an interface to compress data. There is an analogous case to this in the HTTP codec and it is expected to be used commonly enough that it will be beneficial to have the feature in the http2-codec.

Modifications:
- Add a class which extends DefaultHttp2ConnectionEncoder and provides hooks to an EmbeddedChannel
- Add a compressor element to the Http2Stream interface
- Update unit tests to utilize the new feature

Result:
HTTP/2 codec supports data compression.
2014-11-06 14:45:05 -05:00
Scott Mitchell
b33901c5a6 HTTP Content Encoder allow EmptyLastHttpContent
Motiviation:
The HttpContentEncoder does not account for a EmptyLastHttpContent being provided as input.  This is useful in situations where the client is unable to determine if the current content chunk is the last content chunk (i.e. a proxy forwarding content when transfer encoding is chunked).

Modifications:
- HttpContentEncoder should not attempt to compress empty HttpContent objects

Result:
HttpContentEncoder supports a EmptyLastHttpContent to terminate the response.
2014-11-05 23:32:26 -05:00
Trustin Lee
ceb06dc1b1 Remove non-standard header values from HttpHeaderValues
Motivation:

x-gzip and x-deflate are not standard header values, and thus should be
removed from HttpHeaderValues, which is meant to provide the standard
values only.

Modifications:

- Remove X_DEFLATE and X_GZIP from HttpHeaderValues
- Move X_DEFLATE and X_GZIP to HttpContentDecompressor and
  DelegatingDecompressorFrameListener
  - We have slight code duplication here, but it does less harm than
    having non-standard constant.

Result:

HttpHeaderValues contains only standard header values.
2014-11-01 02:51:34 +09:00
Trustin Lee
f793f395d6 Replace HttpHeaders.Names/Values with HttpHeaderNames/Values
Related: 4ce994dd4f

Motivation:

In 4.1, we were not able to change the type of the HTTP header name and
value constants from String to AsciiString due to backward compatibility
reasons.

Instead of breaking backward compatibility in 4.1, we introduced new
types called HttpHeaderNames and HttpHeaderValues which provides the
AsciiString version of the constants, and then deprecated
HttpHeaders.Names/Values.

We should make the same changes while deleting the deprecated classes
activaly.

Modifications:

- Remove HttpHeaders.Names/Values and RtspHeaders
- Add HttpHeaderNames/Values and RtspHeaderNames/Values
  - Make HttpHeaderValues.WEBSOCKET lowercased because it's actually
    lowercased in all WebSocket versions but the oldest one
- Do not use AsciiString.equalsIgnoreCase(CharSeq, CharSeq) if one of
  the parameters are AsciiString
  - Avoid using AsciiString.toString() repetitively
    - Change the parameter type of some methods from String to
      CharSequence

Result:

A user who upgraded from 4.0 to 4.1 first and removed the references to
the deprecated classes and methods can easily upgrade from 4.1 to 5.0.
2014-11-01 02:41:56 +09:00
Matthias Einwag
82461f0511 Added an option to use websockets without masking
Motivation:

The requirement for the masking of frames and for checks of correct
masking in the websocket specifiation have a large impact on performance.
While it is mandatory for browsers to use masking there are other
applications (like IPC protocols) that want to user websocket framing and proxy-traversing
characteristics without the overhead of masking. The websocket standard
also mentions that the requirement for mask verification on server side
might be dropped in future.

Modifications:

Added an optional parameter allowMaskMismatch for the websocket decoder
that allows a server to also accept unmasked frames (and clients to accept
masked frames).
Allowed to set this option through the websocket handshaker
constructors as well as the websocket client and server handlers.
The public API for existing components doesn't change, it will be
forwarded to functions which implicetly set masking as required in the
specification.
For websocket clients an additional parameter is added that allows to
disable the masking of frames that are sent by the client.

Result:

This update gives netty users the ability to create and use completely
unmasked websocket connections in addition to the normal masked channels
that the standard describes.
2014-10-25 22:17:41 +09:00
Trustin Lee
a63723b006 Fix a compilation error 2014-10-25 17:11:46 +09:00
Trustin Lee
1be42ca6e4 Overall cleanup of 2b191fe6e9 2014-10-25 16:59:41 +09:00
Norman Maurer
2b191fe6e9 Modify HttpObjectDecoder to allow parsing the HTTP headers in multiple steps.
Motivation:
At the moment the whole HTTP header must be parsed at once which can lead to multiple parsing of the same bytes. We can do better here and allow to parse it in multiple steps.

Modifications:

 - Not parse headers multiple times
 - Simplify the code
 - Eliminate uncessary String[] creations
 - Use readSlice(...).retain() when possible.

Result:

Performance improvements as shown in the included benchmark below.

Before change:
[nmaurer@xxx]~% ./wrk-benchmark
Running 2m test @ http://xxx:8080/plaintext
  16 threads and 256 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    21.55ms   15.10ms 245.02ms   90.26%
    Req/Sec   196.33k    30.17k  297.29k    76.03%
  373954750 requests in 2.00m, 50.15GB read
Requests/sec: 3116466.08
Transfer/sec:    427.98MB

After change:
[nmaurer@xxx]~% ./wrk-benchmark
Running 2m test @ http://xxx:8080/plaintext
  16 threads and 256 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    20.91ms   36.79ms   1.26s    98.24%
    Req/Sec   206.67k    21.69k  243.62k    94.96%
  393071191 requests in 2.00m, 52.71GB read
Requests/sec: 3275971.50
Transfer/sec:    449.89MB
2014-10-25 16:59:31 +09:00
George Agnelli
ac882d56e9 Don't close the connection whenever Expect: 100-continue is missing.
Motivation:

The 4.1.0-Beta3 implementation of HttpObjectAggregator.handleOversizedMessage closes the
connection if the client sent oversized chunked data with no Expect:
100-continue header. This causes a broken pipe or "connection reset by
peer" error in some clients (tested on Firefox 31 OS X 10.9.5,
async-http-client 1.8.14).

This part of the HTTP 1.1 spec (below) seems to say that in this scenario the connection
should not be closed (unless the intention is to be very strict about
how data should be sent).

http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html

"If an origin server receives a request that does not include an
Expect request-header field with the "100-continue" expectation,
the request includes a request body, and the server responds
with a final status code before reading the entire request body
from the transport connection, then the server SHOULD NOT close
the transport connection until it has read the entire request,
or until the client closes the connection. Otherwise, the client
might not reliably receive the response message. However, this
requirement is not be construed as preventing a server from
defending itself against denial-of-service attacks, or from
badly broken client implementations."

Modifications:

Change HttpObjectAggregator.handleOversizedMessage to close the
connection only if keep-alive is off and Expect: 100-continue is
missing. Update test to reflect the change.

Result:

Broken pipe and connection reset errors on the client are avoided when
oversized data is sent.
2014-10-24 21:49:39 +02:00
Trustin Lee
36b41570a4 Overall clean-up on Headers and its subtypes
Motivation:

- There are still various inspector warnings to fix.
- ValueConverter.convert() methods need to end with the type name like
  other methods in Headers, such as setInt() and addInt(), for more
  consistency

Modifications:

- Fix all inspector warnings
- Rename ValueConverter.convert() to convert<type>()

Result:

- Cleaner code
- Consistency
2014-10-22 15:08:12 +09:00
Trustin Lee
a1d7a84271 Handle an empty ByteBuf specially in HttpObjectEncoder
Related: #2983

Motivation:

It is a well known idiom to write an empty buffer and add a listener to
its future to close a channel when the last byte has been written out:

  ChannelFuture f = channel.writeAndFlush(Unpooled.EMPTY_BUFFER);
  f.addListener(ChannelFutureListener.CLOSE);

When HttpObjectEncoder is in the pipeline, this still works, but it
silently raises an IllegalStateException, because HttpObjectEncoder does
not allow writing a ByteBuf when it is expecting an HttpMessage.

Modifications:

- Handle an empty ByteBuf specially in HttpObjectEncoder, so that
  writing an empty buffer does not fail even if the pipeline contains an
  HttpObjectEncoder
- Add a test

Result:

An exception is not triggered anymore by HttpObjectEncoder, when a user
attempts to write an empty buffer.
2014-10-22 14:46:44 +09:00
Daniel Bevenius
b4604cdbbc CorsHandler should release HttpRequest after processing preflight/error.
Motivation:
Currently, when the CorsHandler processes a preflight request, or
respondes with an 403 Forbidden using the short-curcuit option, the
HttpRequest is not released which leads to a buffer leak.

Modifications:
Releasing the HttpRequest when done processing a preflight request or
responding with an 403.

Result:
Using the CorsHandler will not cause buffer leaks.
2014-10-22 06:36:52 +02:00
Scott Mitchell
2374e17c6e Netty Headers Class Restructure and Algorithm Updates
Motivation:
Headers within netty do not cleanly share a common class hierarchy.  As a result some header types support some operations
and don't support others.  The consolidation of the class hierarchy will allow for maintenance and scalability for new codec.
The existing hierarchy also has a few short comings such as it is not clear when data conversions are happening.  This
could result unintentionally getting back a collection or iterator where a conversion on each entry must happen.

The current headers algorithm also prepends all elements which means to find the first element or return a collection
in insertion order often requires a complete traversal followed by a collections.reverse call.

Modifications:
-Provide a generic base class which provides all the implementation for headers in netty
-Provide an extension to this class which allows for name type conversions to happen (to accommodate legacy CharSequence to String conversions)
-Update the headers interface to clarify when conversions will happen.
-Update the headers data structure so that appends are done to avoid unnecessary iteration or collection reversal.

Result:
-More unified class hierarchy for headers in netty
-Improved headers data structure and algorithms
-headers API more clearly identify when conversions are required.
2014-10-21 13:04:08 -04:00
Frederic Bregier
d6e7997f8d Master - Fix "=" character in HttpPostRequestDecoder
Motivation
Issue #3004 shows that "=" character was not supported as it should in
the HttpPostRequestDecoder in form-data boundary.

Modifications:
Add 2 methods in StringUtil

split with maxParts: String split with a max parts only (to prevent multiple '=' to
be source of extra split while not needed)
substringAfter: String part after delimiter (since first part is not needed)
Use those methods in HttpPostRequestDecoder. Change and the
HttpPostRequestDecoderTest to check using a boundary beginning with "=".

Results:
The fix implies more stability and fix the issue.
2014-10-18 01:14:28 +02:00
Trustin Lee
9c125eecb1 Add the encoder/decoder getter methods to HttpClientCodec
Motivation:

There's no way for a user to get the encoder and the decoder of an
HttpClientCodec.  The lack of such getter methods makes it impossible to
remove the codec handlers from the pipeline correctly.

For example, a user could add more than one HttpClientCodec to the
pipeline, and then the user cannot easily decide which encoder and
decoder to remove.

Modifications:

- Add encoder() and decoder() method to HttpClientCodec which returns
  HttpRequestEncoder and HttpResponseDecoder respectively
- Also made the same changes to HttpServerCodec

Result:

A user can distinguish the handlers added by multiple HttpClientCodecs
easily.
2014-10-14 12:33:44 +09:00
Matthias Einwag
a82508d422 Add verification for websocket subprotocol on the client side.
Motivation:

Websocket clients can request to speak a specific subprotocol. The list of
subprotocols the client understands are sent to the server. The server
should select one of the protocols an reply this with the websocket
handshake response. The added code verifies that the reponded subprotocol
is valid.

Modifications:

Added verification of the subprotocol received from the server against the
subprotocol(s) that the user requests. If the user requests a subprotocol
but the server responds none or a non-requested subprotocol this is an
error and the handshake fails through an exception. If the user requests
no subprotocol but the server responds one this is also marked as an
error.

Addiontionally a getter for the WebSocketClientHandshaker in the
WebSocketClientProtocolHandler is added to enable the user of a
WebSocketClientProtocolHandler to extract the used negotiated subprotocol.

Result:

The subprotocol field which is received from a websocket server is now
properly verified on client side and clients and websocket connection
attempts will now only succeed if both parties can negotiate on a
subprotocol.
If the client sends a list of multiple possible subprotocols it can
extract the negotiated subprotocol through the added handshaker getter (WebSocketClientProtocolHandler.handshaker().actualSubprotocol()).
2014-10-13 07:31:23 +02:00
Matthias Einwag
9dd8e19376 Add a test for handover from HTTP to Websocket
Motivation:
I was not fully reassured that whether everything works correctly when a websocket client receives the websocket handshake HTTP response and a websocket frame in a single ByteBuf (which can happen when the server sends a response directly or shortly after the connect). In this case some parts of the ByteBuf must be processed by HTTP decoder and the remaining by the websocket decoder.

Modification:
Adding a test that verifies that in this scenaria the handshake and the message are correctly interpreted and delivered by Netty.

Result:
One more test for Netty.
The test succeeds - No problems
2014-10-13 07:19:12 +02:00
Matthias Einwag
30db808d0f Fix the leak in the WebSocketClientProtocolHandshakeHandler
Motivation:
The WebSocketClientProtocolHandshakeHandler never releases the received handshake response.

Modification:
Release the message in a finally block.

Result:
No more leak
2014-10-12 20:25:52 +02:00
Matthias Einwag
b9e507c9cc Avoid vectored writes for small websocket messages
Motivation:
The WebSocket08FrameEncoder contains an optimization path for small messages which copies the message content into the header buffer to avoid vectored writes. However this path is in the current implementation never taken because the target buffer is preallocated only for exactly the size of the header.

Modification:
For messages below a certain treshold allocate the buffer so that the message can be directly copied. Thereby the optimized path is taken.

Result:
A speedup of about 25% for 100byte messages. Declines with bigger message sizes. I have currently set the treshold to 1kB which is a point where I could still see a few percent speedup, but we should also avoid burning too many CPU cycles.
2014-10-12 20:12:18 +02:00
Matthias Einwag
301f18c793 Improve WebSocket performance
Motivation:

Websocket performance is to a large account determined through the masking
and unmasking of frames. The current behavior of this in Netty can be
improved.

Modifications:

Perform the XOR operation not bytewise but in int blocks as long as
possible. This reduces the number of necessary operations by 4. Also don't
read the writerIndex in each iteration.
Added a unit test for websocket decoding and encoding for verifiation.

Result:

A large performance gain (up to 50%) in websocket throughput.
2014-10-12 19:54:07 +02:00