Introduce HttpSend trait for converting Request -> Response
Parameterize everything that involves sending HTTP requests with the `H: HttpSend` bound. This will allow us to swap out `HttpSend` implementations when necessary, in order to better test our code
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use page::Page;
|
||||
use http_send::HttpSend;
|
||||
use serde::Deserialize;
|
||||
|
||||
/// Abstracts away the `next_page` logic into a single stream of items
|
||||
@@ -23,15 +24,15 @@ use serde::Deserialize;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub(crate) struct ItemsIter<'a, T: Clone + for<'de> Deserialize<'de>> {
|
||||
page: Page<'a, T>,
|
||||
pub(crate) struct ItemsIter<'a, T: Clone + for<'de> Deserialize<'de>, H: 'a + HttpSend> {
|
||||
page: Page<'a, T, H>,
|
||||
buffer: Vec<T>,
|
||||
cur_idx: usize,
|
||||
use_initial: bool,
|
||||
}
|
||||
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> {
|
||||
pub(crate) fn new(page: Page<'a, T>) -> ItemsIter<'a, T> {
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> ItemsIter<'a, T, H> {
|
||||
pub(crate) fn new(page: Page<'a, T, H>) -> ItemsIter<'a, T, H> {
|
||||
ItemsIter {
|
||||
page,
|
||||
buffer: vec![],
|
||||
@@ -60,7 +61,7 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>> Iterator for ItemsIter<'a, T> {
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> Iterator for ItemsIter<'a, T, H> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
use Result;
|
||||
use reqwest::{Client, Request, RequestBuilder, Response};
|
||||
|
||||
pub trait HttpSend {
|
||||
fn execute(&self, client: &Client, request: Request) -> Result<Response>;
|
||||
fn send(&self, client: &Client, builder: &mut RequestBuilder) -> Result<Response> {
|
||||
let request = builder.build()?;
|
||||
self.execute(client, request)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HttpSender;
|
||||
|
||||
impl HttpSend for HttpSender {
|
||||
fn execute(&self, client: &Client, request: Request) -> Result<Response> {
|
||||
Ok(client.execute(request)?)
|
||||
}
|
||||
}
|
||||
+63
-46
@@ -50,10 +50,12 @@ use reqwest::{
|
||||
header::{Authorization, Bearer, Headers},
|
||||
Client,
|
||||
Response,
|
||||
RequestBuilder,
|
||||
};
|
||||
|
||||
use entities::prelude::*;
|
||||
use page::Page;
|
||||
use http_send::{HttpSend, HttpSender};
|
||||
|
||||
pub use data::Data;
|
||||
pub use errors::{ApiError, Error, Result};
|
||||
@@ -69,6 +71,8 @@ pub mod data;
|
||||
pub mod entities;
|
||||
/// Errors
|
||||
pub mod errors;
|
||||
/// Contains trait for converting `reqwest::Request`s to `reqwest::Response`s
|
||||
pub mod http_send;
|
||||
/// Handling multiple pages of entities.
|
||||
pub mod page;
|
||||
/// Registering your app.
|
||||
@@ -90,8 +94,9 @@ pub mod prelude {
|
||||
|
||||
/// Your mastodon application client, handles all requests to and from Mastodon.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Mastodon {
|
||||
pub struct Mastodon<H: HttpSend = HttpSender> {
|
||||
client: Client,
|
||||
http_sender: H,
|
||||
headers: Headers,
|
||||
/// Raw data about your mastodon instance.
|
||||
pub data: Data,
|
||||
@@ -100,35 +105,35 @@ pub struct Mastodon {
|
||||
/// Represents the set of methods that a Mastodon Client can do, so that
|
||||
/// implementations might be swapped out for testing
|
||||
#[allow(unused)]
|
||||
pub trait MastodonClient {
|
||||
fn favourites(&self) -> Result<Page<Status>> {
|
||||
pub trait MastodonClient<H: HttpSend = HttpSender> {
|
||||
fn favourites(&self) -> Result<Page<Status, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn blocks(&self) -> Result<Page<Account>> {
|
||||
fn blocks(&self) -> Result<Page<Account, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn domain_blocks(&self) -> Result<Page<String>> {
|
||||
fn domain_blocks(&self) -> Result<Page<String, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn follow_requests(&self) -> Result<Page<Account>> {
|
||||
fn follow_requests(&self) -> Result<Page<Account, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn get_home_timeline(&self) -> Result<Page<Status>> {
|
||||
fn get_home_timeline(&self) -> Result<Page<Status, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn get_emojis(&self) -> Result<Page<Emoji>> {
|
||||
fn get_emojis(&self) -> Result<Page<Emoji, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn mutes(&self) -> Result<Page<Account>> {
|
||||
fn mutes(&self) -> Result<Page<Account, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn notifications(&self) -> Result<Page<Notification>> {
|
||||
fn notifications(&self) -> Result<Page<Notification, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn reports(&self) -> Result<Page<Report>> {
|
||||
fn reports(&self) -> Result<Page<Report, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn followers(&self, id: &str) -> Result<Page<Account>> {
|
||||
fn followers(&self, id: &str) -> Result<Page<Account, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn following(&self) -> Result<Account> {
|
||||
@@ -233,13 +238,13 @@ pub trait MastodonClient {
|
||||
fn get_tagged_timeline(&self, hashtag: String, local: bool) -> Result<Vec<Status>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>>
|
||||
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status, H>>
|
||||
where
|
||||
S: Into<Option<StatusesRequest<'a>>>,
|
||||
{
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship>> {
|
||||
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
fn search_accounts(
|
||||
@@ -247,25 +252,30 @@ pub trait MastodonClient {
|
||||
query: &str,
|
||||
limit: Option<u64>,
|
||||
following: bool,
|
||||
) -> Result<Page<Account>> {
|
||||
) -> Result<Page<Account, H>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
impl Mastodon {
|
||||
impl<H: HttpSend> Mastodon<H> {
|
||||
methods![get, post, delete,];
|
||||
|
||||
fn route(&self, url: &str) -> String {
|
||||
let mut s = (*self.base).to_owned();
|
||||
s += url;
|
||||
s
|
||||
format!("{}{}", self.base, url)
|
||||
}
|
||||
|
||||
pub(crate) fn send(&self, req: &mut RequestBuilder) -> Result<Response> {
|
||||
Ok(self.http_sender.send(
|
||||
&self.client,
|
||||
req.headers(self.headers.clone())
|
||||
)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Data> for Mastodon {
|
||||
impl From<Data> for Mastodon<HttpSender> {
|
||||
/// Creates a mastodon instance from the data struct.
|
||||
fn from(data: Data) -> Mastodon {
|
||||
let mut builder = MastodonBuilder::new();
|
||||
fn from(data: Data) -> Mastodon<HttpSender> {
|
||||
let mut builder = MastodonBuilder::new(HttpSender);
|
||||
builder.data(data);
|
||||
builder
|
||||
.build()
|
||||
@@ -273,7 +283,7 @@ impl From<Data> for Mastodon {
|
||||
}
|
||||
}
|
||||
|
||||
impl MastodonClient for Mastodon {
|
||||
impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
|
||||
paged_routes! {
|
||||
(get) favourites: "favourites" => Status,
|
||||
(get) blocks: "blocks" => Account,
|
||||
@@ -328,12 +338,11 @@ impl MastodonClient for Mastodon {
|
||||
|
||||
fn update_credentials(&self, changes: CredientialsBuilder) -> Result<Account> {
|
||||
let url = self.route("/api/v1/accounts/update_credentials");
|
||||
let response = self
|
||||
.client
|
||||
.patch(&url)
|
||||
.headers(self.headers.clone())
|
||||
.multipart(changes.into_form()?)
|
||||
.send()?;
|
||||
let response = self.send(
|
||||
self.client
|
||||
.patch(&url)
|
||||
.multipart(changes.into_form()?)
|
||||
)?;
|
||||
|
||||
let status = response.status().clone();
|
||||
|
||||
@@ -348,12 +357,11 @@ impl MastodonClient for Mastodon {
|
||||
|
||||
/// Post a new status to the account.
|
||||
fn new_status(&self, status: StatusBuilder) -> Result<Status> {
|
||||
let response = self
|
||||
.client
|
||||
.post(&self.route("/api/v1/statuses"))
|
||||
.headers(self.headers.clone())
|
||||
.json(&status)
|
||||
.send()?;
|
||||
let response = self.send(
|
||||
self.client
|
||||
.post(&self.route("/api/v1/statuses"))
|
||||
.json(&status)
|
||||
)?;
|
||||
|
||||
deserialise(response)
|
||||
}
|
||||
@@ -423,7 +431,7 @@ impl MastodonClient for Mastodon {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>>
|
||||
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status, H>>
|
||||
where
|
||||
S: Into<Option<StatusesRequest<'a>>>,
|
||||
{
|
||||
@@ -433,14 +441,16 @@ impl MastodonClient for Mastodon {
|
||||
url = format!("{}{}", url, request.to_querystring());
|
||||
}
|
||||
|
||||
let response = self.client.get(&url).headers(self.headers.clone()).send()?;
|
||||
let response = self.send(
|
||||
&mut self.client.get(&url)
|
||||
)?;
|
||||
|
||||
Page::new(self, response)
|
||||
}
|
||||
|
||||
/// Returns the client account's relationship to a list of other accounts.
|
||||
/// Such as whether they follow them or vice versa.
|
||||
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship>> {
|
||||
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship, H>> {
|
||||
let mut url = self.route("/api/v1/accounts/relationships?");
|
||||
|
||||
if ids.len() == 1 {
|
||||
@@ -455,7 +465,9 @@ impl MastodonClient for Mastodon {
|
||||
url.pop();
|
||||
}
|
||||
|
||||
let response = self.client.get(&url).headers(self.headers.clone()).send()?;
|
||||
let response = self.send(
|
||||
&mut self.client.get(&url)
|
||||
)?;
|
||||
|
||||
Page::new(self, response)
|
||||
}
|
||||
@@ -468,7 +480,7 @@ impl MastodonClient for Mastodon {
|
||||
query: &str,
|
||||
limit: Option<u64>,
|
||||
following: bool,
|
||||
) -> Result<Page<Account>> {
|
||||
) -> Result<Page<Account, H>> {
|
||||
let url = format!(
|
||||
"{}/api/v1/accounts/search?q={}&limit={}&following={}",
|
||||
self.base,
|
||||
@@ -477,13 +489,15 @@ impl MastodonClient for Mastodon {
|
||||
following
|
||||
);
|
||||
|
||||
let response = self.client.get(&url).headers(self.headers.clone()).send()?;
|
||||
let response = self.send(
|
||||
&mut self.client.get(&url)
|
||||
)?;
|
||||
|
||||
Page::new(self, response)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Deref for Mastodon {
|
||||
impl<H: HttpSend> ops::Deref for Mastodon<H> {
|
||||
type Target = Data;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@@ -491,14 +505,16 @@ impl ops::Deref for Mastodon {
|
||||
}
|
||||
}
|
||||
|
||||
struct MastodonBuilder {
|
||||
struct MastodonBuilder<H: HttpSend> {
|
||||
client: Option<Client>,
|
||||
http_sender: H,
|
||||
data: Option<Data>,
|
||||
}
|
||||
|
||||
impl MastodonBuilder {
|
||||
pub fn new() -> Self {
|
||||
impl<H: HttpSend> MastodonBuilder<H> {
|
||||
pub fn new(sender: H) -> Self {
|
||||
MastodonBuilder {
|
||||
http_sender: sender,
|
||||
client: None,
|
||||
data: None,
|
||||
}
|
||||
@@ -515,7 +531,7 @@ impl MastodonBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<Mastodon> {
|
||||
pub fn build(self) -> Result<Mastodon<H>> {
|
||||
Ok(if let Some(data) = self.data {
|
||||
let mut headers = Headers::new();
|
||||
headers.set(Authorization(Bearer {
|
||||
@@ -524,6 +540,7 @@ impl MastodonBuilder {
|
||||
|
||||
Mastodon {
|
||||
client: self.client.unwrap_or_else(|| Client::new()),
|
||||
http_sender: self.http_sender,
|
||||
headers,
|
||||
data,
|
||||
}
|
||||
|
||||
+20
-19
@@ -4,9 +4,9 @@ macro_rules! methods {
|
||||
fn $method<T: for<'de> serde::Deserialize<'de>>(&self, url: String)
|
||||
-> Result<T>
|
||||
{
|
||||
let response = self.client.$method(&url)
|
||||
.headers(self.headers.clone())
|
||||
.send()?;
|
||||
let response = self.send(
|
||||
&mut self.client.$method(&url)
|
||||
)?;
|
||||
|
||||
deserialise(response)
|
||||
}
|
||||
@@ -22,11 +22,11 @@ macro_rules! paged_routes {
|
||||
"Equivalent to `/api/v1/",
|
||||
$url,
|
||||
"`\n# Errors\nIf `access_token` is not set."),
|
||||
fn $name(&self) -> Result<Page<$ret>> {
|
||||
fn $name(&self) -> Result<Page<$ret, H>> {
|
||||
let url = self.route(concat!("/api/v1/", $url));
|
||||
let response = self.client.$method(&url)
|
||||
.headers(self.headers.clone())
|
||||
.send()?;
|
||||
let response = self.send(
|
||||
&mut self.client.$method(&url)
|
||||
)?;
|
||||
|
||||
Page::new(self, response)
|
||||
}
|
||||
@@ -55,10 +55,11 @@ macro_rules! route {
|
||||
.file(stringify!($param), $param.as_ref())?
|
||||
)*;
|
||||
|
||||
let response = self.client.post(&self.route(concat!("/api/v1/", $url)))
|
||||
.headers(self.headers.clone())
|
||||
.multipart(form_data)
|
||||
.send()?;
|
||||
let response = self.send(
|
||||
self.client
|
||||
.post(&self.route(concat!("/api/v1/", $url)))
|
||||
.multipart(form_data)
|
||||
)?;
|
||||
|
||||
let status = response.status().clone();
|
||||
|
||||
@@ -90,10 +91,10 @@ macro_rules! route {
|
||||
)*
|
||||
});
|
||||
|
||||
let response = self.client.$method(&self.route(concat!("/api/v1/", $url)))
|
||||
.headers(self.headers.clone())
|
||||
.json(&form_data)
|
||||
.send()?;
|
||||
let response = self.send(
|
||||
self.client.$method(&self.route(concat!("/api/v1/", $url)))
|
||||
.json(&form_data)
|
||||
)?;
|
||||
|
||||
let status = response.status().clone();
|
||||
|
||||
@@ -152,11 +153,11 @@ macro_rules! paged_routes_with_id {
|
||||
"Equivalent to `/api/v1/",
|
||||
$url,
|
||||
"`\n# Errors\nIf `access_token` is not set."),
|
||||
fn $name(&self, id: &str) -> Result<Page<$ret>> {
|
||||
fn $name(&self, id: &str) -> Result<Page<$ret, H>> {
|
||||
let url = self.route(&format!(concat!("/api/v1/", $url), id));
|
||||
let response = self.client.$method(&url)
|
||||
.headers(self.headers.clone())
|
||||
.send()?;
|
||||
let response = self.send(
|
||||
&mut self.client.$method(&url)
|
||||
)?;
|
||||
|
||||
Page::new(self, response)
|
||||
}
|
||||
|
||||
+10
-8
@@ -7,8 +7,10 @@ use reqwest::{
|
||||
use serde::Deserialize;
|
||||
use url::Url;
|
||||
|
||||
pub struct Page<'a, T: for<'de> Deserialize<'de>> {
|
||||
mastodon: &'a Mastodon,
|
||||
use http_send::HttpSend;
|
||||
|
||||
pub struct Page<'a, T: for<'de> Deserialize<'de>, H: 'a + HttpSend> {
|
||||
mastodon: &'a Mastodon<H>,
|
||||
next: Option<Url>,
|
||||
prev: Option<Url>,
|
||||
/// Initial set of items
|
||||
@@ -25,9 +27,9 @@ macro_rules! pages {
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let response = self.mastodon.client.get(url)
|
||||
.headers(self.mastodon.headers.clone())
|
||||
.send()?;
|
||||
let response = self.mastodon.send(
|
||||
&mut self.mastodon.client.get(url)
|
||||
)?;
|
||||
|
||||
let (prev, next) = get_links(&response)?;
|
||||
self.next = next;
|
||||
@@ -39,13 +41,13 @@ macro_rules! pages {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: for<'de> Deserialize<'de>> Page<'a, T> {
|
||||
impl<'a, T: for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
|
||||
pages! {
|
||||
next: next_page,
|
||||
prev: prev_page
|
||||
}
|
||||
|
||||
pub fn new(mastodon: &'a Mastodon, response: Response) -> Result<Self> {
|
||||
pub fn new(mastodon: &'a Mastodon<H>, response: Response) -> Result<Self> {
|
||||
let (prev, next) = get_links(&response)?;
|
||||
Ok(Page {
|
||||
initial_items: deserialise(response)?,
|
||||
@@ -56,7 +58,7 @@ impl<'a, T: for<'de> Deserialize<'de>> Page<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>> Page<'a, T> {
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
|
||||
/// Returns an iterator that provides a stream of `T`s
|
||||
///
|
||||
/// This abstracts away the process of iterating over each item in a page,
|
||||
|
||||
+44
-10
@@ -1,4 +1,4 @@
|
||||
use reqwest::Client;
|
||||
use reqwest::{Client, RequestBuilder, Response};
|
||||
use try_from::TryInto;
|
||||
|
||||
use apps::{App, Scopes};
|
||||
@@ -7,12 +7,14 @@ use Error;
|
||||
use Mastodon;
|
||||
use MastodonBuilder;
|
||||
use Result;
|
||||
use http_send::{HttpSend, HttpSender};
|
||||
|
||||
/// Handles registering your mastodon app to your instance. It is recommended
|
||||
/// you cache your data struct to avoid registering on every run.
|
||||
pub struct Registration {
|
||||
pub struct Registration<H: HttpSend> {
|
||||
base: String,
|
||||
client: Client,
|
||||
http_sender: H,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -32,7 +34,7 @@ struct AccessToken {
|
||||
access_token: String,
|
||||
}
|
||||
|
||||
impl Registration {
|
||||
impl Registration<HttpSender> {
|
||||
/// Construct a new registration process to the instance of the `base` url.
|
||||
/// ```
|
||||
/// use elefren::apps::prelude::*;
|
||||
@@ -43,8 +45,27 @@ impl Registration {
|
||||
Registration {
|
||||
base: base.into(),
|
||||
client: Client::new(),
|
||||
http_sender: HttpSender,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: HttpSend> Registration<H> {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn with_sender<I: Into<String>>(base: I, http_sender: H) -> Self {
|
||||
Registration {
|
||||
base: base.into(),
|
||||
client: Client::new(),
|
||||
http_sender: http_sender,
|
||||
}
|
||||
}
|
||||
|
||||
fn send(&self, req: &mut RequestBuilder) -> Result<Response> {
|
||||
Ok(self.http_sender.send(
|
||||
&self.client,
|
||||
req
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Register the application with the server from the `base` url.
|
||||
///
|
||||
@@ -69,13 +90,15 @@ impl Registration {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn register<I: TryInto<App>>(self, app: I) -> Result<Registered>
|
||||
pub fn register<I: TryInto<App>>(self, app: I) -> Result<Registered<H>>
|
||||
where
|
||||
Error: From<<I as TryInto<App>>::Err>,
|
||||
{
|
||||
let app = app.try_into()?;
|
||||
let url = format!("{}/api/v1/apps", self.base);
|
||||
let oauth: OAuth = self.client.post(&url).form(&app).send()?.json()?;
|
||||
let oauth: OAuth = self.send(
|
||||
self.client.post(&url).form(&app)
|
||||
)?.json()?;
|
||||
|
||||
Ok(Registered {
|
||||
base: self.base,
|
||||
@@ -84,11 +107,19 @@ impl Registration {
|
||||
client_secret: oauth.client_secret,
|
||||
redirect: oauth.redirect_uri,
|
||||
scopes: app.scopes(),
|
||||
http_sender: self.http_sender,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Registered {
|
||||
impl<H: HttpSend> Registered<H> {
|
||||
fn send(&self, req: &mut RequestBuilder) -> Result<Response> {
|
||||
Ok(self.http_sender.send(
|
||||
&self.client,
|
||||
req
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Returns the full url needed for authorisation. This needs to be opened
|
||||
/// in a browser.
|
||||
pub fn authorize_url(&self) -> Result<String> {
|
||||
@@ -102,7 +133,7 @@ impl Registered {
|
||||
|
||||
/// Create an access token from the client id, client secret, and code
|
||||
/// provided by the authorisation url.
|
||||
pub fn complete(self, code: String) -> Result<Mastodon> {
|
||||
pub fn complete(self, code: String) -> Result<Mastodon<H>> {
|
||||
let url = format!(
|
||||
"{}/oauth/token?client_id={}&client_secret={}&code={}&grant_type=authorization_code&redirect_uri={}",
|
||||
self.base,
|
||||
@@ -112,7 +143,9 @@ impl Registered {
|
||||
self.redirect
|
||||
);
|
||||
|
||||
let token: AccessToken = self.client.post(&url).send()?.json()?;
|
||||
let token: AccessToken = self.send(
|
||||
&mut self.client.post(&url)
|
||||
)?.json()?;
|
||||
|
||||
let data = Data {
|
||||
base: self.base.into(),
|
||||
@@ -122,17 +155,18 @@ impl Registered {
|
||||
token: token.access_token.into(),
|
||||
};
|
||||
|
||||
let mut builder = MastodonBuilder::new();
|
||||
let mut builder = MastodonBuilder::new(self.http_sender);
|
||||
builder.client(self.client).data(data);
|
||||
Ok(builder.build()?)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Registered {
|
||||
pub struct Registered<H: HttpSend> {
|
||||
base: String,
|
||||
client: Client,
|
||||
client_id: String,
|
||||
client_secret: String,
|
||||
redirect: String,
|
||||
scopes: Scopes,
|
||||
http_sender: H,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user