responseParse static method

Response responseParse(
  1. Uint8List data
)

将原始Socket字节数据解析为http.Response对象

Implementation

static http.Response responseParse(Uint8List data) {
  // 解析响应头(必须是文本)和响应体(可能是二进制)
  final headerEndIndex = _findHeaderEnd(data);

  if (headerEndIndex == -1) {
    throw FormatException('Could not find end of HTTP headers');
  }

  // 提取并解析响应头(只处理这部分的编码)
  final headerData = data.sublist(0, headerEndIndex);
  String headerString;

  // 更健壮的编码检测和处理
  try {
    // 尝试UTF-8
    headerString = utf8.decode(headerData, allowMalformed: false);
  } on FormatException {
    try {
      // 尝试Latin-1 (ISO-8859-1)
      headerString = latin1.decode(headerData);
    } on FormatException {
      // 最后尝试允许畸形的UTF-8
      headerString = utf8.decode(headerData, allowMalformed: true);
    }
  }

  // 解析状态行和头字段
  final headerLines = headerString.split('\r\n');
  if (headerLines.isEmpty) {
    throw FormatException('Missing status line in HTTP response');
  }

  // 解析状态行 (格式: HTTP/version statusCode reasonPhrase)
  final statusLine = headerLines[0];
  final statusLineParts = Utils.splitUntil(statusLine, ' ', maxParts: 3); // 最多分成3部分,避免原因短语包含空格
  if (statusLineParts.length < 2) {
    throw FormatException('Invalid status line format: $statusLine');
  }

  final httpVersion = statusLineParts[0];
  final statusCode = int.tryParse(statusLineParts[1]) ??
      (throw FormatException('Invalid status code: ${statusLineParts[1]}'));
  final reasonPhrase = statusLineParts.length > 2 ? statusLineParts[2] : '';

  if (!httpVersion.startsWith('HTTP/')) {
    throw FormatException('Invalid HTTP version: $httpVersion');
  }

  // 解析响应头
  final headers = <String, String>{};
  for (int i = 1; i < headerLines.length; i++) {
    final line = headerLines[i];
    if (line.isEmpty) continue;

    final colonIndex = line.indexOf(':');
    if (colonIndex == -1) {
      throw FormatException('Invalid header format: $line');
    }

    final name = line.substring(0, colonIndex).trim().toLowerCase();
    final value = line.substring(colonIndex + 1).trim();

    // 处理重复的头字段
    if (headers.containsKey(name)) {
      headers[name] = '${headers[name]}, $value';
    } else {
      headers[name] = value;
    }
  }

  // 处理响应体(直接使用原始字节,避免编码转换问题)
  Uint8List body = Uint8List(0);
  final bodyStartIndex = headerEndIndex + 4; // 跳过\r\n\r\n
  if (bodyStartIndex < data.length) {
    // 根据Content-Length验证体长度
    final contentLengthStr = headers['content-length'];
    if (contentLengthStr != null) {
      final contentLength = int.tryParse(contentLengthStr) ?? 0;
      final actualLength = data.length - bodyStartIndex;

      // 处理实际长度与声明长度不匹配的情况
      if (actualLength < contentLength) {
        body = data.sublist(bodyStartIndex);
      } else if (actualLength > contentLength) {
        body = data.sublist(bodyStartIndex, bodyStartIndex + contentLength);
      } else {
        body = data.sublist(bodyStartIndex);
      }
    } else {
      // 没有Content-Length时,使用所有剩余数据
      body = data.sublist(bodyStartIndex);
    }
  }

  // 创建响应对象
  final response = http.Response.bytes(
    body,
    statusCode,
    headers: headers,
    reasonPhrase: reasonPhrase,
    request: null, // 可以根据需要关联请求对象
  );

  return response;
}