playframework / playframework/play-ws
Null pointer error in `play.api.libs.ws.ahc.CookieBuilder` if cookie has no value
Nobody has claimed this yet.
- Dominant language
- Scala
- Stars
- 224
- Forks
- 92
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 28
Description
In my app I construct a WSRequest and call .stream() on it (this is the Scala API). It's talking to an in-house service, which responds with a Set-Cookie header with a cookie name but no cookie value. In my repro setup I use a mock response with a line saying Set-Cookie: absent-value;. In both cases I get a null pointer exception.
I tracked it down:
- When I touch the cookies I hit this: https://github.com/playframework/play-ws/blob/d06f8b15b2564384c0754711b8cb2dbb384311f0/play-ahc-ws-standalone/src/main/scala/play/api/libs/ws/ahc/StreamedResponse.scala#L56
- This in turns goes here: https://github.com/playframework/play-ws/blob/d06f8b15b2564384c0754711b8cb2dbb384311f0/play-ahc-ws-standalone/src/main/scala/play/api/libs/ws/ahc/CookieBuilder.scala#L21
- Since the cookie value is absent, the underlying cookie builder returns null
- Then
Some(c) = Some(null)acts just likec = null(in the cookie builder) - Then
asCookie(null)is called, which tries to access(null).namewhich throws the null pointer exception.
I believe Some(c) = Option(<the same expression as before>) will make the null pointer exception not happen, but it's not obvious to me that this is the right design.
It's just what I did as a workaround: I made a wrapper around WSRepsonse which forwards everything to the underlying response, except it diverts the code path leading to this buggy line onto a copy-pasted-and-the-fixed version which says Option instead of Some on this line—plus some incidental and (I believe) unrelated changes.
I'm not sure what behavior to expect, given that value-free cookie headers do not conform to any HTTP standard I could find—not that I looked all day—but I definitely don't expect a null pointer exception.
Here's sbt dependencyTree | grep ws | grep -v aws | cut -f2- -d'-' | sort -u, just in case it helps. My above links are to the most recent version of each of the linked files, as far as I can find out; they look like differently indented versions of the source my LSP/metals setup jumps to.
com.typesafe.play:play-ahc-ws-standalone_2.13:2.1.7 [S]
com.typesafe.play:play-ahc-ws_2.13:2.8.11 (evicted by: 2.8.13)
com.typesafe.play:play-ahc-ws_2.13:2.8.13 [S]
com.typesafe.play:play-ws-standalone-json_2.13:2.1.7 [S]
com.typesafe.play:play-ws-standalone-xml_2.13:2.1.7 [S]
com.typesafe.play:play-ws-standalone_2.13:2.1.7 [S]
com.typesafe.play:play-ws_2.13:2.8.13 [S]
API: Scala. We also have a bit of java stuff lying around but I don't think it interacts with this bug.
OS/Java:
$ uname -a
Linux <hostname_withheld> 5.4.0-122-generic #138-Ubuntu SMP Wed Jun 22 15:00:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
$ java -version
openjdk version "11.0.16" 2022-07-19
OpenJDK Runtime Environment (build 11.0.16+8-post-Ubuntu-0ubuntu120.04)
OpenJDK 64-Bit Server VM (build 11.0.16+8-post-Ubuntu-0ubuntu120.04, mixed mode, sharing)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at StreamedResponse.scala line 56 and follow the cookie handling into CookieBuilder.scala line 21. Reproduce the failure with a response containing Set-Cookie: absent-value;, then determine the appropriate behavior for a cookie with no value. Done means this response no longer causes a null pointer exception.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- scala
- Domain
- api
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100