I was in need of a break last night after flailing in the face of a new library-language-build-system for a few hours. So, I decided to hack some Webmachine (it was too late to sit down at the trap set).
I was thinking about how the os-environment resource from my last post could be extended. This post begins a four-part series in which new capabilities are added to env_resource.erl.
PUT
Let's start with modification. Why not allow setting those variables?
I need to do three things: announce that the resource supports PUT, list what types of data it accepts, and then actually handle decoding the incoming data. Fifteen quick lines of code should handle it:
-export([allowed_methods/2, content_types_accepted/2, from_json/2]).
allowed_methods(RD, Ctx) ->
{['GET', 'HEAD', 'PUT'], RD, Ctx}.
content_types_accepted(RD, Ctx) ->
{[{"application/json", from_json}], RD, Ctx}.
from_json(RD, Ctx) ->
case wrq:path_info(env, RD) of
undefined ->
{struct, MJ} = mochijson:decode(wrq:req_body(RD)),
[ os:putenv(K, V) || {K, V} <- MJ ];
Env ->
MJ = mochijson:decode(wrq:req_body(RD)),
os:putenv(Env, MJ)
end,
{true, RD, Ctx}.
Arbitrary decisions were made above:
- Clients shall send JSON-encoded data. I could have just as easily added another element to the return value of content_types_accepted/2 and written another method to handle it (e.g. {"text/plain", from_text} and from_text/2). Accepting JSON is nice, since it makes PUT and GET simply symmetric.
- /_env expects a JSON structure, while /_env/VARIABLE expects a string. Again with the simple symmetry between PUT and GET.
- /_env only modifies or creates the variables described in the JSON structure it receives. Alternatively, it could have cleared out any unnamed environment variables, but this seemed unnecessary.
- No body is returned in a successful response. It would have been fairly simple to generate the same body that would have been returned in a GET, then use wrq:append_to_response_body/2 to return a modified RD, but this also seemed unnecessary.
I can now set MY_VAR to "hello", using two different curl commands:
$ curl -X PUT -H "Content-type: application/json" \
http://localhost:8000/_env -d "{\"MY_VAR\":\"hello\"}"
$ curl -X PUT -H "Content-type: application/json" \
http://localhost:8000/_env/MY_VAR -d "\"hello\""
Come back tomorrow for part two, in which I'll add authorization via username and password.
Update: part two is up.
Categories: Development Erlang Webmachine
Post Copyright © 2009 Bryan Fink