apollo_compiler/request.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
//! GraphQL [requests](https://spec.graphql.org/draft/#request)
//!
//! This exists primarily to support [`introspection::partial_execute`].
use crate::executable::Operation;
use crate::execution::input_coercion::InputCoercionError;
#[cfg(doc)]
use crate::introspection;
use crate::parser::SourceMap;
use crate::parser::SourceSpan;
use crate::response::GraphQLError;
use crate::response::JsonMap;
use crate::validation::SuspectedValidationBug;
use crate::validation::Valid;
use crate::Schema;
/// Coerce the values of [variables](https://spec.graphql.org/draft/#sec-Language.Variables)
/// from a GraphQL request to the types expected by the operation.
///
/// This is [_CoerceVariableValues()_](https://spec.graphql.org/October2021/#CoerceVariableValues())
/// in the GraphQL specification.
///
/// Returns a [request error](https://spec.graphql.org/draft/#sec-Errors.Request-Errors)
/// if a value as an incompatible type, or if a required variable is not provided.
pub fn coerce_variable_values(
schema: &Valid<Schema>,
operation: &Operation,
values: &JsonMap,
) -> Result<Valid<JsonMap>, RequestError> {
Ok(crate::execution::input_coercion::coerce_variable_values(
schema, operation, values,
)?)
}
/// A [request error](https://spec.graphql.org/draft/#sec-Errors.Request-Errors) is an error
/// raised during an early phase of the [execution](https://spec.graphql.org/draft/#sec-Execution)
/// to indicate that the request as a whole is considered faulty.
///
/// A request error should cause the rest of execution to be aborted,
/// and result in a GraphQL response that does not have a `data` key.
/// This differs from a response with `"data": null` which can happen with
/// a [field error](https://spec.graphql.org/draft/#sec-Errors.Field-Errors)
/// on a non-null field whose ancestors fields are all also non-null.
/// In that case the `null` value
/// is [propagated](https://spec.graphql.org/draft/#sec-Handling-Field-Errors)
/// all the way to the entire response data.
#[derive(Debug, Clone)]
pub struct RequestError {
pub(crate) message: String,
pub(crate) location: Option<SourceSpan>,
pub(crate) is_suspected_validation_bug: bool,
}
impl From<InputCoercionError> for RequestError {
fn from(error: InputCoercionError) -> Self {
match error {
InputCoercionError::SuspectedValidationBug(SuspectedValidationBug {
message,
location,
}) => Self {
message,
location,
is_suspected_validation_bug: true,
},
InputCoercionError::ValueError { message, location } => Self {
message,
location,
is_suspected_validation_bug: false,
},
}
}
}
impl RequestError {
pub fn message(&self) -> impl std::fmt::Display + '_ {
&self.message
}
pub fn location(&self) -> Option<SourceSpan> {
self.location
}
pub fn to_graphql_error(&self, sources: &SourceMap) -> GraphQLError {
let mut error = GraphQLError::new(&self.message, self.location, sources);
if self.is_suspected_validation_bug {
error
.extensions
.insert("APOLLO_SUSPECTED_VALIDATION_BUG", true.into());
}
error
}
}