mardi 7 février 2017

Composing BodyParser in Play 2.5

Vote count: 0

Given a function with this signature:

def parser[A](otherParser: BodyParser[A]): BodyParser[A]

How can I write the function in such a way that the request body is examined and verified before it is passed to otherParser?

For simplicity let's say that I want to verify that a header ("Some-Header", perhaps) has a value that matches the body exactly. So if I have this action:

def post(): Action(parser(parse.tolerantText)) { request =>
  Ok(request.body)
}

When I make a request like curl -H "Some-Header: hello" -d "hello" http://localhost:9000/post it should return "hello" in the response body with a status of 200. If my request is curl -H "Some-Header: hello" -d "hi" http://localhost:9000/post it should return a 400 with no body.

Here's what I've tried.

This one does not compile because otherParser(request).through(flow) expects flow to output a ByteString. The idea here was that the flow could notify the accumulator whether or not to continue processing via the Either output. I'm not sure how to let the accumulator know the status of the previous step.

def parser[A](otherParser: BodyParser[A]): BodyParser[A] = BodyParser { request =>
  val flow: Flow[ByteString, Either[Result, ByteString], NotUsed] = Flow[ByteString].map { bytes =>
    if (request.headers.get("Some-Header").contains(bytes.utf8String)) {
      Right(bytes)
    } else {
      Left(BadRequest)
    }
  }

  val acc: Accumulator[ByteString, Either[Result, A]] = otherParser(request)

  // This fails to compile because flow needs to output a ByteString
  acc.through(flow)
}

I also attempted to use filter. This one does compile and the response body that gets written is correct. However it always returns a 200 Ok response status.

def parser[A](otherParser: BodyParser[A]): BodyParser[A] = BodyParser { request =>
  val flow: Flow[ByteString, ByteString, akka.NotUsed] = Flow[ByteString].filter { bytes =>
    request.headers.get("Some-Header").contains(bytes.utf8String)
  }

  val acc: Accumulator[ByteString, Either[Result, A]] = otherParser(request)

  acc.through(flow)
}

asked 13 secs ago

Let's block ads! (Why?)



Composing BodyParser in Play 2.5

Aucun commentaire:

Enregistrer un commentaire