CalumMcCall
CalumMcCall

Reputation: 1687

Sending auth cookie using WS and ScalaTest

I have a web app which uses a form to login, this returns a session cookie to the user which is used to authorize requests to the rest of the app. I'm having trouble sending this cookie value with my requests. My test harness is below:

val loginResponse = await(WS.url(s"http://localhost:$port/authenticate")
  .withHeaders("Content-Type" -> "application/x-www-form-urlencoded")
  .post(Map("email" -> Seq("[email protected]"), "password" -> Seq("genivirocks!"))))
loginResponse.status mustBe (OK)
val cookies = loginResponse.cookies(0).toString
val vehiclesResponse = await(WS.url(s"http://localhost:$port/api/v1/vehicles/" + testVin)
  .withHeaders("Cookie" -> cookies)
  .put(""))
vehiclesResponse.status mustBe (OK)
val vehiclesFilterResponse = await(WS.url(s"http://localhost:$port/api/v1/vehicles?regex=" + testVin)
  .withHeaders("Cookie" -> cookies)
  .get())
vehiclesFilterResponse.status mustBe (OK)

The request fails, as the second request gets a 204 instead of a 200, as it gets redirected to the login page because the cookie is interpreted as invalid. The web server gives the following error, when the second request is made:

2015-10-06 14:56:15,991 [sota-core-service-akka.actor.default-dispatcher-42] WARN akka.actor.ActorSystemImpl - Illegal request header: Illegal 'cookie' header: Invalid input 'EOI', expected tchar, '\r', WSP or '=' (line 1, column 178): PLAY2AUTH_SESS_ID=ee84a2d5a0a422a3e5446f82f9f3c6f8eda9db1cr~jz7ei0asg0hk.ebd8j.h4cpjj~~9c0(yxt8p*jqvgf)_t1.5b(7i~tly21(*id; path=/; expires=1444139775000; maxAge=3600s; HTTPOnly

I've tried building the cookie string myself and making sure there are no extra '\r' characters at the end and so on, with no luck. Google also doesn't seem to have any hints. Is there a better way of sending cookie values using WS?

EDIT

Got it working with the following code:

import play.api.mvc.Cookies

val loginResponse = ...
loginResponse.status mustBe (OK)
val cookies = loginResponse.cookies
val cookie = Cookies.decodeCookieHeader(loginResponse.cookies(0).toString)
val vehiclesResponse = await(WS.url(s"http://localhost:$port/api/v1/vehicles/" + testVin)
  .withHeaders("Cookie" -> Cookies.encodeCookieHeader(cookie))
  .put(""))
vehiclesResponse.status mustBe (OK)
...

Upvotes: 0

Views: 445

Answers (1)

JoseM
JoseM

Reputation: 4302

Why don't you use the existing Cookies.encode function to do the cookie encoding for you?

import play.api.mvc.Cookies

val loginResponse = ...
loginResponse.status mustBe (OK)
val cookies = loginResponse.cookies
val vehiclesResponse = await(WS.url(s"http://localhost:$port/api/v1/vehicles/" + testVin)
  .withHeaders("Cookie" -> Cookies.encode(cookies))
  .put(""))
vehiclesResponse.status mustBe (OK)
...

Upvotes: 1

Related Questions