PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/www/streambody.html

https://github.com/KodiEhf/webmachine
HTML | 176 lines | 136 code | 40 blank | 0 comment | 0 complexity | 9fbbed564eea4a65e20815102f54ceb8 MD5 | raw file
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta name="author" content="Basho Technologies" />
  5. <meta name="description" content="Webmachine streamed bodies" />
  6. <meta name="keywords" content="webmachine http rest web" />
  7. <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  8. <link rel="stylesheet" href="css/style-1c.css" type="text/css" />
  9. <title>Webmachine streamed bodies</title>
  10. </head>
  11. <body>
  12. <div id="content">
  13. <h1><span class="hr"></span><a href="/">webmachine</a></h1>
  14. <ul id="top">
  15. <li><a href="/">Home</a></li>
  16. <li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
  17. <li><a href="contact.html">Contact</a></li>
  18. </ul>
  19. <div id="left">
  20. <h3>Webmachine streamed bodies</h3>
  21. <p>
  22. Webmachine allows the resource developer to handle request and
  23. response bodies as either whole units (binary or iolist) to be handed
  24. around at once, or else to choose to "stream" the body.
  25. </p>
  26. <p>
  27. The body-handling functions are:
  28. </p>
  29. <ul><li><code> wrq:req_body/1 </code>
  30. </li><li><code> wrq:stream_req_body/2 </code>
  31. </li><li><code> wrq:set_resp_body/2 </code>
  32. </li></ul>
  33. <p>
  34. The last of these, <code>wrq:set_resp_body/2</code>, is also called
  35. implicitly with the return value of any content-producing function
  36. such as <code>to_html/2</code>.
  37. </p>
  38. <p>
  39. The first of these (<code>req_body</code>) is the simplest. It will
  40. provide the whole incoming request body as a binary. (Unless the body
  41. is too large, as set by <code>wrq:set_max_recv_body/2</code> or
  42. defaulting to 50M) For the majority of resources, this is the easiest
  43. way to handle the incoming request body.
  44. </p>
  45. <p>
  46. If a resource wants to handle the incoming request body a hunk at a
  47. time, it may call <code>wrq:stream_req_body/2</code> instead. Instead
  48. of a binary, this produces a <code>StreamBody</code> structure.
  49. </p>
  50. <p>
  51. (It is an error to call both <code>wrq:req_body/1</code> and
  52. <code>wrq:stream_req_body/2</code> in the execution of a single
  53. resource.)
  54. </p>
  55. <p>
  56. A <code>StreamBody</code> is a pair of the form
  57. <code>{Data,Next}</code> where <code>Data</code> is a binary and
  58. <code>Next</code> is either the atom <code>done</code> signifying the
  59. end of the body or else a 0-arity function that, when called, will
  60. produce the "next" <code>StreamBody</code> structure.
  61. </p>
  62. <p>
  63. The integer parameter to <code>wrq:stream_req_body/2</code> indicates
  64. the maximum size in bytes of any <code>Hunk</code> from the resulting
  65. <code>StreamBody</code>.
  66. </p>
  67. <p>
  68. When a resource provides a body to be sent in the response, it should
  69. use <code>wrq:set_resp_body/2</code>. The parameter to this function
  70. may be either an iolist, representing the entire body, or else a pair
  71. of the form <code>{stream, StreamBody}</code>.
  72. </p>
  73. <p>
  74. An example may make the usage of this API clearer. A complete and
  75. working resource module using this API in both directions:
  76. </p>
  77. <p>
  78. <pre>
  79. -module(mywebdemo_resource).
  80. -export([init/1, allowed_methods/2, process_post/2]).
  81. -include_lib("webmachine/include/webmachine.hrl").
  82. init([]) -> {ok, undefined}.
  83. allowed_methods(ReqData, State) -> {['POST'], ReqData, State}.
  84. process_post(ReqData, State) ->
  85. Body = get_streamed_body(wrq:stream_req_body(ReqData, 3), []),
  86. {true, wrq:set_resp_body({stream, send_streamed_body(Body,4)},ReqData), State}.
  87. send_streamed_body(Body, Max) ->
  88. HunkLen=8*Max,
  89. case Body of
  90. <<A:HunkLen,Rest/binary>> ->
  91. io:format("SENT ~p~n",[<<A:HunkLen>>]),
  92. {<<A:HunkLen>>, fun() -> send_streamed_body(Rest,Max) end};
  93. _ ->
  94. io:format("SENT ~p~n",[Body]),
  95. {Body, done}
  96. end.
  97. get_streamed_body({Hunk,done},Acc) ->
  98. io:format("RECEIVED ~p~n",[Hunk]),
  99. iolist_to_binary(lists:reverse([Hunk|Acc]));
  100. get_streamed_body({Hunk,Next},Acc) ->
  101. io:format("RECEIVED ~p~n",[Hunk]),
  102. get_streamed_body(Next(),[Hunk|Acc]).
  103. </pre>
  104. </p>
  105. <p>
  106. If you use this resource in place of the file
  107. <code>/tmp/mywebdemo/src/mywebdemo_resource.erl</code> in the
  108. <a href="quickstart.html">quickstart</a> setup, you should then be able
  109. to issue <code>curl -d '1234567890' http://127.0.0.1:8000/</code> on
  110. the command line and the <code>io:format</code> calls will show you
  111. what is going on.
  112. </p>
  113. <p>
  114. Obviously, a realistic resource wouldn't use this API just to collect
  115. the whole binary into memory or break one up that is already present
  116. -- you'd use <code>req_body</code> and put a simple iolist into
  117. <code>set_resp_body</code> instead. Also, the choices of 3 and 4
  118. bytes as hunk size are far from optimal for most reasonable uses.
  119. This resource is intended only as a demonstration of the API, not as a
  120. real-world use of streaming request/response bodies.
  121. </p>
  122. </div>
  123. <div id="footer">
  124. </div>
  125. </div>
  126. <script type="text/javascript">
  127. var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
  128. document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
  129. </script>
  130. <script type="text/javascript">
  131. try {
  132. var pageTracker = _gat._getTracker("UA-4979965-5");
  133. pageTracker._trackPageview();
  134. } catch(err) {}</script>
  135. </body>
  136. </html>