connect method

Future<void> connect()

建立连接

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;
  }
}