Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Playframework handling post request

In my routes:

POST        /forms/FormValidator1/validateForm                       controllers.FormValidator1.validateForm(jsonForm:String)

There is a controller method defined for that route:

def validateForm(jsonForm:String) = Action { ...

Then I try to send POST request by chrome POSTMAN plugin (see pic above).

I use:

url: http://localhost:9000/forms/FormValidator1/validateForm
headers: Content Type: application/json
json data: {name: "me", surname: "my"}

So, sending this POST request I can not reach controller's method by mentioned route / url. Why?

UPDATE:

Interestly enough: after I got it working on my laptop (see my answer below) then push it on gitHub and pull it to another machine it starts working differently. Now it complains than Bad Request is [Invalid XML] nevertheless I use "application/json" header and did not change any line of code after commit. I wonder maybe it is a bug.

enter image description here

like image 624
ses Avatar asked Oct 21 '22 20:10

ses


1 Answers

It seems I got it.

Here: https://groups.google.com/forum/#!topic/play-framework/XH3ulCys_co

And here: https://groups.google.com/forum/#!msg/play-framework/M97vBcvvL58/216pTqm22HcJ

There is wrong and correct way explained:

Doesn't work: curl -d "name=sam" http://localhost:9000/test
Works: curl -d "" http://localhost:9000/test?name=sam

This is the way how POST params are passing..in play. (second link is explanation WHY):

Sometimes you have to make compromises. In Play 1 you could bind your action parameters from any parameter extracted from the URL path, query string or even the request body. It was highly productive but you had no way to control the way the form was uploaded. I mean, if a user uploads a big file you needed to load the entire request in memory to be able to handle it.

In Play 2 you can control the request body submission. You can reject it early if something is wrong with the user, you can process big files or streams without filling your memory with more than one HTTP chunk… You gain a high control of what happens and it can help you to scale you service. But, the other side of the coin is that when a request is routed, Play 2 only uses the request header to make its decision: the request body is not available yet, hence the inability to directly bind an action parameter from a parameter extracted from the request body.

UPDATE: Interestly enough: after I got it working on my laptop then push it on gitHub and pull it to another machine it starts working differently. Now it complains than Bad Request is [Invalid XML] nevertheless I use "application/json" header and did not change any line of code after commit.

UPDATE 2

So I fixed it like this:

On angular side (we even can comment dataType and headers):

  var data =  $scope.fields

            $http({
                url: '/forms/FormValidator1/validateForm',
                method: "POST",
                //dataType: "json",
                data: data,
                //headers: {'Content-Type': 'application/json'}
            }).success(function (data, status, headers, config) {
                    console.log("good")
            }).error(function (data, status, headers, config) {
                    console.log("something wrong")
            });

On playFramework side: (use BodyParser)

 def validateForm = Action { request =>


    val body: AnyContent = request.body
    val jsonBody: Option[JsValue] = body.asJson

      // Expecting text body
      jsonBody.map { jsValue =>

            val name = (jsValue \ "name")
            val surname = (jsValue \ "surname")
    ....
    }

Routes (don't define parameters at all !):

 POST       /forms/FormValidator1/validateForm             controllers.FormValidator1.validateForm
like image 52
ses Avatar answered Oct 24 '22 18:10

ses