Change a body Field name in a Post in Spray - scala

I'm thinking to replace a field called "type" in a JSON in a POST with somethig like this
def rawJson = extract { _.request.entity.asString}
post {
rawJson { json =>
val new json = println(json.replace("\"type\":", "\"eventType\":"))}
}
And now, with this new JSON I want to reinject the POST to trate it like a new call.
I know "redirect" but I don't see the way to use it in this case.
Thanks!

I'll answer my own question. I hope someone else can found it useful:
I've change the post on-the-fly. My problem was that I was using: entity(as[Event]) and I was unable to transform it. But deserializing it like a JObject I have the control of the fields. It's a very powerful tool.
post {
entity(as[JObject]) {
eventO =>
val nevent: json4s.JValue = eventO.mapField(x => if (x._1=="type") ("eventType",x._2) else (x._1,x._2))
val event = nevent.extract[Event]
handlePerRequest {
RouteMessageToCluster(event)
}
}
}

Related

Gatling session - get attribute as Long

I am a new in Scala and got some problems with casting from String to Long. I try to get Gatling session value as Long in request. Before in exec() part, I try to set the userId value
def setUserId(): ChainBuilder = {
exec(session => session
.set("userId", Random.nextLong())
)
}
Next, in request creator I want to use it like that because I need a new userId every call:
object UserRequestCreator {
def sampleUserRequest(currency: String): Request = {
Data data = new Data()
data.setUserId("${userId}".toLong)
data.setCurrency(currency)
}
}
Test scenario:
exec(setUserId())
.exec(http("postUser")
.post(endpointUser).asXml
.headers(headers)
.body(StringBody(toXmlString(sampleUserRequest("EUR"), classOf[Request])))
.check(status.is(200))
but receive error:
java.lang.NumberFormatException: For input string: "${userId}"
How to fix that in Scala?
I also try Long.valueOf, JLong.parseLong("${userId"}, 16), Try(BigDecimal(...)) and more but nothing can help. I think the problem is with $ symbol, but I don't see any different way to get this value from the session. Maybe it is possible to store Long in the Gating session?
From the documentation and based on your current code, one way to do it is like that:
// with a function payload
http("name").post("/")
.body(StringBody(session => s"""{ "foo": "${session("dynamicValueKey").as[String]}" }"""))
Thus, in your case:
StringBody(session => toXmlString(sampleUserRequest(session)("EUR"), classOf[Request])
def sampleUserRequest(session: Session)(currency: String): Request = {
//...
data.setUserId(session("userId").as[Long])
}

Akka Http - Getting Multipart Form Data

I am creating Post Call using Akka-Http where user will fill the form and make a request.
I want to convert this form data to Scala Map[String, String]
Can any one tell how to do this.
here is the code Snippet
post {
entity(as[Multipart.FormData]) { body =>
complete { //How to process Multi Part Form data to Map
}
}
}
Thanks
Looks like you're looking for the formFieldMap directive.
(post & formFieldMap) { fields =>
doStuffWith(fields)
complete(...)
}
See the docs for more info.

How to read query parameters in akka-http?

I know akka-http libraries marshal and unmarshal to class type while processing request.But now, I need to read request-parameters of GET request. I tried parameter() method and It is returning ParamDefAux type but i need those values as strings types
I check for answer at below questions.
How can I parse out get request parameters in spray-routing?
Query parameters for GET requests using Akka HTTP (formally known as Spray)
but can't do what i need.
Please tell me how can i extract query parameters from request. OR How can I extract required value from ParamDefAux
Request URL
http://host:port/path?key=authType&value=Basic345
Get method definition
val propName = parameter("key")
val propValue = parameter("value")
complete(persistanceMgr.deleteSetting(propName,propValue))
My method declarations
def deleteSetting(name:String,value:String): Future[String] = Future{
code...
}
For a request like http://host:port/path?key=authType&value=Basic345 try
path("path") {
get {
parameters('key.as[String], 'value.as[String]) { (key, value) =>
complete {
someFunction(key,value)
}
}
}
}
Even though being less explicit in the code, you can also extract all the query parameters at once from the context. You can use as follows:
// Previous part of the Akka HTTP routes ...
extract(_.request.uri.query()) { params =>
complete {
someFunction(key,value)
}
}
If you wish extract query parameters as one piece
extract(ctx => ctx.request.uri.queryString(charset = Charset.defaultCharset)) { queryParams =>
//useyourMethod()
}

Akka HTTP set response header based on result of Future

I'm designing a REST service using Akka-HTTP 2.0-M2 and have come across a situation where I'd like to supply additional headers which are dependent upon the reply of the queried Actor.
Currently, I have the following...
val route = {
path("oncologist") {
get {
parameters('active.as[Boolean].?, 'skip.as[Int].?, 'limit.as[Int].?).as(GetAllOncologists) {
req =>
complete {
(oncologistActor ? req).mapTo[OncologistList]
}
}
}
}
While this is returning without issue. I'd like to move some of the properties of OncologistList into the response header rather than returning them in the body. Namely, I'm returning total record counts and offset and I would like to generate a previous and next URL header value for use by the client. I'm at a loss on how to proceed.
I think you can use the onComplete and respondWithHeaders directives to accomplish what you want. The onComplete directive works with the result of a Future which is exactly what ask (?) will return. Here is an example using a case class like so:
case class Foo(id:Int, name:String)
And a simple route showing onComplete like so:
get{
parameters('active.as[Boolean].?, 'skip.as[Int].?, 'limit.as[Int].?).as(GetAllOncologists) { req =>
val fut = (oncologistActor ? req).mapTo[Foo]
onComplete(fut){
case util.Success(f) =>
val headers = List(
RawHeader("X-MyObject-Id", f.id.toString),
RawHeader("X-MyObject-Name", f.name)
)
respondWithHeaders(headers){
complete(StatusCodes.OK)
}
case util.Failure(ex) =>
complete(StatusCodes.InternalServerError )
}
}
}
So if we get a successful result from the ask on oncologistActor we can then leverage the respondWithHeaders to add some custom headers to the response. Hopefully this is what you were looking for.

How can I parse out get request parameters in spray-routing?

This is what the section of code looks like
get{
respondWithMediaType(MediaTypes.`application/json`){
entity(as[HttpRequest]){
obj => complete{
println(obj)
"ok"
}
}
}
}~
I can map the request to a spray.http.HttpRequest object and I can extract the uri from this object but I imagine there is an easier way to parse out the parameters in a get request than doing it manually.
For example if my get request is
http://localhost:8080/url?id=23434&age=24
I want to be able to get id and age out of this request
Actually you can do this much much better. In routing there are two directives: parameter and parameters, I guess the difference is clear, you can also use some modifiers: ! and ?. In case of !, it means that this parameter must be provided or the request is going to be rejected and ? returns an option, so you can provide a default parameter in this case. Example:
val route: Route = {
(path("search") & get) {
parameter("q"!) { query =>
....
}
}
}
val route: Route = {
(path("search") & get) {
parameters("q"!, "filter" ? "all") { (query, filter) =>
...
}
}
}