• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>HTTP Relay ��</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="head_response_server.html" title="HEAD response (Server) ��">
10<link rel="next" href="send_child_process_output.html" title="Send Child Process Output ��">
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="head_response_server.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="send_child_process_output.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.http_relay"></a><a class="link" href="http_relay.html" title="HTTP Relay ��">HTTP Relay ��</a>
28</h3></div></div></div>
29<p>
30        An HTTP proxy acts as a relay between client and server. The proxy reads
31        a request from the client and sends it to the server, possibly adjusting
32        some of the headers and representation of the body along the way. Then, the
33        proxy reads a response from the server and sends it back to the client, also
34        with the possibility of changing the headers and body representation.
35      </p>
36<p>
37        The example that follows implements a synchronous HTTP relay. It uses a fixed
38        size buffer, to avoid reading in the entire body so that the upstream connection
39        sees a header without unnecessary latency. This example brings together all
40        of the concepts discussed so far, it uses both a <a class="link" href="../ref/boost__beast__http__serializer.html" title="http::serializer"><code class="computeroutput"><span class="identifier">serializer</span></code></a> and a <a class="link" href="../ref/boost__beast__http__parser.html" title="http::parser"><code class="computeroutput"><span class="identifier">parser</span></code></a> to achieve its goal:
41      </p>
42<pre class="programlisting"><span class="comment">/** Relay an HTTP message.
43
44    This function efficiently relays an HTTP message from a downstream
45    client to an upstream server, or from an upstream server to a
46    downstream client. After the message header is read from the input,
47    a user provided transformation function is invoked which may change
48    the contents of the header before forwarding to the output. This may
49    be used to adjust fields such as Server, or proxy fields.
50
51    @param output The stream to write to.
52
53    @param input The stream to read from.
54
55    @param buffer The buffer to use for the input.
56
57    @param transform The header transformation to apply. The function will
58    be called with this signature:
59    @code
60        template&lt;class Body&gt;
61        void transform(message&lt;
62            isRequest, Body, Fields&gt;&amp;,  // The message to transform
63            error_code&amp;);               // Set to the error, if any
64    @endcode
65
66    @param ec Set to the error if any occurred.
67
68    @tparam isRequest `true` to relay a request.
69
70    @tparam Fields The type of fields to use for the message.
71*/</span>
72<span class="keyword">template</span><span class="special">&lt;</span>
73    <span class="keyword">bool</span> <span class="identifier">isRequest</span><span class="special">,</span>
74    <span class="keyword">class</span> <span class="identifier">SyncWriteStream</span><span class="special">,</span>
75    <span class="keyword">class</span> <span class="identifier">SyncReadStream</span><span class="special">,</span>
76    <span class="keyword">class</span> <span class="identifier">DynamicBuffer</span><span class="special">,</span>
77    <span class="keyword">class</span> <span class="identifier">Transform</span><span class="special">&gt;</span>
78<span class="keyword">void</span>
79<span class="identifier">relay</span><span class="special">(</span>
80    <span class="identifier">SyncWriteStream</span><span class="special">&amp;</span> <span class="identifier">output</span><span class="special">,</span>
81    <span class="identifier">SyncReadStream</span><span class="special">&amp;</span> <span class="identifier">input</span><span class="special">,</span>
82    <span class="identifier">DynamicBuffer</span><span class="special">&amp;</span> <span class="identifier">buffer</span><span class="special">,</span>
83    <span class="identifier">error_code</span><span class="special">&amp;</span> <span class="identifier">ec</span><span class="special">,</span>
84    <span class="identifier">Transform</span><span class="special">&amp;&amp;</span> <span class="identifier">transform</span><span class="special">)</span>
85<span class="special">{</span>
86    <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>
87        <span class="string">"SyncWriteStream requirements not met"</span><span class="special">);</span>
88
89    <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>
90        <span class="string">"SyncReadStream requirements not met"</span><span class="special">);</span>
91
92    <span class="comment">// A small buffer for relaying the body piece by piece</span>
93    <span class="keyword">char</span> <span class="identifier">buf</span><span class="special">[</span><span class="number">2048</span><span class="special">];</span>
94
95    <span class="comment">// Create a parser with a buffer body to read from the input.</span>
96    <span class="identifier">parser</span><span class="special">&lt;</span><span class="identifier">isRequest</span><span class="special">,</span> <span class="identifier">buffer_body</span><span class="special">&gt;</span> <span class="identifier">p</span><span class="special">;</span>
97
98    <span class="comment">// Create a serializer from the message contained in the parser.</span>
99    <span class="identifier">serializer</span><span class="special">&lt;</span><span class="identifier">isRequest</span><span class="special">,</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">p</span><span class="special">.</span><span class="identifier">get</span><span class="special">()};</span>
100
101    <span class="comment">// Read just the header from the input</span>
102    <span class="identifier">read_header</span><span class="special">(</span><span class="identifier">input</span><span class="special">,</span> <span class="identifier">buffer</span><span class="special">,</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">);</span>
103    <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
104        <span class="keyword">return</span><span class="special">;</span>
105
106    <span class="comment">// Apply the caller's header transformation</span>
107    <span class="identifier">transform</span><span class="special">(</span><span class="identifier">p</span><span class="special">.</span><span class="identifier">get</span><span class="special">(),</span> <span class="identifier">ec</span><span class="special">);</span>
108    <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
109        <span class="keyword">return</span><span class="special">;</span>
110
111    <span class="comment">// Send the transformed message to the output</span>
112    <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>
113    <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
114        <span class="keyword">return</span><span class="special">;</span>
115
116    <span class="comment">// Loop over the input and transfer it to the output</span>
117    <span class="keyword">do</span>
118    <span class="special">{</span>
119        <span class="keyword">if</span><span class="special">(!</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">is_done</span><span class="special">())</span>
120        <span class="special">{</span>
121            <span class="comment">// Set up the body for writing into our small buffer</span>
122            <span class="identifier">p</span><span class="special">.</span><span class="identifier">get</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">buf</span><span class="special">;</span>
123            <span class="identifier">p</span><span class="special">.</span><span class="identifier">get</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="keyword">sizeof</span><span class="special">(</span><span class="identifier">buf</span><span class="special">);</span>
124
125            <span class="comment">// Read as much as we can</span>
126            <span class="identifier">read</span><span class="special">(</span><span class="identifier">input</span><span class="special">,</span> <span class="identifier">buffer</span><span class="special">,</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">);</span>
127
128            <span class="comment">// This error is returned when buffer_body uses up the buffer</span>
129            <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>
130                <span class="identifier">ec</span> <span class="special">=</span> <span class="special">{};</span>
131            <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
132                <span class="keyword">return</span><span class="special">;</span>
133
134            <span class="comment">// Set up the body for reading.</span>
135            <span class="comment">// This is how much was parsed:</span>
136            <span class="identifier">p</span><span class="special">.</span><span class="identifier">get</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="keyword">sizeof</span><span class="special">(</span><span class="identifier">buf</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">get</span><span class="special">().</span><span class="identifier">body</span><span class="special">().</span><span class="identifier">size</span><span class="special">;</span>
137            <span class="identifier">p</span><span class="special">.</span><span class="identifier">get</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">buf</span><span class="special">;</span>
138            <span class="identifier">p</span><span class="special">.</span><span class="identifier">get</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="special">!</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">is_done</span><span class="special">();</span>
139        <span class="special">}</span>
140        <span class="keyword">else</span>
141        <span class="special">{</span>
142            <span class="identifier">p</span><span class="special">.</span><span class="identifier">get</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>
143            <span class="identifier">p</span><span class="special">.</span><span class="identifier">get</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="number">0</span><span class="special">;</span>
144        <span class="special">}</span>
145
146        <span class="comment">// Write everything in the buffer (which might be empty)</span>
147        <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>
148
149        <span class="comment">// This error is returned when buffer_body uses up the buffer</span>
150        <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>
151            <span class="identifier">ec</span> <span class="special">=</span> <span class="special">{};</span>
152        <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
153            <span class="keyword">return</span><span class="special">;</span>
154    <span class="special">}</span>
155    <span class="keyword">while</span><span class="special">(!</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">is_done</span><span class="special">()</span> <span class="special">&amp;&amp;</span> <span class="special">!</span> <span class="identifier">sr</span><span class="special">.</span><span class="identifier">is_done</span><span class="special">());</span>
156<span class="special">}</span>
157</pre>
158</div>
159<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
160<td align="left"></td>
161<td align="right"><div class="copyright-footer">Copyright © 2016-2019 Vinnie
162      Falco<p>
163        Distributed under the Boost Software License, Version 1.0. (See accompanying
164        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>)
165      </p>
166</div></td>
167</tr></table>
168<hr>
169<div class="spirit-nav">
170<a accesskey="p" href="head_response_server.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="send_child_process_output.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
171</div>
172</body>
173</html>
174