File size: 1,900 Bytes
90f0300
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import {
  DEFAULT_RELAY_STREAM_CHUNK_BYTES,
  filterResponseHeaders
} from '../server/relay-protocol.js';
import { MAX_BODY_BYTES } from './relay-mac-client-config.mjs';
import { encodeResponseBody } from './relay-mac-client-body.mjs';

export function createHttpResponseSender({
  sendRelayMessage,
  waitForRelayBackpressure
}) {
  async function sendBuffered(requestId, response) {
    const encoded = await encodeResponseBody(response, { maxBodyBytes: MAX_BODY_BYTES });
    if (encoded.type === 'http.error') {
      sendRelayMessage({ ...encoded, requestId });
      return;
    }
    sendRelayMessage({
      type: 'http.response',
      requestId,
      status: response.status,
      headers: filterResponseHeaders(response.headers),
      ...encoded
    });
  }

  async function sendStreaming(requestId, response) {
    sendRelayMessage({
      type: 'http.response.start',
      requestId,
      status: response.status,
      headers: filterResponseHeaders(response.headers)
    });
    let sequence = 0;
    let totalBytes = 0;
    if (response.body) {
      for await (const chunk of response.body) {
        const buffer = Buffer.from(chunk);
        for (let offset = 0; offset < buffer.length; offset += DEFAULT_RELAY_STREAM_CHUNK_BYTES) {
          const slice = buffer.subarray(offset, offset + DEFAULT_RELAY_STREAM_CHUNK_BYTES);
          sequence += 1;
          totalBytes += slice.length;
          sendRelayMessage({
            type: 'http.response.chunk',
            requestId,
            sequence,
            encoding: 'base64',
            data: slice.toString('base64'),
            bytes: slice.length
          });
          await waitForRelayBackpressure();
        }
      }
    }
    sendRelayMessage({
      type: 'http.response.end',
      requestId,
      chunks: sequence,
      totalBytes
    });
  }

  return {
    sendBuffered,
    sendStreaming
  };
}