2012 twenty-four merry days of Perl Feed

Take a little REST

adenosine - 2012-12-13

About six months ago I learned about resty. I think Stevan Little may have mentioned it in his Web::Machine talk. Unfortunately resty had problems running in zsh. I initially tried to fix the problem, but then I ported it to Perl instead, which was not only easier but also ended up having a lot of other exciting benfits.

What even is that thing?

Adenosine is a tool that allows you to fiddle with RESTful services easily. The basic gist is that you can use HTTP verbs (POST, PUT, HEAD, GET, OPTIONS, TRACE) directly in your shell. You get the body of the response as stdout, headers and more as stderr if you turn on -v, the exit code is directly related to the error code, and there's a minimal plugin architecture (with more hooks on their way.)

How do I use it?

The first thing you need to do with adenosine is to set up your environment to use it:

  $ eval $(adenosine exports)

The next thing you need to do is set the base URI. The base URI is just a URI with a * in it. So for example, why don't we start with the DuckDuckGo API. A simple, useful base URI could be set as follows:

 $ adenosine 'http://api.duckduckgo.com/?q=*&o=json'

So with that set all you need to do is:

 $ GET test | pp

The above will put test into the base URI in place of the *. pp is just a tiny json pretty printer bundled with adenosine.

If you don't specify a URI scheme (http:// or https://), your URI will be prepended with http://, and if you don't specify a * it will be appended to your URI.

GET isn't all you can do, though it's certainly what I do most often. Here's an example of how I might send a text message with our API at work:

$ adenosine 'http://our.api.com/api/2/*/sms'
$ POST myaccount '{"message":"Hello Frew!","destinations":[8675309]}' \
  -H 'Content-Type: application/json' -H 'Accept: application/json'

If you want to edit the data you are about to post, use adenosine's -V switch to open your $EDITOR.

There's more in the documentation, but that's basically how it works.

Too much to type!

Sometimes you'll want to set certain headers for a given host. For example, in my previous example I need to set the Content-Type and Accept headers so that my application will do the right thing. I actually always want to set those headers when interacting with my application. The way to do this nicely is to create a configuration file for my server. For example, I could create the following:

~/.resty/our.api.com:

POST -H 'Content-Type: application/json' -H 'Accept: application/json'
PUT -H 'Content-Type: application/json' -H 'Accept: application/json'
DELETE -H 'Content-Type: application/json' -H 'Accept: application/json'
GET -H 'Content-Type: application/json' -H 'Accept: application/json'

That will set those two headers for all four of the major HTTP verbs, so the previous example could now be merely:

  $ POST myaccount '{"message":"Hello Frew!","destinations":[8675309]}'

Plugins

One of the most exciting new features of adenosine (vs. resty) is that it supports plugins. I initially just wrote two: Stopwatch and Rainbow.

Stopwatch

Stopwatch adds timing info to the output from -v. I like to know how long various commands and requests take, especially when I am the implementor of said command. If something takes longer than 0.5s, I did a bad job. So Stopwatch gives me exactly what information I need to know. To enable it put the following in ~/.adenosinerc.yml:

plugins:
   - ::Stopwatch

Rainbow

Rainbow color codes the output from -v. I really like this, but obviously it's not for everyone. At the most basic, you can enable it the same way that you enable Stopwatch, but that just gives you the most basic color coding. Rainbow is implemented to be easily themable as well as overridable. If you just wanted to override the color of the method from the request, put the following in ~/.adenosinerc.yml:

plugins:
   - ::Rainbow: {
         request_method_color: cyan
     }

That's fine for experimentation, but I'd like to encourage everyone to make their own themes and submit them as pull requests. To make a theme, all you need to do is create a file as follows:

package App::Adenosine::Plugin::Rainbow::Halloween;

use Moo;
extends 'App::Adenosine::Plugin::Rainbow';
has '+response_header_colon_color' => (default => sub { '' });
has '+response_header_name_color' => (default => sub { 'orange1' });
has '+response_header_value_color' => (default => sub { 'orange2' });
# ...

Rainbow uses Term::ExtendedColor, so to see what colors are available run the color_matrix script that comes with it. Also note that while in the example above only a single color is specified, the foreground, backround, and even a few other (spottily supported) attributes may be set:

has '+response_header_value_color' => (
  default => sub {
     {
        fg => 'orange2',
        bg => 'cyan', # what a bad choice
        bold => 1,
        italic => 1,
        underline => 1,
     }
  }
);

Once you've done that, your ~/.adenosinerc.yml can reference your theme directly:

plugins:
   - ::Rainbow::Halloween
   - ::Stopwatch

…and that's adenosine! Please play with it and let me know if you like it!

Installing adenosine without CPAN

Most readers of this article are likely to be comfortable installing adenosine from the CPAN, but if you don't want to use CPAN, or you somehow got to this post as a non-japh, this might be more your speed:

 git clone http://github.com/frioux/app-adenosine-prefab
 source app-adenosine-prefab/adenosine-exports

See Also

Gravatar Image This article contributed by: Arthur Axel "fREW" Schmidt <frew@cpan.org>