Split Endpoint trait into OutgoingRequest, IncomingRequest
This commit is contained in:
parent
abc34eeb7e
commit
987d48666c
@ -101,7 +101,7 @@ impl ToTokens for Api {
|
||||
let request_type = &self.request;
|
||||
let response_type = &self.response;
|
||||
|
||||
let request_try_from_type = if self.request.contains_lifetimes() {
|
||||
let incoming_request_type = if self.request.contains_lifetimes() {
|
||||
quote!(IncomingRequest)
|
||||
} else {
|
||||
quote!(Request)
|
||||
@ -227,22 +227,25 @@ impl ToTokens for Api {
|
||||
|
||||
let request_lifetimes = self.request.combine_lifetimes();
|
||||
|
||||
let non_auth_endpoint_impl = if requires_authentication.value {
|
||||
let non_auth_endpoint_impls = if requires_authentication.value {
|
||||
TokenStream::new()
|
||||
} else {
|
||||
quote! {
|
||||
impl #request_lifetimes #ruma_api_import::NonAuthEndpoint
|
||||
impl #request_lifetimes #ruma_api_import::OutgoingNonAuthRequest
|
||||
for Request #request_lifetimes
|
||||
{}
|
||||
|
||||
impl #ruma_api_import::IncomingNonAuthRequest for #incoming_request_type {}
|
||||
}
|
||||
};
|
||||
|
||||
let api = quote! {
|
||||
|
||||
#[doc = #request_doc]
|
||||
#request_type
|
||||
|
||||
impl ::std::convert::TryFrom<#ruma_api_import::exports::http::Request<Vec<u8>>> for #request_try_from_type {
|
||||
impl ::std::convert::TryFrom<#ruma_api_import::exports::http::Request<Vec<u8>>>
|
||||
for #incoming_request_type
|
||||
{
|
||||
type Error = #ruma_api_import::error::FromHttpRequestError;
|
||||
|
||||
#[allow(unused_variables)]
|
||||
@ -308,21 +311,24 @@ impl ToTokens for Api {
|
||||
}
|
||||
}
|
||||
|
||||
impl #request_lifetimes #ruma_api_import::Endpoint for Request #request_lifetimes {
|
||||
type Response = Response;
|
||||
type ResponseError = #error;
|
||||
type IncomingRequest = <Self as #ruma_api_import::Outgoing>::Incoming;
|
||||
const __METADATA: #ruma_api_import::Metadata = #ruma_api_import::Metadata {
|
||||
description: #description,
|
||||
method: #ruma_api_import::exports::http::Method::#method,
|
||||
name: #name,
|
||||
path: #path,
|
||||
rate_limited: #rate_limited,
|
||||
requires_authentication: #requires_authentication,
|
||||
};
|
||||
|
||||
impl #request_lifetimes #ruma_api_import::OutgoingRequest
|
||||
for Request #request_lifetimes
|
||||
{
|
||||
type EndpointError = #error;
|
||||
type IncomingResponse = <Response as #ruma_api_import::Outgoing>::Incoming;
|
||||
|
||||
// FIXME: Doc string interpolation
|
||||
/// Metadata for the `#name` endpoint.
|
||||
const METADATA: #ruma_api_import::Metadata = #ruma_api_import::Metadata {
|
||||
description: #description,
|
||||
method: #ruma_api_import::exports::http::Method::#method,
|
||||
name: #name,
|
||||
path: #path,
|
||||
rate_limited: #rate_limited,
|
||||
requires_authentication: #requires_authentication,
|
||||
};
|
||||
const METADATA: #ruma_api_import::Metadata = __METADATA;
|
||||
|
||||
#[allow(unused_mut, unused_variables)]
|
||||
fn try_into_http_request(
|
||||
@ -333,7 +339,7 @@ impl ToTokens for Api {
|
||||
#ruma_api_import::exports::http::Request<Vec<u8>>,
|
||||
#ruma_api_import::error::IntoHttpError,
|
||||
> {
|
||||
let metadata = Request::METADATA;
|
||||
let metadata = <Self as #ruma_api_import::OutgoingRequest>::METADATA;
|
||||
|
||||
let http_request = #ruma_api_import::exports::http::Request::builder()
|
||||
.method(#ruma_api_import::exports::http::Method::#method)
|
||||
@ -350,7 +356,16 @@ impl ToTokens for Api {
|
||||
}
|
||||
}
|
||||
|
||||
#non_auth_endpoint_impl
|
||||
impl #ruma_api_import::IncomingRequest for #incoming_request_type {
|
||||
type EndpointError = #error;
|
||||
type OutgoingResponse = Response;
|
||||
|
||||
// FIXME: Doc string interpolation
|
||||
/// Metadata for the `#name` endpoint.
|
||||
const METADATA: #ruma_api_import::Metadata = __METADATA;
|
||||
}
|
||||
|
||||
#non_auth_endpoint_impls
|
||||
};
|
||||
|
||||
api.to_tokens(tokens);
|
||||
|
@ -4,12 +4,14 @@
|
||||
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use crate::EndpointError;
|
||||
|
||||
// FIXME when `!` becomes stable use it
|
||||
/// Default `ResponseError` for `ruma_api!` macro
|
||||
/// Default `EndpointError` for `ruma_api!` macro
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Void {}
|
||||
|
||||
impl crate::EndpointError for Void {
|
||||
impl EndpointError for Void {
|
||||
fn try_from_response(
|
||||
response: http::Response<Vec<u8>>,
|
||||
) -> Result<Self, ResponseDeserializationError> {
|
||||
|
@ -231,7 +231,7 @@ pub trait Outgoing {
|
||||
type Incoming;
|
||||
}
|
||||
|
||||
/// Gives users the ability to define their own serializable/deserializable errors.
|
||||
/// Gives users the ability to define their own serializable / deserializable errors.
|
||||
pub trait EndpointError: std::error::Error + Sized {
|
||||
/// Tries to construct `Self` from an `http::Response`.
|
||||
///
|
||||
@ -242,22 +242,15 @@ pub trait EndpointError: std::error::Error + Sized {
|
||||
) -> Result<Self, error::ResponseDeserializationError>;
|
||||
}
|
||||
|
||||
/// A Matrix API endpoint.
|
||||
///
|
||||
/// The type implementing this trait contains any data needed to make a request to the endpoint.
|
||||
pub trait Endpoint: Outgoing<Incoming = <Self as Endpoint>::IncomingRequest> {
|
||||
/// Data returned in a successful response from the endpoint.
|
||||
type Response: Outgoing<Incoming = Self::IncomingResponse>
|
||||
+ TryInto<http::Response<Vec<u8>>, Error = IntoHttpError>;
|
||||
/// Error type returned when response from endpoint fails.
|
||||
type ResponseError: EndpointError;
|
||||
/// A request type for a Matrix API endpoint. (trait used for sending requests)
|
||||
pub trait OutgoingRequest {
|
||||
/// A type capturing the expected error conditions the server can return.
|
||||
type EndpointError: EndpointError;
|
||||
|
||||
/// Shorthand for `<Self as Outgoing>::Incoming`.
|
||||
type IncomingRequest: TryFrom<http::Request<Vec<u8>>, Error = FromHttpRequestError>;
|
||||
/// Shorthand for `<Self::Response as Outgoing>::Incoming`.
|
||||
/// Response type returned when the request is successful.
|
||||
type IncomingResponse: TryFrom<
|
||||
http::Response<Vec<u8>>,
|
||||
Error = FromHttpResponseError<<Self as Endpoint>::ResponseError>,
|
||||
Error = FromHttpResponseError<Self::EndpointError>,
|
||||
>;
|
||||
|
||||
/// Metadata about the endpoint.
|
||||
@ -278,11 +271,23 @@ pub trait Endpoint: Outgoing<Incoming = <Self as Endpoint>::IncomingRequest> {
|
||||
) -> Result<http::Request<Vec<u8>>, IntoHttpError>;
|
||||
}
|
||||
|
||||
/// A Matrix API endpoint that doesn't require authentication.
|
||||
///
|
||||
/// This marker trait is to indicate that a type implementing `Endpoint` doesn't require any
|
||||
/// authentication.
|
||||
pub trait NonAuthEndpoint: Endpoint {}
|
||||
/// A request type for a Matrix API endpoint. (trait used for receiving requests)
|
||||
pub trait IncomingRequest: TryFrom<http::Request<Vec<u8>>, Error = FromHttpRequestError> {
|
||||
/// A type capturing the error conditions that can be returned in the response.
|
||||
type EndpointError: EndpointError;
|
||||
|
||||
/// Response type to return when the request is successful.
|
||||
type OutgoingResponse: TryInto<http::Response<Vec<u8>>, Error = IntoHttpError>;
|
||||
|
||||
/// Metadata about the endpoint.
|
||||
const METADATA: Metadata;
|
||||
}
|
||||
|
||||
/// Marker trait for requests that don't require authentication. (for the client side)
|
||||
pub trait OutgoingNonAuthRequest: OutgoingRequest {}
|
||||
|
||||
/// Marker trait for requests that don't require authentication. (for the server side)
|
||||
pub trait IncomingNonAuthRequest: IncomingRequest {}
|
||||
|
||||
/// Metadata about an API endpoint.
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use ruma_api::{ruma_api, Endpoint as _};
|
||||
use ruma_api::{ruma_api, OutgoingRequest as _};
|
||||
use ruma_identifiers::{user_id, UserId};
|
||||
|
||||
ruma_api! {
|
||||
|
@ -10,7 +10,7 @@ use ruma_api::{
|
||||
FromHttpRequestError, FromHttpResponseError, IntoHttpError, RequestDeserializationError,
|
||||
ResponseDeserializationError, ServerError, Void,
|
||||
},
|
||||
Endpoint, Metadata, Outgoing,
|
||||
IncomingRequest, Metadata, Outgoing, OutgoingRequest,
|
||||
};
|
||||
|
||||
/// A request to create a new room alias.
|
||||
@ -24,35 +24,33 @@ impl Outgoing for Request {
|
||||
type Incoming = Self;
|
||||
}
|
||||
|
||||
impl Endpoint for Request {
|
||||
type Response = Response;
|
||||
type ResponseError = Void;
|
||||
type IncomingRequest = Self;
|
||||
const METADATA: Metadata = Metadata {
|
||||
description: "Add an alias to a room.",
|
||||
method: Method::PUT,
|
||||
name: "create_alias",
|
||||
path: "/_matrix/client/r0/directory/room/:room_alias",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
};
|
||||
|
||||
impl OutgoingRequest for Request {
|
||||
type EndpointError = Void;
|
||||
type IncomingResponse = Response;
|
||||
|
||||
const METADATA: Metadata = Metadata {
|
||||
description: "Add an alias to a room.",
|
||||
method: Method::PUT,
|
||||
name: "create_alias",
|
||||
path: "/_matrix/client/r0/directory/room/:room_alias",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
};
|
||||
const METADATA: Metadata = METADATA;
|
||||
|
||||
fn try_into_http_request(
|
||||
self,
|
||||
base_url: &str,
|
||||
_access_token: Option<&str>,
|
||||
) -> Result<http::Request<Vec<u8>>, IntoHttpError> {
|
||||
let metadata = Request::METADATA;
|
||||
|
||||
let url = (base_url.to_owned() + metadata.path)
|
||||
let url = (base_url.to_owned() + METADATA.path)
|
||||
.replace(":room_alias", &self.room_alias.to_string());
|
||||
|
||||
let request_body = RequestBody { room_id: self.room_id };
|
||||
|
||||
let http_request = http::Request::builder()
|
||||
.method(metadata.method)
|
||||
.method(METADATA.method)
|
||||
.uri(url)
|
||||
.body(serde_json::to_vec(&request_body)?)
|
||||
// this cannot fail because we don't give user-supplied data to any of the
|
||||
@ -63,6 +61,13 @@ impl Endpoint for Request {
|
||||
}
|
||||
}
|
||||
|
||||
impl IncomingRequest for Request {
|
||||
type EndpointError = Void;
|
||||
type OutgoingResponse = Response;
|
||||
|
||||
const METADATA: Metadata = METADATA;
|
||||
}
|
||||
|
||||
impl TryFrom<http::Request<Vec<u8>>> for Request {
|
||||
type Error = FromHttpRequestError;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use ruma_api::{ruma_api, Endpoint};
|
||||
use ruma_api::{ruma_api, OutgoingRequest as _};
|
||||
|
||||
ruma_api! {
|
||||
metadata: {
|
||||
|
@ -56,7 +56,7 @@ mod tests {
|
||||
use std::convert::TryInto;
|
||||
|
||||
use js_int::uint;
|
||||
use ruma_api::Endpoint as _;
|
||||
use ruma_api::OutgoingRequest as _;
|
||||
|
||||
use super::{Request, Response};
|
||||
|
||||
|
@ -118,7 +118,7 @@ mod tests {
|
||||
use super::{Direction, Request};
|
||||
|
||||
use js_int::uint;
|
||||
use ruma_api::Endpoint;
|
||||
use ruma_api::OutgoingRequest;
|
||||
use ruma_identifiers::room_id;
|
||||
|
||||
use crate::r0::filter::{LazyLoadOptions, RoomEventFilter};
|
||||
|
@ -140,7 +140,7 @@ mod user_serde;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruma_api::Endpoint;
|
||||
use ruma_api::OutgoingRequest;
|
||||
use serde_json::{from_value as from_json_value, json, Value as JsonValue};
|
||||
|
||||
use super::{LoginInfo, Medium, Request, UserInfo};
|
||||
|
@ -403,7 +403,7 @@ impl DeviceLists {
|
||||
mod tests {
|
||||
use std::{convert::TryInto, time::Duration};
|
||||
|
||||
use ruma_api::Endpoint;
|
||||
use ruma_api::OutgoingRequest;
|
||||
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||
|
||||
use matches::assert_matches;
|
||||
|
@ -113,7 +113,7 @@ use http::{uri::Uri, Response as HttpResponse};
|
||||
use hyper::{client::HttpConnector, Client as HyperClient};
|
||||
#[cfg(feature = "hyper-tls")]
|
||||
use hyper_tls::HttpsConnector;
|
||||
use ruma_api::Endpoint;
|
||||
use ruma_api::OutgoingRequest;
|
||||
use ruma_client_api::r0::sync::sync_events::{
|
||||
Filter as SyncFilter, Request as SyncRequest, Response as SyncResponse,
|
||||
};
|
||||
@ -350,19 +350,19 @@ where
|
||||
}
|
||||
|
||||
/// Makes a request to a Matrix API endpoint.
|
||||
pub async fn request<Request: Endpoint>(
|
||||
pub async fn request<Request: OutgoingRequest>(
|
||||
&self,
|
||||
request: Request,
|
||||
) -> Result<Request::IncomingResponse, Error<Request::ResponseError>> {
|
||||
) -> Result<Request::IncomingResponse, Error<Request::EndpointError>> {
|
||||
self.request_with_url_params(request, None).await
|
||||
}
|
||||
|
||||
/// Makes a request to a Matrix API endpoint including additional URL parameters.
|
||||
pub async fn request_with_url_params<Request: Endpoint>(
|
||||
pub async fn request_with_url_params<Request: OutgoingRequest>(
|
||||
&self,
|
||||
request: Request,
|
||||
extra_params: Option<BTreeMap<String, String>>,
|
||||
) -> Result<Request::IncomingResponse, Error<Request::ResponseError>> {
|
||||
) -> Result<Request::IncomingResponse, Error<Request::EndpointError>> {
|
||||
let client = self.0.clone();
|
||||
let mut http_request = {
|
||||
let session;
|
||||
|
Loading…
x
Reference in New Issue
Block a user