Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
finagle-http: make handling of invalid URI consistent across client i…
…mplementations Problem We have inconsistent behavior when faced with a an illegal URI across our HTTP/1.x and HTTP/2 client implementations. For the HTTP/2 client, this results in unhandled exceptions propogating as `UnknownChannelExceptions` when the `java.net.URI` parser is called under the covers on invalid input via the Netty pipeline. For HTTP/1.x clients, we see the clients happily able to submit a request with invalid input. We should really see a more consistent, non-retryable exception get thrown in all cases, while still ensuring that our server implementations consistently respond to these requests with a `400 Bad Request` status. Solution Add better error handling to the `UriUtils`, which is used across our implementations to handle invalid escape sequences. Additionally, the error handling does not behave as expected for pure HTTP/2 clients, which do not have any validation/mapping installed in their pipelines. Let's add tests and ensure that we install this handling more consistently and correct this behavior through better test coverage. We will now throw a `InvalidUriException` when attempting to submit a request with an invalid URI and ensure this exception is marked as non-retryable. Result More consistent behavior across HTTP client implementations. JIRA Issues: CSL-10770 Differential Revision: https://phabricator.twitter.biz/D660069
- Loading branch information
Showing
13 changed files
with
219 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
finagle-base-http/src/main/scala/com/twitter/finagle/http/InvalidUriException.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.twitter.finagle.http | ||
|
||
import com.twitter.finagle.{ChannelException, FailureFlags} | ||
import com.twitter.logging.{HasLogLevel, Level} | ||
|
||
private[finagle] object InvalidUriException { | ||
def apply(uri: CharSequence): InvalidUriException = | ||
new InvalidUriException(uri, FailureFlags.NonRetryable) | ||
} | ||
|
||
final class InvalidUriException private ( | ||
uri: CharSequence, | ||
override val flags: Long) | ||
extends ChannelException(new IllegalArgumentException(s"Invalid URI: $uri")) | ||
with FailureFlags[InvalidUriException] | ||
with HasLogLevel { | ||
|
||
override protected def copyWithFlags(flags: Long): InvalidUriException = | ||
new InvalidUriException(uri, flags) | ||
|
||
override def logLevel: Level = Level.WARNING | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
...http/src/test/scala/com/twitter/finagle/netty4/http/handler/UriValidatorHandlerTest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.twitter.finagle.netty4.http.handler | ||
|
||
import com.twitter.finagle.http.InvalidUriException | ||
import io.netty.channel.embedded.EmbeddedChannel | ||
import io.netty.handler.codec.http.{ | ||
DefaultHttpRequest, | ||
HttpMethod, | ||
HttpRequest, | ||
HttpResponse, | ||
HttpVersion | ||
} | ||
import org.scalatest.FunSuite | ||
import org.scalatestplus.mockito.MockitoSugar | ||
|
||
class UriValidatorHandlerTest extends FunSuite with MockitoSugar { | ||
|
||
test("Accepts valid URI") { | ||
val channel = new EmbeddedChannel(UriValidatorHandler) | ||
val msg = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/abc.jpg") | ||
assert(channel.writeInbound(msg)) | ||
assert(channel.readInbound[HttpRequest].uri() == "/abc.jpg") | ||
} | ||
|
||
test("Marks decoder failure for invalid URI (non-ascii chars)") { | ||
val channel = new EmbeddedChannel(UriValidatorHandler) | ||
val msg = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/DSC02175拷貝.jpg") | ||
assert(channel.writeInbound(msg)) | ||
assert(channel.readInbound[HttpResponse].decoderResult().isFailure) | ||
} | ||
|
||
test("Write exception for invalid URI (non-ascii chars)") { | ||
val channel = new EmbeddedChannel(UriValidatorHandler) | ||
val msg = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/DSC02175拷貝.jpg") | ||
intercept[InvalidUriException] { | ||
channel.writeOutbound(msg) | ||
} | ||
} | ||
|
||
test("Marks decoder failure for invalid URI (encoding)") { | ||
val channel = new EmbeddedChannel(UriValidatorHandler) | ||
val msg = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/1%%.jpg") | ||
assert(channel.writeInbound(msg)) | ||
assert(channel.readInbound[HttpResponse].decoderResult().isFailure) | ||
} | ||
|
||
test("Write exception for invalid URI (encoding)") { | ||
val channel = new EmbeddedChannel(UriValidatorHandler) | ||
val msg = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/1%%.jpg") | ||
intercept[InvalidUriException] { | ||
channel.writeOutbound(msg) | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters