Question

I have something like this:

case HttpRequest(POST, Uri.Path("/userAction"), headers, entity: HttpEntity.NonEmpty, protocol) =>
  val x = entity.as[spray.http.FormData].merge.asInstanceOf[spray.http.FormData].fields
  sender ! HttpResponse(entity="Got it: " + x)

It seems a little bit inconvinient to unwrap the HttpEntity, is there a much more elegant way?

Furthermore: is it possible to get the data from inputs with multiple delacred variables? Is there a better way to access FormData, e.g. as Json or HashMap?

Was it helpful?

Solution

Is there an actual reason why you are implementing this with spray-can? In routing it's more easier and natural:

lazy val yourRoute: Route = {
  (post & path("userAction")) {
    entity(as[SomeType]) { data =>
      // do what you want
    }
  }
}

In this version it all comes to the proper unmarshaller for your type (SomeType). But if you want to stick with spray-can, you can use spray-httpx unmarshaller. I don't have IDE near to me, but this can like this (actual code from my project with some Scalaz tricks):

case request @ HttpRequest(...) =>
  fromTryCatch(request.entity |> unmarshal[SomeType]) // returns Throwable \/ SomeType, like scala's Either type

Here it also comes to the right unmarshaller, e.g if you want to get your entity in Json format (i.e spray JsObject), then you need to emit a request with json payload, write entity(as[JsObject]) and provide an implicit unmarshaller from spray.json.SprayJsonSupport. I think that using this approach for FormData is a bit overhead, cause for simple Post payload you have formFields directive, and you can write:

lazy val yourRoute: Route = {
  (post & path("userAction")) {
    formFields(...) { fields => // just enumerate field names from your FormData
      // do what you want
    }
  }
}

For Map approach if the same, just add spray.json.DefaultJsonProtocol into the scope, to add unmarshaller for maps.

Still using spray-routing DSL is far better then dealing with low-level can code. If you still want to use, then take a look at spray.httpx.unmarshalling package, it contains different types of unmarshallers, for entity, request and response.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top