forked from twitter/finagle
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
finagle-http: Fix body and header in 204 and 304
Problem We currently have two problems. Firstly, as described in RFC2616[1] and RFC7231[2], 204 and 304 responses must not contain a message-body. This requirement was not enforced in finagle, i.e., a message-body can be added. Moreover, a Content-Length header field can be added to these responses, which is not allowed as mentioned in RFC7230#section-3.3.2[3]. Solution First of all, we can replace a message-body(which we call content in finagle) with Buffers.Empty if the response status code is either 204 or 304 to satisfy RFC7231. As a response status code seems to be finally determined at some point in HttpServerDispatcher, we can do this in HttpServerDispatcher. Secondly, we need to make sure not to add a Content-Length header field in a 204 response to follow RFC7230#section-3.3.2. With regard to a 304 response, a server May send a Content-Length header as mentioned in the same section. Thus it'd be better for us to allow users to set the field if they like. Result We follow the specification of RFC with regard to a message-header and message-body except that we have not added some header fields equired in a response with status code 304 to satisfy RFC7232#section-4.1[4]; Any of the following header fields must be generated: Cache-Control, Content-Location, Date, ETag, Expires, and Vary. [1] https://tools.ietf.org/html/rfc2616 [2] https://tools.ietf.org/html/rfc7231 [3] https://tools.ietf.org/html/rfc7230#section-3.3.2 [4] https://tools.ietf.org/html/rfc7232#section-4.1
- Loading branch information
1 parent
9b04fc2
commit f9eee09
Showing
5 changed files
with
228 additions
and
13 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
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
...tp/src/main/scala/com/twitter/finagle/http/filter/ModifyContentAndHeaderFieldFilter.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.http.filter | ||
|
||
import com.twitter.finagle.http.{Fields, Request, Response, Status} | ||
import com.twitter.finagle._ | ||
import com.twitter.util.Future | ||
|
||
/** | ||
* Modify Content and header field filter. Remove message-body and modify a Content-Length header field if necessary. | ||
* | ||
* @see [[https://tools.ietf.org/html/rfc2616 "Hypertext Transfer Protocol -- HTTP/1.1"]] | ||
* @see [[https://tools.ietf.org/html/rfc7230 "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing"]] | ||
* section-3.3.2 on `Content-Length` for more information. | ||
*/ | ||
private[finagle] class ModifyContentAndHeaderFieldFilter[Req <: Request] extends SimpleFilter[Req, Response] { | ||
import ModifyContentAndHeaderFieldFilter._ | ||
|
||
def apply(request: Req, service: Service[Req, Response]): Future[Response] = { | ||
service(request) map { rep => | ||
if (mustNotIncludeContent(rep.status)) { | ||
rep.clearContent() | ||
|
||
if (rep.status == Status.NoContent) | ||
rep.headerMap.remove(Fields.ContentLength) | ||
|
||
//Make sure a Content-Length header field is set with a value of 0 if it is explicitly sent for a 304 response | ||
if (rep.contentLength.isDefined) | ||
rep.headerMap.set(Fields.ContentLength, "0") | ||
} | ||
|
||
rep | ||
} | ||
} | ||
} | ||
|
||
private[finagle] object ModifyContentAndHeaderFieldFilter extends HeadFilter[Request] { | ||
|
||
val Role = Stack.Role("ModifyContentAndHeaderField") | ||
val Description = "Remove message-body and modify a Content-Length header field if necessary" | ||
|
||
private def mustNotIncludeContent(status: Status): Boolean = status match { | ||
case Status.NoContent | Status.NotModified => true | ||
case _ => false | ||
} | ||
|
||
def module: Stackable[ServiceFactory[Request, Response]] = | ||
new Stack.Module0[ServiceFactory[Request, Response]] { | ||
val role = Role | ||
val description = Description | ||
|
||
def make(next: ServiceFactory[Request, Response]): ServiceFactory[Request, Response] = { | ||
new ModifyContentAndHeaderFieldFilter().andThen(next) | ||
} | ||
} | ||
} |
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