PageRenderTime 25ms CodeModel.GetById 13ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/deps/webmachine/www/streambody.html

https://code.google.com/p/zotonic/
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
 22<p>
 23
 24Webmachine allows the resource developer to handle request and
 25response bodies as either whole units (binary or iolist) to be handed
 26around at once, or else to choose to "stream" the body.
 27
 28</p>
 29<p>
 30
 31The body-handling functions are:
 32
 33</p>
 34
 35<ul><li><code> wrq:req_body/1 </code>
 36</li><li><code> wrq:stream_req_body/2 </code>
 37</li><li><code> wrq:set_resp_body/2 </code>
 38</li></ul>
 39
 40<p>
 41
 42The last of these, <code>wrq:set_resp_body/2</code>, is also called
 43implicitly with the return value of any content-producing function
 44such as <code>to_html/2</code>.
 45
 46</p>
 47<p>
 48
 49The first of these (<code>req_body</code>) is the simplest.  It will
 50provide the whole incoming request body as a binary.  (Unless the body
 51is too large, as set by <code>wrq:set_max_recv_body/2</code> or
 52defaulting to 50M) For the majority of resources, this is the easiest
 53way to handle the incoming request body.
 54
 55</p>
 56<p>
 57
 58If a resource wants to handle the incoming request body a hunk at a
 59time, it may call <code>wrq:stream_req_body/2</code> instead.  Instead
 60of a binary, this produces a <code>StreamBody</code> structure.
 61
 62</p>
 63<p>
 64
 65(It is an error to call both <code>wrq:req_body/1</code> and
 66<code>wrq:stream_req_body/2</code> in the execution of a single
 67resource.)
 68
 69</p>
 70<p>
 71
 72A <code>StreamBody</code> is a pair of the form
 73<code>{Data,Next}</code> where <code>Data</code> is a binary and
 74<code>Next</code> is either the atom <code>done</code> signifying the
 75end of the body or else a 0-arity function that, when called, will
 76produce the "next" <code>StreamBody</code> structure.
 77
 78</p>
 79<p>
 80
 81The integer parameter to <code>wrq:stream_req_body/2</code> indicates
 82the maximum size in bytes of any <code>Hunk</code> from the resulting
 83<code>StreamBody</code>.
 84
 85</p>
 86<p>
 87
 88When a resource provides a body to be sent in the response, it should
 89use <code>wrq:set_resp_body/2</code>.  The parameter to this function
 90may be either an iolist, representing the entire body, or else a pair
 91of the form <code>{stream, StreamBody}</code>.
 92
 93</p>
 94<p>
 95
 96An example may make the usage of this API clearer.  A complete and
 97working resource module using this API in both directions:
 98
 99</p>
100<p>
101
102<pre>
103-module(mywebdemo_resource).
104-export([init/1, allowed_methods/2, process_post/2]).
105
106-include_lib("webmachine/include/webmachine.hrl").
107
108init([]) -> {ok, undefined}.
109
110allowed_methods(ReqData, State) -> {['POST'], ReqData, State}.
111
112process_post(ReqData, State) ->
113    Body = get_streamed_body(wrq:stream_req_body(ReqData, 3), []),
114    {true, wrq:set_resp_body({stream, send_streamed_body(Body,4)},ReqData), State}.
115
116send_streamed_body(Body, Max) ->
117    HunkLen=8*Max,
118    case Body of        
119        <<A:HunkLen,Rest/binary>> ->
120            io:format("SENT ~p~n",[<<A:HunkLen>>]),
121            {<<A:HunkLen>>, fun() -> send_streamed_body(Rest,Max) end};
122        _ ->
123            io:format("SENT ~p~n",[Body]),
124            {Body, done}
125    end.
126
127get_streamed_body({Hunk,done},Acc) ->
128    io:format("RECEIVED ~p~n",[Hunk]),
129    iolist_to_binary(lists:reverse([Hunk|Acc]));
130get_streamed_body({Hunk,Next},Acc) ->
131    io:format("RECEIVED ~p~n",[Hunk]),
132    get_streamed_body(Next(),[Hunk|Acc]).
133</pre>
134
135</p>
136<p>
137
138If you use this resource in place of the file
139<code>/tmp/mywebdemo/src/mywebdemo_resource.erl</code> in the
140<a href="quickstart.html">quickstart</a> setup, you should then be able
141to issue <code>curl -d '1234567890' http://127.0.0.1:8000/</code> on
142the command line and the <code>io:format</code> calls will show you
143what is going on.
144
145</p>
146<p>
147
148Obviously, a realistic resource wouldn't use this API just to collect
149the whole binary into memory or break one up that is already present
150-- you'd use <code>req_body</code> and put a simple iolist into
151<code>set_resp_body</code> instead.  Also, the choices of 3 and 4
152bytes as hunk size are far from optimal for most reasonable uses.
153This resource is intended only as a demonstration of the API, not as a
154real-world use of streaming request/response bodies.
155
156</p>
157
158		</div>
159		<div id="footer">
160
161		</div>
162	</div>
163
164<script type="text/javascript">
165var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
166document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
167</script>
168<script type="text/javascript">
169try {
170var pageTracker = _gat._getTracker("UA-4979965-5");
171pageTracker._trackPageview();
172} catch(err) {}</script>
173
174</body>
175</html>
176