from static method
Creates an instance of SSHHttpClientResponse that contains the response
sent by the HTTP server over socket
.
Implementation
static Future<SSHHttpClientResponse> from(SSHSocket socket) async {
int? statusCode;
String? reasonPhrase;
final body = StringBuffer();
final 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;
}
final separator = line.indexOf(':');
final name = line.substring(0, separator).toLowerCase().trim();
final value = line.substring(separator + 1).trim();
if (name == SSHHttpHeaders.transferEncodingHeader &&
value.toLowerCase() != 'identity') {
throw UnsupportedError('only identity transfer encoding is accepted');
}
if (name == SSHHttpHeaders.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');
}
}
final lineDecoder = LineDecoder.withCallback(processLine);
await for (final chunk in socket.stream) {
if (!inHeader ||
!inBody ||
((contentRead + lineDecoder.bufferedBytes) < contentLength)) {
lineDecoder.add(chunk);
continue;
}
break;
}
try {
lineDecoder.close();
} finally {
socket.close();
}
// try {
// while (!inHeader ||
// !inBody ||
// ((contentRead + lineDecoder.bufferedBytes) < contentLength)) {
// final bytes = socket.readSync(1024);
// if (bytes == null || bytes.isEmpty) {
// break;
// }
// lineDecoder.add(bytes);
// }
// } finally {
// try {
// lineDecoder.close();
// } finally {
// socket.closeSync();
// }
// }
return SSHHttpClientResponse._(
headers,
reasonPhrase: reasonPhrase,
statusCode: statusCode,
body: body.toString(),
);
}