Revise API to convert between associated types and Hyper request/response types.
This commit is contained in:
parent
b6a743d821
commit
5a4661c408
11
Cargo.toml
11
Cargo.toml
@ -11,8 +11,13 @@ repository = "https://github.com/ruma/ruma-api"
|
|||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = "0.8.21"
|
|
||||||
|
[dependencies.hyper]
|
||||||
|
git = "https://github.com/hyperium/hyper"
|
||||||
|
rev = "fed04dfb58e19b408322d4e5ca7474871e848a35"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
ruma-identifiers = "0.6.0"
|
ruma-identifiers = "0.11"
|
||||||
serde_derive = "0.8.21"
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
|
serde_json = "1.0"
|
||||||
|
240
src/lib.rs
240
src/lib.rs
@ -2,133 +2,139 @@
|
|||||||
//! in the various [Matrix](https://matrix.org) API specifications.
|
//! in the various [Matrix](https://matrix.org) API specifications.
|
||||||
//! These types can be shared by client and server code for all Matrix APIs.
|
//! These types can be shared by client and server code for all Matrix APIs.
|
||||||
//!
|
//!
|
||||||
//! When implementing a new Matrix API, each endpoint have a type that implements `Endpoint`, plus
|
//! When implementing a new Matrix API, each endpoint has a type that implements `Endpoint`, plus
|
||||||
//! any necessary associated types.
|
//! the necessary associated types.
|
||||||
//! An implementation of `Endpoint` contains all the information about the HTTP method, the path and
|
//! An implementation of `Endpoint` contains all the information about the HTTP method, the path and
|
||||||
//! input parameters for requests, and the structure of a successful response.
|
//! input parameters for requests, and the structure of a successful response.
|
||||||
//! Such types can then be used by client code to make requests, and by server code to fulfill
|
//! Such types can then be used by client code to make requests, and by server code to fulfill
|
||||||
//! those requests.
|
//! those requests.
|
||||||
//!
|
|
||||||
//! # Example
|
|
||||||
//!
|
|
||||||
//! ```rust,no_run
|
|
||||||
//! # #![feature(proc_macro)]
|
|
||||||
//! #
|
|
||||||
//! # extern crate ruma_api;
|
|
||||||
//! # extern crate ruma_identifiers;
|
|
||||||
//! # #[macro_use]
|
|
||||||
//! # extern crate serde_derive;
|
|
||||||
//! #
|
|
||||||
//! # fn main() {
|
|
||||||
//! /// PUT /_matrix/client/r0/directory/room/:room_alias
|
|
||||||
//! pub mod create {
|
|
||||||
//! use ruma_api;
|
|
||||||
//! use ruma_identifiers::{RoomAliasId, RoomId};
|
|
||||||
//!
|
|
||||||
//! /// This API endpoint's body parameters.
|
|
||||||
//! #[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
//! pub struct BodyParams {
|
|
||||||
//! pub room_id: RoomId,
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! /// This API endpoint's path parameters.
|
|
||||||
//! #[derive(Clone, Debug)]
|
|
||||||
//! pub struct PathParams {
|
|
||||||
//! pub room_alias: RoomAliasId,
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! /// Details about this API endpoint.
|
|
||||||
//! pub struct Endpoint;
|
|
||||||
//!
|
|
||||||
//! impl ruma_api::Endpoint for Endpoint {
|
|
||||||
//! type BodyParams = BodyParams;
|
|
||||||
//! type PathParams = PathParams;
|
|
||||||
//! type QueryParams = ();
|
|
||||||
//! type Response = ();
|
|
||||||
//!
|
|
||||||
//! fn method() -> ruma_api::Method {
|
|
||||||
//! ruma_api::Method::Put
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn request_path(params: Self::PathParams) -> String {
|
|
||||||
//! format!("/_matrix/client/r0/directory/room/{}", params.room_alias)
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn router_path() -> &'static str {
|
|
||||||
//! "/_matrix/client/r0/directory/room/:room_alias"
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn name() -> &'static str {
|
|
||||||
//! "room_directory"
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn description() -> &'static str {
|
|
||||||
//! "Matrix implementation of room directory."
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn requires_authentication() -> bool {
|
|
||||||
//! true
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn rate_limited() -> bool {
|
|
||||||
//! false
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! # }
|
|
||||||
|
|
||||||
|
#![deny(missing_debug_implementations)]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
#![feature(associated_consts, try_from)]
|
||||||
|
|
||||||
extern crate serde;
|
extern crate hyper;
|
||||||
|
#[cfg(test)] extern crate ruma_identifiers;
|
||||||
|
#[cfg(test)] extern crate serde;
|
||||||
|
#[cfg(test)] #[macro_use] extern crate serde_derive;
|
||||||
|
#[cfg(test)] extern crate serde_json;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
|
||||||
/// HTTP request methods used in Matrix APIs.
|
use hyper::{Method, Request, Response};
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
pub enum Method {
|
|
||||||
/// DELETE
|
|
||||||
Delete,
|
|
||||||
/// GET
|
|
||||||
Get,
|
|
||||||
/// POST
|
|
||||||
Post,
|
|
||||||
/// PUT
|
|
||||||
Put,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An API endpoint.
|
/// A Matrix API endpoint.
|
||||||
pub trait Endpoint {
|
pub trait Endpoint {
|
||||||
/// Request parameters supplied via the body of the HTTP request.
|
/// Data needed to make a request to the endpoint.
|
||||||
type BodyParams: Deserialize + Serialize;
|
type Request: TryInto<Request>;
|
||||||
|
/// Data returned from the endpoint.
|
||||||
|
type Response: TryFrom<Response>;
|
||||||
|
|
||||||
/// Request parameters supplied via the URL's path.
|
/// Metadata about the endpoint.
|
||||||
type PathParams;
|
const METADATA: Metadata;
|
||||||
|
}
|
||||||
/// Parameters supplied via the URL's query string.
|
|
||||||
type QueryParams: Deserialize + Serialize;
|
/// Metadata about an API endpoint.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
/// The body of the response.
|
pub struct Metadata {
|
||||||
type Response: Deserialize + Serialize;
|
/// A human-readable description of the endpoint.
|
||||||
|
pub description: &'static str,
|
||||||
/// Returns the HTTP method used by this endpoint.
|
/// The HTTP method used by this endpoint.
|
||||||
fn method() -> Method;
|
pub method: Method,
|
||||||
|
/// A unique identifier for this endpoint.
|
||||||
/// Generates the path component of the URL for this endpoint using the supplied parameters.
|
pub name: &'static str,
|
||||||
fn request_path(params: Self::PathParams) -> String;
|
/// The path of this endpoint's URL, with variable names where path parameters should be filled
|
||||||
|
/// in during a request.
|
||||||
/// Generates a generic path component of the URL for this endpoint, suitable for `Router` from
|
pub path: &'static str,
|
||||||
/// the router crate.
|
/// Whether or not this endpoint is rate limited by the server.
|
||||||
fn router_path() -> &'static str;
|
pub rate_limited: bool,
|
||||||
|
/// Whether or not the server requires an authenticated user for this endpoint.
|
||||||
/// A unique identifier for this endpoint, suitable for `Router` from the router crate.
|
pub requires_authentication: bool,
|
||||||
fn name() -> &'static str;
|
}
|
||||||
|
|
||||||
/// A human-readable description of the endpoint.
|
#[cfg(test)]
|
||||||
fn description() -> &'static str;
|
mod tests {
|
||||||
|
/// PUT /_matrix/client/r0/directory/room/:room_alias
|
||||||
/// Whether or not this endpoint requires an authenticated user.
|
pub mod create {
|
||||||
fn requires_authentication() -> bool;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
/// Whether or not this endpoint is rate limited.
|
use hyper::{Method, Request as HyperRequest, Response as HyperResponse, StatusCode};
|
||||||
fn rate_limited() -> bool;
|
use ruma_identifiers::{RoomAliasId, RoomId};
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
|
use super::super::{Endpoint as ApiEndpoint, Metadata};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Endpoint;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Error;
|
||||||
|
|
||||||
|
impl ApiEndpoint for Endpoint {
|
||||||
|
type Request = Request;
|
||||||
|
type Response = 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: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A request to create a new room alias.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Request {
|
||||||
|
pub room_id: RoomId, // body
|
||||||
|
pub room_alias: RoomAliasId, // path
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
struct RequestBody {
|
||||||
|
room_id: RoomId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Request> for HyperRequest {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(request: Request) -> Result<HyperRequest, Self::Error> {
|
||||||
|
let metadata = Endpoint::METADATA;
|
||||||
|
|
||||||
|
let path = metadata.path
|
||||||
|
.to_string()
|
||||||
|
.replace(":room_alias", &request.room_alias.to_string());
|
||||||
|
|
||||||
|
let mut hyper_request = HyperRequest::new(
|
||||||
|
metadata.method,
|
||||||
|
path.parse().map_err(|_| Error)?,
|
||||||
|
);
|
||||||
|
|
||||||
|
let request_body = RequestBody {
|
||||||
|
room_id: request.room_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
hyper_request.set_body(serde_json::to_vec(&request_body).map_err(|_| Error)?);
|
||||||
|
|
||||||
|
Ok(hyper_request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The response to a request to create a new room alias.
|
||||||
|
pub struct Response;
|
||||||
|
|
||||||
|
impl TryFrom<HyperResponse> for Response {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(hyper_response: HyperResponse) -> Result<Response, Self::Error> {
|
||||||
|
if hyper_response.status() == StatusCode::Ok {
|
||||||
|
Ok(Response)
|
||||||
|
} else {
|
||||||
|
Err(Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user