request method
Executes document without discarding partial data or structured errors.
Implementation
Future<GraphQLResponse> request(
String document, {
Map<String, dynamic>? variables,
String? operationName,
Map<String, dynamic>? extensions,
CancelToken? cancelToken,
}) async {
late Response<dynamic> response;
try {
response = await _dio.post<dynamic>(
endpoint,
data: {
'query': document,
if (variables != null) 'variables': variables,
if (operationName != null) 'operationName': operationName,
if (extensions != null) 'extensions': extensions,
},
cancelToken: cancelToken,
options: Options(
contentType: Headers.jsonContentType,
responseType: ResponseType.json,
headers: {'accept': Headers.jsonContentType, ...headers},
validateStatus: (_) => true,
),
);
} on DioException catch (error) {
throw GraphQLRequestException(
error.type == DioExceptionType.cancel
? 'GraphQL request cancelled'
: 'GraphQL request failed${error.message == null ? '' : ': ${error.message}'}',
statusCode: error.response?.statusCode,
isCancelled: error.type == DioExceptionType.cancel,
);
}
final statusCode = response.statusCode;
if (statusCode == null || statusCode < 200 || statusCode >= 300) {
throw GraphQLRequestException(
'GraphQL request failed (HTTP ${statusCode ?? 'unknown'})',
statusCode: statusCode,
);
}
dynamic rawBody = response.data;
if (rawBody is String) {
try {
rawBody = jsonDecode(rawBody);
} on FormatException {
throw const GraphQLRequestException('Invalid GraphQL JSON response');
}
}
if (rawBody is! Map) {
throw const GraphQLRequestException('Invalid GraphQL response body');
}
final body = Map<String, dynamic>.from(rawBody);
final rawData = body['data'];
final rawErrors = body['errors'];
return GraphQLResponse(
data: rawData is Map ? Map<String, dynamic>.from(rawData) : null,
errors: rawErrors is List
? rawErrors
.map(GraphQLError.fromJson)
.whereType<GraphQLError>()
.toList()
: const [],
extensions: body['extensions'] is Map
? Map<String, dynamic>.from(body['extensions'] as Map)
: null,
);
}