#![cfg(feature = "macros")]
#![allow(dead_code)]
use core::convert::Infallible;
use kynos::{
HeaderParams, PathParams, QueryParams, Schema,
error::rejection::{
AuthRejection, BodyRejection, HeaderRejection, NegotiationRejection, PathRejection,
QueryRejection,
},
extract::{
FromRequest, FromRequestParts,
body::{binary::Binary, text::Text},
connection::{ConnectInfo, MatchedPath},
media::OctetStream,
params::{header::Headers as HeaderExtractor, path::Path, query::Query},
},
response::{negotiate::Accept, range::Range},
security::{
Authenticates, Authenticator,
auth::{Auth, MaybeAuth, Scoped, Scopes},
carrier::BearerToken,
schemes::Bearer,
},
};
fn head_rejects_with<E, C, T: FromRequestParts<C, Rejection = E>>() {}
fn body_rejects_with<E, C, T: FromRequest<C, Rejection = E>>() {}
#[derive(Schema, PathParams)]
struct UserPath {
id: u64,
}
#[derive(Schema, QueryParams)]
struct Page {
page: u32,
}
#[derive(HeaderParams)]
struct Wanted {
x_request_id: String,
}
#[test]
fn a_parameter_extractor_rejects_with_its_own_type() {
head_rejects_with::<PathRejection, (), Path<UserPath>>();
head_rejects_with::<QueryRejection, (), Query<Page>>();
head_rejects_with::<HeaderRejection, (), HeaderExtractor<Wanted>>();
}
#[cfg(feature = "cookie")]
#[test]
fn a_cookie_extractor_rejects_with_its_own_type() {
use kynos::{
CookieParams, error::rejection::CookieRejection,
extract::params::cookie::Cookies as CookieExtractor,
};
#[derive(CookieParams)]
struct Session {
session: String,
}
head_rejects_with::<CookieRejection, (), CookieExtractor<Session>>();
}
#[test]
fn a_body_extractor_rejects_with_the_body_type() {
body_rejects_with::<BodyRejection, (), Text>();
body_rejects_with::<BodyRejection, (), Binary<OctetStream>>();
#[cfg(feature = "json")]
{
use kynos::extract::body::json::Json;
#[derive(Schema, serde::Deserialize)]
struct User {
id: u64,
}
body_rejects_with::<BodyRejection, (), Json<User>>();
}
#[cfg(all(feature = "json", feature = "openapi32"))]
{
use kynos::extract::body::json_lines::{JsonLines, JsonSeq, records::Records};
#[derive(serde::Deserialize)]
struct Reading {
value: f64,
}
body_rejects_with::<BodyRejection, (), JsonLines<Records<Reading>>>();
body_rejects_with::<BodyRejection, (), JsonSeq<Records<Reading>>>();
}
}
#[test]
fn an_optional_body_delegates_to_the_body_it_wraps() {
body_rejects_with::<BodyRejection, (), Option<Text>>();
}
#[test]
fn negotiation_rejects_with_the_negotiation_type() {
head_rejects_with::<NegotiationRejection, (), Accept<()>>();
}
#[test]
fn the_connection_extractors_cannot_fail() {
head_rejects_with::<Infallible, (), MatchedPath>();
head_rejects_with::<Infallible, (), ConnectInfo>();
}
#[test]
fn a_range_extractor_cannot_reject() {
head_rejects_with::<Infallible, (), Range<Binary<OctetStream>>>();
}
#[test]
fn injection_cannot_fail() {
use kynos::di::inject::Inject;
head_rejects_with::<Infallible, u8, Inject<u8>>();
}
struct Claims;
struct Tokens;
impl<C: Sync> Authenticator<Bearer<Claims>, C> for Tokens {
async fn authenticate(
&self,
presented: BearerToken,
context: &C,
) -> Result<Claims, AuthRejection> {
let _ = (presented, context);
Err(AuthRejection::unauthenticated())
}
async fn authorize(
&self,
credential: &Claims,
scopes: &'static [&'static str],
context: &C,
) -> Result<(), AuthRejection> {
let _ = (credential, scopes, context);
Err(AuthRejection::forbidden())
}
}
struct App {
tokens: Tokens,
}
impl Authenticates<Bearer<Claims>> for App {
type Authenticator = Tokens;
fn authenticator(&self) -> &Self::Authenticator {
&self.tokens
}
}
struct ReadReports;
impl Scopes for ReadReports {
const SCOPES: &'static [&'static str] = &["reports:read"];
}
#[test]
fn an_authenticated_extractor_rejects_with_the_auth_type() {
head_rejects_with::<AuthRejection, App, Auth<Bearer<Claims>>>();
head_rejects_with::<AuthRejection, App, MaybeAuth<Bearer<Claims>>>();
}
#[test]
fn a_scoped_extractor_rejects_with_its_scope_sets_rejection() {
head_rejects_with::<
kynos::error::rejection::ScopedRejection<ReadReports>,
App,
Scoped<Bearer<Claims>, ReadReports>,
>();
}