Add feature gate cbor
.
This commit is contained in:
parent
800eb4b10a
commit
3b9fa765ad
|
@ -21,6 +21,7 @@ string_number = ["num-traits"]
|
||||||
dataloader = ["futures-timer", "futures-channel", "lru"]
|
dataloader = ["futures-timer", "futures-channel", "lru"]
|
||||||
tracing = ["tracinglib", "tracing-futures"]
|
tracing = ["tracinglib", "tracing-futures"]
|
||||||
decimal = ["rust_decimal"]
|
decimal = ["rust_decimal"]
|
||||||
|
cbor = ["serde_cbor"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-graphql-derive = { path = "derive", version = "2.9.8" }
|
async-graphql-derive = { path = "derive", version = "2.9.8" }
|
||||||
|
@ -37,13 +38,14 @@ pin-project-lite = "0.2.6"
|
||||||
regex = "1.4.5"
|
regex = "1.4.5"
|
||||||
serde = { version = "1.0.125", features = ["derive"] }
|
serde = { version = "1.0.125", features = ["derive"] }
|
||||||
serde_json = "1.0.64"
|
serde_json = "1.0.64"
|
||||||
serde_cbor = "0.11.1"
|
|
||||||
thiserror = "1.0.24"
|
thiserror = "1.0.24"
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
http = "0.2.3"
|
http = "0.2.3"
|
||||||
multer = "2.0.0"
|
multer = "2.0.0"
|
||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
bytes = { version = "1.0.1", features = ["serde"] }
|
bytes = { version = "1.0.1", features = ["serde"] }
|
||||||
|
mime = "0.3.15"
|
||||||
|
|
||||||
# Feature optional dependencies
|
# Feature optional dependencies
|
||||||
bson = { version = "2.0.0-beta.1", optional = true, features = ["chrono-0_4"] }
|
bson = { version = "2.0.0-beta.1", optional = true, features = ["chrono-0_4"] }
|
||||||
chrono = { version = "0.4.19", optional = true }
|
chrono = { version = "0.4.19", optional = true }
|
||||||
|
@ -56,7 +58,7 @@ opentelemetry = { version = "0.13.0", optional = true }
|
||||||
url = { version = "2.2.1", optional = true }
|
url = { version = "2.2.1", optional = true }
|
||||||
uuid = { version = "0.8.2", optional = true, features = ["v4", "serde"] }
|
uuid = { version = "0.8.2", optional = true, features = ["v4", "serde"] }
|
||||||
rust_decimal = { version = "1.14.3", optional = true }
|
rust_decimal = { version = "1.14.3", optional = true }
|
||||||
mime = "0.3.15"
|
|
||||||
# Non-feature optional dependencies
|
# Non-feature optional dependencies
|
||||||
blocking = { version = "1.0.2", optional = true }
|
blocking = { version = "1.0.2", optional = true }
|
||||||
lru = { version = "0.6.5", optional = true }
|
lru = { version = "0.6.5", optional = true }
|
||||||
|
@ -64,6 +66,7 @@ num-traits = { version = "0.2.14", optional = true }
|
||||||
sha2 = { version = "0.9.3", optional = true }
|
sha2 = { version = "0.9.3", optional = true }
|
||||||
futures-timer = { version = "3.0.2", optional = true }
|
futures-timer = { version = "3.0.2", optional = true }
|
||||||
futures-channel = { version = "0.3.13", optional = true }
|
futures-channel = { version = "0.3.13", optional = true }
|
||||||
|
serde_cbor = { version = "0.11.1", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { version = "1.4.0", features = ["macros", "rt-multi-thread", "sync", "time"] }
|
tokio = { version = "1.4.0", features = ["macros", "rt-multi-thread", "sync", "time"] }
|
||||||
|
|
|
@ -77,6 +77,7 @@ This crate offers the following features, all of which are not activated by defa
|
||||||
- `dataloader`: Support [DataLoader](dataloader/struct.DataLoader.html).
|
- `dataloader`: Support [DataLoader](dataloader/struct.DataLoader.html).
|
||||||
- `secrecy`: Integrate with the [`secrecy` crate](https://crates.io/crates/secrecy).
|
- `secrecy`: Integrate with the [`secrecy` crate](https://crates.io/crates/secrecy).
|
||||||
- `decimal`: Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal).
|
- `decimal`: Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal).
|
||||||
|
- `cbor`: Support for [serde_cbor](https://crates.io/crates/serde_cbor).
|
||||||
|
|
||||||
## Apollo Studio
|
## Apollo Studio
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,17 @@ mod graphiql_source;
|
||||||
mod multipart;
|
mod multipart;
|
||||||
mod playground_source;
|
mod playground_source;
|
||||||
mod websocket;
|
mod websocket;
|
||||||
use mime::{self};
|
|
||||||
use futures_util::io::{AsyncRead, AsyncReadExt};
|
|
||||||
|
|
||||||
use crate::{BatchRequest, ParseRequestError, Request};
|
|
||||||
|
|
||||||
pub use graphiql_source::graphiql_source;
|
pub use graphiql_source::graphiql_source;
|
||||||
pub use multipart::MultipartOptions;
|
pub use multipart::MultipartOptions;
|
||||||
pub use playground_source::{playground_source, GraphQLPlaygroundConfig};
|
pub use playground_source::{playground_source, GraphQLPlaygroundConfig};
|
||||||
pub use websocket::{ClientMessage, Protocols as WebSocketProtocols, WebSocket, WsMessage};
|
pub use websocket::{ClientMessage, Protocols as WebSocketProtocols, WebSocket, WsMessage};
|
||||||
|
|
||||||
|
use futures_util::io::{AsyncRead, AsyncReadExt};
|
||||||
|
use mime;
|
||||||
|
|
||||||
|
use crate::{BatchRequest, ParseRequestError, Request};
|
||||||
|
|
||||||
/// Receive a GraphQL request from a content type and body.
|
/// Receive a GraphQL request from a content type and body.
|
||||||
pub async fn receive_body(
|
pub async fn receive_body(
|
||||||
content_type: Option<impl AsRef<str>>,
|
content_type: Option<impl AsRef<str>>,
|
||||||
|
@ -32,26 +33,37 @@ pub async fn receive_batch_body(
|
||||||
opts: MultipartOptions,
|
opts: MultipartOptions,
|
||||||
) -> Result<BatchRequest, ParseRequestError> {
|
) -> Result<BatchRequest, ParseRequestError> {
|
||||||
// if no content-type header is set, we default to json
|
// if no content-type header is set, we default to json
|
||||||
let content_type = content_type.as_ref().map(AsRef::as_ref).unwrap_or("application/json");
|
let content_type = content_type
|
||||||
|
.as_ref()
|
||||||
|
.map(AsRef::as_ref)
|
||||||
|
.unwrap_or("application/json");
|
||||||
|
|
||||||
let content_type: mime::Mime = content_type.parse()?;
|
let content_type: mime::Mime = content_type.parse()?;
|
||||||
|
|
||||||
match (content_type.type_(), content_type.subtype()) {
|
match (content_type.type_(), content_type.subtype()) {
|
||||||
// application/json -> try json
|
// application/json -> try json
|
||||||
(mime::APPLICATION, mime::JSON) => receive_batch_json(body).await,
|
(mime::APPLICATION, mime::JSON) => receive_batch_json(body).await,
|
||||||
|
|
||||||
// cbor is in application/octet-stream.
|
// cbor is in application/octet-stream.
|
||||||
// TODO: wait for mime to add application/cbor and match against that too
|
// TODO: wait for mime to add application/cbor and match against that too
|
||||||
(mime::OCTET_STREAM, _) | (mime::APPLICATION, mime::OCTET_STREAM) => receive_batch_cbor(body).await,
|
#[cfg(feature = "cbor")]
|
||||||
|
(mime::OCTET_STREAM, _) | (mime::APPLICATION, mime::OCTET_STREAM) => {
|
||||||
|
receive_batch_cbor(body).await
|
||||||
|
}
|
||||||
|
|
||||||
// try to use multipart
|
// try to use multipart
|
||||||
(mime::MULTIPART, _) => {
|
(mime::MULTIPART, _) => {
|
||||||
if let Some(boundary) = content_type.get_param("boundary") {
|
if let Some(boundary) = content_type.get_param("boundary") {
|
||||||
multipart::receive_batch_multipart(body, boundary.to_string(), opts).await
|
multipart::receive_batch_multipart(body, boundary.to_string(), opts).await
|
||||||
} else {
|
} else {
|
||||||
Err(ParseRequestError::InvalidMultipart(multer::Error::NoBoundary))
|
Err(ParseRequestError::InvalidMultipart(
|
||||||
|
multer::Error::NoBoundary,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// default to json and try that
|
// default to json and try that
|
||||||
_ => receive_batch_json(body).await
|
_ => receive_batch_json(body).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +83,16 @@ pub async fn receive_batch_json(body: impl AsyncRead) -> Result<BatchRequest, Pa
|
||||||
.map_err(|e| ParseRequestError::InvalidRequest(Box::new(e)))?)
|
.map_err(|e| ParseRequestError::InvalidRequest(Box::new(e)))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receive a GraphQL request from a body as CBOR
|
/// Receive a GraphQL request from a body as CBOR.
|
||||||
|
#[cfg(feature = "cbor")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "cbor")))]
|
||||||
|
pub async fn receive_cbor(body: impl AsyncRead) -> Result<Request, ParseRequestError> {
|
||||||
|
receive_batch_cbor(body).await?.into_single()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Receive a GraphQL batch request from a body as CBOR
|
||||||
|
#[cfg(feature = "cbor")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "cbor")))]
|
||||||
pub async fn receive_batch_cbor(body: impl AsyncRead) -> Result<BatchRequest, ParseRequestError> {
|
pub async fn receive_batch_cbor(body: impl AsyncRead) -> Result<BatchRequest, ParseRequestError> {
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
futures_util::pin_mut!(body);
|
futures_util::pin_mut!(body);
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
//! - `string_number`: Enable the [StringNumber](types/struct.StringNumber.html).
|
//! - `string_number`: Enable the [StringNumber](types/struct.StringNumber.html).
|
||||||
//! - `dataloader`: Support [DataLoader](dataloader/struct.DataLoader.html).
|
//! - `dataloader`: Support [DataLoader](dataloader/struct.DataLoader.html).
|
||||||
//! - `decimal`: Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal).
|
//! - `decimal`: Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal).
|
||||||
|
//! - `cbor`: Support for [serde_cbor](https://crates.io/crates/serde_cbor).
|
||||||
//!
|
//!
|
||||||
//! ## Integrations
|
//! ## Integrations
|
||||||
//!
|
//!
|
||||||
|
|
Loading…
Reference in New Issue
Block a user