SyncHttpClientResponse constructor

SyncHttpClientResponse(
  1. RawSynchronousSocket socket
)

Creates an instance of SyncHttpClientResponse that contains the response sent by the HTTP server over socket.

Implementation

factory SyncHttpClientResponse(RawSynchronousSocket socket) {
  int? statusCode;
  String? reasonPhrase;
  var body = StringBuffer();
  var headers = <String, List<String>>{};

  var inHeader = false;
  var inBody = false;
  var contentLength = 0;
  var contentRead = 0;

  void processLine(String line, int bytesRead, _LineDecoder decoder) {
    if (inBody) {
      body.write(line);
      contentRead += bytesRead;
    } else if (inHeader) {
      if (line.trim().isEmpty) {
        inBody = true;
        if (contentLength > 0) {
          decoder.expectedByteCount = contentLength;
        }
        return;
      }
      var separator = line.indexOf(':');
      var name = line.substring(0, separator).toLowerCase().trim();
      var value = line.substring(separator + 1).trim();
      if (name == HttpHeaders.transferEncodingHeader &&
          value.toLowerCase() != 'identity') {
        throw UnsupportedError('only identity transfer encoding is accepted');
      }
      if (name == HttpHeaders.contentLengthHeader) {
        contentLength = int.parse(value);
      }
      if (!headers.containsKey(name)) {
        headers[name] = [];
      }
      headers[name]!.add(value);
    } else if (line.startsWith('HTTP/1.1') || line.startsWith('HTTP/1.0')) {
      statusCode = int.parse(
          line.substring('HTTP/1.x '.length, 'HTTP/1.x xxx'.length));
      reasonPhrase = line.substring('HTTP/1.x xxx '.length);
      inHeader = true;
    } else {
      throw UnsupportedError('unsupported http response format');
    }
  }

  var lineDecoder = _LineDecoder.withCallback(processLine);

  try {
    while (!inHeader ||
        !inBody ||
        ((contentRead + lineDecoder.bufferedBytes) < contentLength)) {
      var bytes = socket.readSync(1024);

      if (bytes == null || bytes.isEmpty) {
        break;
      }
      lineDecoder.add(bytes);
    }
  } finally {
    try {
      lineDecoder.close();
    } finally {
      socket.closeSync();
    }
  }

  return SyncHttpClientResponse._(headers,
      reasonPhrase: reasonPhrase,
      statusCode: statusCode,
      body: body.toString());
}