• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Send Child Process Output ��</title>
5<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="../../index.html" title="Chapter 1. Boost.Beast">
8<link rel="up" href="../more_examples.html" title="HTTP Examples">
9<link rel="prev" href="http_relay.html" title="HTTP Relay ��">
10<link rel="next" href="../using_websocket.html" title="WebSocket">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%"><tr>
14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
15<td align="center"><a href="../../../../../../index.html">Home</a></td>
16<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
19<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
20</tr></table>
21<hr>
22<div class="spirit-nav">
23<a accesskey="p" href="http_relay.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../more_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../using_websocket.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
24</div>
25<div class="section">
26<div class="titlepage"><div><div><h3 class="title">
27<a name="beast.more_examples.send_child_process_output"></a><a class="link" href="send_child_process_output.html" title="Send Child Process Output ��">Send Child
28      Process Output ��</a>
29</h3></div></div></div>
30<p>
31        Sometimes it is necessary to send a message whose body is not conveniently
32        described by a single container. For example, when implementing an HTTP relay
33        function a robust implementation needs to present body buffers individually
34        as they become available from the downstream host. These buffers should be
35        fixed in size, otherwise creating the unnecessary and inefficient burden
36        of reading the complete message body before forwarding it to the upstream
37        host.
38      </p>
39<p>
40        To enable these use-cases, the body type <a class="link" href="../ref/boost__beast__http__buffer_body.html" title="http::buffer_body"><code class="computeroutput"><span class="identifier">buffer_body</span></code></a> is provided. This body
41        uses a caller-provided pointer and size instead of an owned container. To
42        use this body, instantiate an instance of the serializer and fill in the
43        pointer and size fields before calling a stream write function.
44      </p>
45<p>
46        This example reads from a child process and sends the output back in an HTTP
47        response. The output of the process is sent as it becomes available:
48      </p>
49<pre class="programlisting"><span class="comment">/** Send the output of a child process as an HTTP response.
50
51    The output of the child process comes from a @b SyncReadStream. Data
52    will be sent continuously as it is produced, without the requirement
53    that the entire process output is buffered before being sent. The
54    response will use the chunked transfer encoding.
55
56    @param input A stream to read the child process output from.
57
58    @param output A stream to write the HTTP response to.
59
60    @param ec Set to the error, if any occurred.
61*/</span>
62<span class="keyword">template</span><span class="special">&lt;</span>
63    <span class="keyword">class</span> <span class="identifier">SyncReadStream</span><span class="special">,</span>
64    <span class="keyword">class</span> <span class="identifier">SyncWriteStream</span><span class="special">&gt;</span>
65<span class="keyword">void</span>
66<span class="identifier">send_cgi_response</span><span class="special">(</span>
67    <span class="identifier">SyncReadStream</span><span class="special">&amp;</span> <span class="identifier">input</span><span class="special">,</span>
68    <span class="identifier">SyncWriteStream</span><span class="special">&amp;</span> <span class="identifier">output</span><span class="special">,</span>
69    <span class="identifier">error_code</span><span class="special">&amp;</span> <span class="identifier">ec</span><span class="special">)</span>
70<span class="special">{</span>
71    <span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_sync_read_stream</span><span class="special">&lt;</span><span class="identifier">SyncReadStream</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">,</span>
72        <span class="string">"SyncReadStream requirements not met"</span><span class="special">);</span>
73
74    <span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">is_sync_write_stream</span><span class="special">&lt;</span><span class="identifier">SyncWriteStream</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">,</span>
75        <span class="string">"SyncWriteStream requirements not met"</span><span class="special">);</span>
76
77    <span class="comment">// Set up the response. We use the buffer_body type,</span>
78    <span class="comment">// allowing serialization to use manually provided buffers.</span>
79    <span class="identifier">response</span><span class="special">&lt;</span><span class="identifier">buffer_body</span><span class="special">&gt;</span> <span class="identifier">res</span><span class="special">;</span>
80
81    <span class="identifier">res</span><span class="special">.</span><span class="identifier">result</span><span class="special">(</span><span class="identifier">status</span><span class="special">::</span><span class="identifier">ok</span><span class="special">);</span>
82    <span class="identifier">res</span><span class="special">.</span><span class="identifier">version</span><span class="special">(</span><span class="number">11</span><span class="special">);</span>
83    <span class="identifier">res</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="identifier">field</span><span class="special">::</span><span class="identifier">server</span><span class="special">,</span> <span class="string">"Beast"</span><span class="special">);</span>
84    <span class="identifier">res</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="identifier">field</span><span class="special">::</span><span class="identifier">transfer_encoding</span><span class="special">,</span> <span class="string">"chunked"</span><span class="special">);</span>
85
86    <span class="comment">// No data yet, but we set more = true to indicate</span>
87    <span class="comment">// that it might be coming later. Otherwise the</span>
88    <span class="comment">// serializer::is_done would return true right after</span>
89    <span class="comment">// sending the header.</span>
90    <span class="identifier">res</span><span class="special">.</span><span class="identifier">body</span><span class="special">().</span><span class="identifier">data</span> <span class="special">=</span> <span class="keyword">nullptr</span><span class="special">;</span>
91    <span class="identifier">res</span><span class="special">.</span><span class="identifier">body</span><span class="special">().</span><span class="identifier">more</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
92
93    <span class="comment">// Create the serializer.</span>
94    <span class="identifier">response_serializer</span><span class="special">&lt;</span><span class="identifier">buffer_body</span><span class="special">,</span> <span class="identifier">fields</span><span class="special">&gt;</span> <span class="identifier">sr</span><span class="special">{</span><span class="identifier">res</span><span class="special">};</span>
95
96    <span class="comment">// Send the header immediately.</span>
97    <span class="identifier">write_header</span><span class="special">(</span><span class="identifier">output</span><span class="special">,</span> <span class="identifier">sr</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">);</span>
98    <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
99        <span class="keyword">return</span><span class="special">;</span>
100
101    <span class="comment">// Alternate between reading from the child process</span>
102    <span class="comment">// and sending all the process output until there</span>
103    <span class="comment">// is no more output.</span>
104    <span class="keyword">do</span>
105    <span class="special">{</span>
106        <span class="comment">// Read a buffer from the child process</span>
107        <span class="keyword">char</span> <span class="identifier">buffer</span><span class="special">[</span><span class="number">2048</span><span class="special">];</span>
108        <span class="keyword">auto</span> <span class="identifier">bytes_transferred</span> <span class="special">=</span> <span class="identifier">input</span><span class="special">.</span><span class="identifier">read_some</span><span class="special">(</span>
109            <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">,</span> <span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">)),</span> <span class="identifier">ec</span><span class="special">);</span>
110        <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">error</span><span class="special">::</span><span class="identifier">eof</span><span class="special">)</span>
111        <span class="special">{</span>
112            <span class="identifier">ec</span> <span class="special">=</span> <span class="special">{};</span>
113
114            <span class="comment">// `nullptr` indicates there is no buffer</span>
115            <span class="identifier">res</span><span class="special">.</span><span class="identifier">body</span><span class="special">().</span><span class="identifier">data</span> <span class="special">=</span> <span class="keyword">nullptr</span><span class="special">;</span>
116
117            <span class="comment">// `false` means no more data is coming</span>
118            <span class="identifier">res</span><span class="special">.</span><span class="identifier">body</span><span class="special">().</span><span class="identifier">more</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span>
119        <span class="special">}</span>
120        <span class="keyword">else</span>
121        <span class="special">{</span>
122            <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
123                <span class="keyword">return</span><span class="special">;</span>
124
125            <span class="comment">// Point to our buffer with the bytes that</span>
126            <span class="comment">// we received, and indicate that there may</span>
127            <span class="comment">// be some more data coming</span>
128            <span class="identifier">res</span><span class="special">.</span><span class="identifier">body</span><span class="special">().</span><span class="identifier">data</span> <span class="special">=</span> <span class="identifier">buffer</span><span class="special">;</span>
129            <span class="identifier">res</span><span class="special">.</span><span class="identifier">body</span><span class="special">().</span><span class="identifier">size</span> <span class="special">=</span> <span class="identifier">bytes_transferred</span><span class="special">;</span>
130            <span class="identifier">res</span><span class="special">.</span><span class="identifier">body</span><span class="special">().</span><span class="identifier">more</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
131        <span class="special">}</span>
132
133        <span class="comment">// Write everything in the body buffer</span>
134        <span class="identifier">write</span><span class="special">(</span><span class="identifier">output</span><span class="special">,</span> <span class="identifier">sr</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">);</span>
135
136        <span class="comment">// This error is returned by body_buffer during</span>
137        <span class="comment">// serialization when it is done sending the data</span>
138        <span class="comment">// provided and needs another buffer.</span>
139        <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span> <span class="special">==</span> <span class="identifier">error</span><span class="special">::</span><span class="identifier">need_buffer</span><span class="special">)</span>
140        <span class="special">{</span>
141            <span class="identifier">ec</span> <span class="special">=</span> <span class="special">{};</span>
142            <span class="keyword">continue</span><span class="special">;</span>
143        <span class="special">}</span>
144        <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
145            <span class="keyword">return</span><span class="special">;</span>
146    <span class="special">}</span>
147    <span class="keyword">while</span><span class="special">(!</span> <span class="identifier">sr</span><span class="special">.</span><span class="identifier">is_done</span><span class="special">());</span>
148<span class="special">}</span>
149</pre>
150</div>
151<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
152<td align="left"></td>
153<td align="right"><div class="copyright-footer">Copyright © 2016-2019 Vinnie
154      Falco<p>
155        Distributed under the Boost Software License, Version 1.0. (See accompanying
156        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
157      </p>
158</div></td>
159</tr></table>
160<hr>
161<div class="spirit-nav">
162<a accesskey="p" href="http_relay.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../more_examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../using_websocket.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
163</div>
164</body>
165</html>
166