Save the server-port of the original request - #1865
Conversation
… in a lazy val, and Jetty will recycle the request instance if the lazy val is realized too late
farmdawgnation
left a comment
There was a problem hiding this comment.
Looks good overall. One minor, opportunistic formatting change requested.
| lazy val serverPort: Int = req.serverPort match { | ||
| case 80 => headers("X-SSL").flatMap(Helpers.asBoolean _).filter(a => a).map(a => 443).headOption getOrElse 80 | ||
| lazy val serverPort: Int = _serverPort match { | ||
| case 80 => headers("X-SSL").flatMap(Helpers.asBoolean).filter(identity).map(a => 443).headOption getOrElse 80 |
There was a problem hiding this comment.
While we're here, can we change this to be a bit more readable?
case 80 =>
headers("X-SSL")
.flatMap(Helpers.asBoolean)
.filter(identity)
.map(a => 443)
.headOption
.getOrElse(80)Also, what's the point of the filter?
There was a problem hiding this comment.
Formatting done.
And about that filter call: It seems to exist because the headers method returns a List[String] and we want to check if there is any true value.
But, now that I looked into it a bit more, I think there might be something wrong with how the headers method is used here. It doesn't return header values, it just returns the names of the headers, which are never going to be converted to a true value and the result of this entire chain is always 80.
I am not sure if I should push a change here or create a ticket.
The
Hm, that doesn't look good. I don't have time to look at it right now, but can you build out a unit test demonstrating that? If you're right, I think we should look to fix it here. |
|
About the About the |
|
@farmdawgnation Added a quick-n-dirty test, just for demo, to show that the current Also added a demo of a correct implementation. These are throwaway changes, and I'll clean them up if it looks okay to you. Was also wondering why we are changing the server port of the original request anyway. |
Shadowfiend
left a comment
There was a problem hiding this comment.
Left a couple of notes while I was looking around.
| } | ||
|
|
||
| private class OfflineRequestSnapshot(req: HTTPRequest, val provider: HTTPProvider) extends HTTPRequest { | ||
| private [servlet] class OfflineRequestSnapshot(req: HTTPRequest, val provider: HTTPProvider) extends HTTPRequest { |
There was a problem hiding this comment.
If we're making this private[servlet], I wonder if we just move it outside of HTTPRequestServlet and into its own file altogether? Not necessarily a pre-req for merging, just occurred to me while reading.
There was a problem hiding this comment.
Sounds like a good idea.
|
|
||
| "A snapshot request should" in { | ||
| val mockHttpRequest = mock[HTTPRequest] | ||
| val mockProvider = mock[HTTPProvider] |
There was a problem hiding this comment.
This could probably just be new HTTPProvider { val context = _ }---no huge difference, just a preference for using the language instead of mock magic when possible.
There was a problem hiding this comment.
Setting the context value to _ results in unbound placeholder parameter. I think that only works for class level vars.
Setting context to null doesn't feel right to me. I also thought about setting it to an instance of net.liftweb.http.LiftFilter, which implements the HTTPProvider trait, but then it would look like it has some purpose. So, considering these two scenarios, I think mock is probably appropriate here?
There was a problem hiding this comment.
Yeah, right you are! = null it would have to be.
It's not “right” in the sense that if this were live code it would be a bad idea. Since this is a test, I usually care a lot less.
Think of it this way: with the mock, if someone tried to call something on context, things would blow up (because there's no expectation set up for that mock). So in that sense it's the same as if you set a null there: interacting with the object in question will cause issues. But, we save ourselves whatever weird plumbing and other magic the mocking framework does, instead favoring straightforward language constructs.
There was a problem hiding this comment.
Now that you said it, null seems okay. Pushed a change.
|
|
||
| object OfflineRequestSnapshotSpec extends WebSpec with Mockito { | ||
|
|
||
| "A snapshot request should" in { |
There was a problem hiding this comment.
This can be "A snapshot request" should {. Also, I would suggest folding in the name of the class under spec, i.e. "An OfflineRequestSnapshot" should { or even (my personal preference) "OfflineRequestSnapshot" should {. This makes it easier when seeing a failed test to know exactly what class failed.
There was a problem hiding this comment.
Absolutely. I just wrote this up as a quick-n-dirty example to show the current implementation didn't work correctly. To be improved if approved. I guess this means I should go ahead and do the cleanup.
|
The Codacy issues are about converting |
|
Fwiw I do think the |
|
Yeah. In fact, I started using |
|
Found the |
farmdawgnation
left a comment
There was a problem hiding this comment.
Requesting some minor changes in the test because I was confused while reading it, but overall this is looking good.
|
|
||
| private[this] val xSSLHeader = HTTPParam(X_SSL, List("true")) :: Nil | ||
|
|
||
| private[this] def getRequestSnapshot(originalPort: Int, headers: List[HTTPParam] = xSSLHeader, params: List[HTTPParam] = Nil) = { |
There was a problem hiding this comment.
headers should probably default to Nil otherwise it's not obvious in a casual reading of your tests that the SSL header is included.
| val port80Req = getRequestSnapshot(originalPort = 80) | ||
| port80Req.serverPort shouldEqual 443 | ||
| } | ||
| s"equal to the original request-port when the '$X_SSL' header is absent or not set to the string 'true' (case-insensitive), or if the original port is not 80" in { |
There was a problem hiding this comment.
This looks ripe for splitting into three separate specifications. :)
Set the default value for the `headers` param in `getRequestSnapshot` to Nil
farmdawgnation
left a comment
There was a problem hiding this comment.
This LGTM. I'll let it sit for a day or two to get any additional feedback from interested parties, and then I'll merge it. 👍
Thanks for the solid contribution!
Issue #1794
store the server-port of the original request since it's used in a lazy val, and Jetty will recycle the request instance if the lazy val is realized too late