connect method
建立连接
Implementation
Future<void> connect() async {
if (_isClosed) {
throw StateError('SSE 客户端已关闭');
}
if (_isConnected) {
throw StateError('SSE 客户端已经连接,请先关闭现有连接');
}
if (_isConnecting) {
throw StateError('SSE 客户端正在连接中,请勿重复调用');
}
_isConnecting = true;
try {
// 构建 URL
final uri = _buildUri();
// 创建 HTTP 客户端
_httpClient = HttpClient();
// 根据方法创建请求
final upperMethod = method.toUpperCase();
if (upperMethod == 'POST') {
_request = await _httpClient!.postUrl(uri);
} else {
_request = await _httpClient!.getUrl(uri);
}
// 设置请求头(必须 await,因为动态请求头构建是异步的)
await _setHeaders();
// 如果是 POST 请求且有数据,写入请求体
if (upperMethod == 'POST' && data != null) {
await _writeRequestBody();
}
// 发送请求
_response = await _request!.close();
// 检查响应状态
if (_response!.statusCode != 200) {
throw HttpException(
'SSE 连接失败: HTTP ${_response!.statusCode}',
uri: uri,
);
}
// 检查 Content-Type
final contentType = _response!.headers.value('content-type');
if (contentType == null || !contentType.contains('text/event-stream')) {
// 警告但不阻止,因为某些服务器可能不设置正确的 Content-Type
print('警告: 响应 Content-Type 不是 text/event-stream: $contentType');
}
// 处理响应流
_handleResponse();
_isConnected = true;
} catch (e) {
// 连接失败时清理资源
_cleanupResources();
// 检查 _eventController 是否已关闭,防止在关闭后调用 addError()
if (!_isClosed && !_eventController.isClosed) {
_eventController.addError(e);
}
rethrow;
} finally {
_isConnecting = false;
}
}