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
93
94
95
96
//! Interface to various endpoints of the RING HTTP API.

use std::borrow::Cow;
use serde::{ Serialize, Deserialize };
use reqwest::{ Method, header::HeaderMap };
pub use submit::*;
pub use status::*;
pub use result::*;

pub mod submit;
pub mod status;
pub mod result;

/// What body, if any, should be sent with a request?
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum RequestBody<T> {
    /// Do not send body or modify URL query parameters at all.
    None,
    /// Serialize value as JSON and send it in body.
    Json(T),
    /// Serialize value as query string and append it to URL query parameters.
    Query(T),
    /// Serialize value as x-www-form-urlencoded and send it in body.
    Form(T),
    /// Serialize value as multipart/form-data and send it in body.
    Multipart(T),
}

impl<T> Default for RequestBody<T> {
    fn default() -> Self {
        RequestBody::None
    }
}

/// A RING API request.
pub trait Request {
    /// The type of the body for this request. TODO(H2CO3): default to `()`.
    type Body: Serialize;

    /// The "return type" of the request.
    type Response: for<'de> Deserialize<'de>;

    /// The HTTP method ("verb") for the request.
    const METHOD: Method = Method::GET;

    /// The endpoint: the part of the URL/path that follows the base URL.
    fn endpoint(&self) -> Cow<str>;

    /// Additional headers for this request.
    fn headers(&self) -> HeaderMap {
        Default::default()
    }

    /// The body of the request, if any
    fn body(&self) -> RequestBody<&Self::Body> {
        Default::default()
    }
}

impl<R: Request> Request for &R {
    type Body = R::Body;
    type Response = R::Response;

    const METHOD: Method = R::METHOD;

    fn endpoint(&self) -> Cow<str> {
        (**self).endpoint()
    }

    fn headers(&self) -> HeaderMap {
        (**self).headers()
    }

    fn body(&self) -> RequestBody<&Self::Body> {
        (**self).body()
    }
}

impl<R: Request> Request for &mut R {
    type Body = R::Body;
    type Response = R::Response;

    const METHOD: Method = R::METHOD;

    fn endpoint(&self) -> Cow<str> {
        (**self).endpoint()
    }

    fn headers(&self) -> HeaderMap {
        (**self).headers()
    }

    fn body(&self) -> RequestBody<&Self::Body> {
        (**self).body()
    }
}