PageRenderTime 52ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/2012/articles/2012-12-13.pod

http://github.com/rjbs/Perl-Advent
Unknown | 170 lines | 126 code | 44 blank | 0 comment | 0 complexity | 04ac7867979efed106584e89facc091d MD5 | raw file
  1. Title: Take a little REST
  2. Topic: adenosine
  3. Author: Arthur Axel "fREW" Schmidt <frew@cpan.org>
  4. About six months ago I learned about L<resty|https://github.com/micha/resty>.
  5. I think Stevan Little may have mentioned it in his L<Web::Machine> talk.
  6. Unfortunately C<resty> had problems running in C<zsh>. I initially tried to
  7. fix the problem, but then I ported it to Perl instead, which was not only
  8. easier but also ended up having a lot of other exciting benfits.
  9. =head1 L<What even is that thing?|https://www.youtube.com/watch?v=H4w0_n1Yras&t=3m29s>
  10. Adenosine is a tool that allows you to fiddle with
  11. L<RESTful|https://en.wikipedia.org/wiki/Representational_state_transfer>
  12. services easily. The basic gist is that you can use C<HTTP> verbs (C<POST>,
  13. C<PUT>, C<HEAD>, C<GET>, C<OPTIONS>, C<TRACE>) directly in your shell.
  14. You get the body of the response as stdout, headers and more as stderr if
  15. you turn on C<-v>, the exit code is directly related to the error code,
  16. and there's a minimal plugin architecture (with more hooks on their way.)
  17. =head1 How do I use it?
  18. The first thing you need to do with adenosine is to set up your environment to
  19. use it:
  20. $ eval $(adenosine exports)
  21. The next thing you need to do is set the base URI. The base URI is just a
  22. URI with a C<*> in it. So for example, why don't we start with the
  23. DuckDuckGo API. A simple, useful base URI could be set as follows:
  24. $ adenosine 'http://api.duckduckgo.com/?q=*&o=json'
  25. So with that set all you need to do is:
  26. $ GET test | pp
  27. The above will put C<test> into the base URI in place of the C<*>. L<pp>
  28. is just a tiny json pretty printer bundled with adenosine.
  29. If you don't specify a URI scheme (C<http://> or C<https://>), your URI will
  30. be prepended with C<http://>, and if you don't specify a C<*> it will be
  31. appended to your URI.
  32. C<GET> isn't all you can do, though it's certainly what I<I> do most often.
  33. Here's an example of how I might send a text message with our API at work:
  34. #!code
  35. $ adenosine 'http://our.api.com/api/2/*/sms'
  36. $ POST myaccount '{"message":"Hello Frew!","destinations":[8675309]}' \
  37. -H 'Content-Type: application/json' -H 'Accept: application/json'
  38. If you want to edit the data you are about to post, use adenosine's C<-V>
  39. switch to open your C<$EDITOR>.
  40. There's more in the L<documentation|adenosine>, but that's basically how
  41. it works.
  42. =head1 Too much to type!
  43. Sometimes you'll want to set certain headers for a given host. For example, in
  44. my previous example I need to set the C<Content-Type> and C<Accept> headers so
  45. that my application will do the right thing. I actually B<always> want to set
  46. those headers when interacting with my application. The way to do this nicely
  47. is to create a configuration file for my server. For example, I could create
  48. the following:
  49. F<~/.resty/our.api.com>:
  50. #!code
  51. POST -H 'Content-Type: application/json' -H 'Accept: application/json'
  52. PUT -H 'Content-Type: application/json' -H 'Accept: application/json'
  53. DELETE -H 'Content-Type: application/json' -H 'Accept: application/json'
  54. GET -H 'Content-Type: application/json' -H 'Accept: application/json'
  55. That will set those two headers for all four of the major HTTP verbs, so the
  56. previous example could now be merely:
  57. $ POST myaccount '{"message":"Hello Frew!","destinations":[8675309]}'
  58. =head1 Plugins
  59. One of the most exciting new features of adenosine (vs. resty) is that it
  60. supports plugins. I initially just wrote two: Stopwatch and Rainbow.
  61. =head2 C<Stopwatch>
  62. C<Stopwatch> adds timing info to the output from C<-v>. I like to know
  63. how long various commands and requests take, especially when I am the
  64. implementor of said command. If something takes longer than 0.5s, I did a
  65. bad job. So C<Stopwatch> gives me exactly what information I need to know.
  66. To enable it put the following in F<~/.adenosinerc.yml>:
  67. #!vim yaml
  68. plugins:
  69. - ::Stopwatch
  70. =head2 C<Rainbow>
  71. C<Rainbow> color codes the output from C<-v>. I really like this, but
  72. obviously it's not for everyone. At the most basic, you can enable it the
  73. same way that you enable C<Stopwatch>, but that just gives you the most
  74. basic color coding. C<Rainbow> is implemented to be easily themable as well
  75. as overridable. If you just wanted to override the color of the method from
  76. the request, put the following in F<~/.adenosinerc.yml>:
  77. #!vim yaml
  78. plugins:
  79. - ::Rainbow: {
  80. request_method_color: cyan
  81. }
  82. That's fine for experimentation, but I'd like to encourage everyone to make
  83. their own themes and submit them as pull requests. To make a theme, all you
  84. need to do is create a file as follows:
  85. #!perl
  86. package App::Adenosine::Plugin::Rainbow::Halloween;
  87. use Moo;
  88. extends 'App::Adenosine::Plugin::Rainbow';
  89. has '+response_header_colon_color' => (default => sub { '' });
  90. has '+response_header_name_color' => (default => sub { 'orange1' });
  91. has '+response_header_value_color' => (default => sub { 'orange2' });
  92. # ...
  93. C<Rainbow> uses L<Term::ExtendedColor>, so to see what colors are available
  94. run the C<color_matrix> script that comes with it. Also note that while in the
  95. example above only a single color is specified, the foreground, backround, and
  96. even a few other (spottily supported) attributes may be set:
  97. #!perl
  98. has '+response_header_value_color' => (
  99. default => sub {
  100. {
  101. fg => 'orange2',
  102. bg => 'cyan', # what a bad choice
  103. bold => 1,
  104. italic => 1,
  105. underline => 1,
  106. }
  107. }
  108. );
  109. Once you've done that, your F<~/.adenosinerc.yml> can reference your theme
  110. directly:
  111. #!vim yaml
  112. plugins:
  113. - ::Rainbow::Halloween
  114. - ::Stopwatch
  115. and that's adenosine! Please play with it and let me know if you like it!
  116. =head1 Installing C<adenosine> without CPAN
  117. Most readers of this article are likely to be comfortable installing adenosine
  118. from the CPAN, but if you don't want to use CPAN, or you somehow got to this
  119. post as a non-L<japh|http://en.wikipedia.org/wiki/Just_another_Perl_hacker>,
  120. this might be more your speed:
  121. git clone http://github.com/frioux/app-adenosine-prefab
  122. source app-adenosine-prefab/adenosine-exports
  123. =head1 See Also
  124. =for :list
  125. * L<adenosine>
  126. * L<resty|https://github.com/micha/resty>