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 have to clear a message-body, which we call content in finagle, if the response status code is either 204 or 304 to satisfy RFC7231. 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 with a value of 0 if they like. Most importantly, we make sure that these things are achieved and the new system is bugwards-compatible by provding a new filter.[4] 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 required in a response with status code 304 to satisfy RFC7232#section-4.1[5]; Any of the following header fields must be generated: Cache-Control, Content-Location, Date, ETag, Expires, and Vary. As we achieve this by creating a new filter and set it to Http.scala[6], users who are not willing to make use of the functionality can easily disable it by removing the filter. [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] twitter#521 (comment) [5] https://tools.ietf.org/html/rfc7232#section-4.1 [6] https://github.com/monkey-mas/finagle/blob/finagle-6.35.0/finagle-http/src/main/scala/com/twitter/finagle/Http.scala#L298-L304
- Loading branch information
1 parent
b98237f
commit 7b0e4c4
Showing
5 changed files
with
227 additions
and
12 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
55 changes: 55 additions & 0 deletions
55
...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,55 @@ | ||
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 a content and header field filter in a 204 and 304 response. | ||
* Remove a 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 a 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