SyncHttpClientResponse constructor Null safety
- 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());
}