2

I just started working with Yaws to try to create some simple RESTful web services, however I ran into an unexpected issue: I can't seem to access my data when I do a PUT request. When I try to use the yaws_api:parse_post function, I get the following error:

ERROR: Can't parse post body for 'PUT' requests: URL: ...

I wrote out the entire request and everything looks identical, so I'm very confused. Am I doing something wrong? GETs and POSTs work properly. In fact, the only difference between how I handle POSTs and PUTs right now is just what I display for each as right now I'm just writing test code to show success.

Thanks in advance.

blockcipher
  • 2,144
  • 4
  • 22
  • 35

3 Answers3

2

I also find it weird that there's no equivalent of parse_post/1 for non-POST HTTP methods in the Yaws API.

In any case, I simply use parse_query/1 for PUTs. Given a PUT request with param1=abc, param2=def:

index(Args) ->
  case yaws_arg:method(Args) of
  'PUT' ->
    Parsed = yaws_api:parse_query(Args),
    io:format("PUT PARAMS=~p", [Parsed]),
    ....
  'POST' ->
    ....

the output is:

PUT PARAMS=[{"param1","abc"}, {"param2","def"}}]

(The above example is in a Erlyweb controller.)

ettore
  • 678
  • 12
  • 20
  • 1
    I don't think it's weird that `PUT` has no associated parsing method, since [RFC2616](http://www.w3.org/Protocols/rfc2616/rfc2616.html) defines `PUT` as a full resource replacement. This means the request body can have a much broader range of media types than `POST`, making supplying such a parser next to impossible. Technically a `POST` body can also be just as varied, but it's more likely in practice that a `POST` will have data of the `application/x-www-form-urlencoded` media type due to the use of web forms. – Steve Vinoski Apr 18 '11 at 00:52
  • Steve, I'm pretty sure you know RFC2616 better than me, but it looks like a PUT mainly identifies the entity enclosed with the request, therefore making it more specific than a POST. However, per RFC2616, POSTs and PUTs have the same range of media types and so, strictly speaking, `yaws_api:parse_post()` could fail, throwing parsing errors (that we need to handle). So why not having a `yaws_api:parse_put()` method that works and errors out somewhat similarly? In my practical experience, the majority of PUT requests had application/x-www-form-urlencoded data, just like POST requests. – ettore Dec 28 '11 at 19:39
2

You should add (or change) the parameter "dav = true" in the file "yaws.conf" into the section <server> like this:

<server ...>
        dav = true
</server>
1

The data for PUT is located in #arg.clidata, like it is for a POST. Internally the call to parse_query and parse_post ultimately use the same function to parse GET and POST.

A work around for PUT parameters in the body is therefore

Parsed = yaws_api:parse_query( Arg#arg{ querydata = Arg#arg.clidata } ),

It works by copying the clidata field (data in the body) to the querydata field and parsing it like a GET.

This assumes that the body is urlencoded like for a POST.

DeepFreez
  • 91
  • 4