mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-18 07:11:53 +03:00
Merge pull request #885 from AleoHQ/feature-custom-api-route
[CLI] Allow setting custom API endpoint in ENV
This commit is contained in:
commit
4024c1a9b5
44
leo/api.rs
44
leo/api.rs
@ -22,25 +22,24 @@ use reqwest::{
|
|||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Trait describes API Routes and Request bodies, struct which implements
|
/// API Routes and Request bodies.
|
||||||
/// Route MUST also support Serialize to be usable in Api::run_route(r: Route)
|
/// Structs that implement Route MUST also support Serialize to be usable in Api::run_route(r: Route)
|
||||||
pub trait Route {
|
pub trait Route {
|
||||||
/// Whether to use bearer auth or not. Some routes may have additional
|
/// [`true`] if a route supports bearer authentication.
|
||||||
/// features for logged-in users, so authorization token should be sent
|
/// For example, the login route.
|
||||||
/// if it is created of course
|
|
||||||
const AUTH: bool;
|
const AUTH: bool;
|
||||||
|
|
||||||
/// HTTP method to use when requesting
|
/// The HTTP method to use when requesting.
|
||||||
const METHOD: Method;
|
const METHOD: Method;
|
||||||
|
|
||||||
/// URL path without first forward slash (e.g. v1/package/fetch)
|
/// The URL path without the first forward slash (e.g. v1/package/fetch)
|
||||||
const PATH: &'static str;
|
const PATH: &'static str;
|
||||||
|
|
||||||
/// Output type for this route. For login it is simple - String
|
/// The output type for this route. For example, the login route output is [`String`].
|
||||||
/// But for other routes may be more complex.
|
/// But for other routes may be more complex.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Process reqwest Response and turn it into Output
|
/// Process the reqwest Response and turn it into an Output.
|
||||||
fn process(&self, res: Response) -> Result<Self::Output>;
|
fn process(&self, res: Response) -> Result<Self::Output>;
|
||||||
|
|
||||||
/// Transform specific status codes into correct errors for this route.
|
/// Transform specific status codes into correct errors for this route.
|
||||||
@ -50,18 +49,18 @@ pub trait Route {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// REST API handler with reqwest::blocking inside
|
/// REST API handler with reqwest::blocking inside.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Api {
|
pub struct Api {
|
||||||
host: String,
|
host: String,
|
||||||
client: Client,
|
client: Client,
|
||||||
/// Authorization token for API requests
|
/// Authorization token for API requests.
|
||||||
auth_token: Option<String>,
|
auth_token: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Api {
|
impl Api {
|
||||||
/// Create new instance of API, set host and Client is going to be
|
/// Returns a new instance of API.
|
||||||
/// created and set automatically
|
/// The set host and Client are created automatically.
|
||||||
pub fn new(host: String, auth_token: Option<String>) -> Api {
|
pub fn new(host: String, auth_token: Option<String>) -> Api {
|
||||||
Api {
|
Api {
|
||||||
client: Client::new(),
|
client: Client::new(),
|
||||||
@ -70,18 +69,23 @@ impl Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get token for bearer auth, should be passed into Api through Context
|
pub fn host(&self) -> &str {
|
||||||
|
&*self.host
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the token for bearer auth, otherwise None.
|
||||||
|
/// The [`auth_token`] should be passed into the Api through Context.
|
||||||
pub fn auth_token(&self) -> Option<String> {
|
pub fn auth_token(&self) -> Option<String> {
|
||||||
self.auth_token.clone()
|
self.auth_token.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set authorization token for future requests
|
/// Set the authorization token for future requests.
|
||||||
pub fn set_auth_token(&mut self, token: String) {
|
pub fn set_auth_token(&mut self, token: String) {
|
||||||
self.auth_token = Some(token);
|
self.auth_token = Some(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run specific route struct. Turn struct into request body
|
/// Run specific route struct. Turn struct into request body
|
||||||
/// and use type constants and Route implementation to get request params
|
/// and use type constants and Route implementation to get request params.
|
||||||
pub fn run_route<T>(&self, route: T) -> Result<T::Output>
|
pub fn run_route<T>(&self, route: T) -> Result<T::Output>
|
||||||
where
|
where
|
||||||
T: Route,
|
T: Route,
|
||||||
@ -100,7 +104,9 @@ impl Api {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// only one error is possible here
|
// only one error is possible here
|
||||||
let res = res.send().map_err(|_| anyhow!("Unable to connect to Aleo PM"))?;
|
let res = res.send().map_err(|_| {
|
||||||
|
anyhow!("Unable to connect to Aleo PM. If you specified custom API endpoint, then check the URL for errors")
|
||||||
|
})?;
|
||||||
|
|
||||||
// where magic begins
|
// where magic begins
|
||||||
route.process(res)
|
route.process(res)
|
||||||
@ -143,7 +149,7 @@ impl Route for Fetch {
|
|||||||
// TODO: we should return 404 on not found author/package
|
// TODO: we should return 404 on not found author/package
|
||||||
// and return BAD_REQUEST if data format is incorrect or some of the arguments
|
// and return BAD_REQUEST if data format is incorrect or some of the arguments
|
||||||
// were not passed
|
// were not passed
|
||||||
StatusCode::NOT_FOUND => anyhow!("Package is hidden"),
|
StatusCode::NOT_FOUND => anyhow!("Package not found"),
|
||||||
_ => anyhow!("Unknown API error: {}", status),
|
_ => anyhow!("Unknown API error: {}", status),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,7 +189,7 @@ impl Route for Login {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Handler for 'my_profile' route. Meant to be used to get profile details but
|
/// Handler for 'my_profile' route. Meant to be used to get profile details but
|
||||||
/// in current application is used to check if user is logged in. Any non-200 response
|
/// in the current application it is used to check if the user is logged in. Any non-200 response
|
||||||
/// is treated as Unauthorized.
|
/// is treated as Unauthorized.
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Profile {}
|
pub struct Profile {}
|
||||||
|
@ -15,10 +15,7 @@
|
|||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use super::build::Build;
|
use super::build::Build;
|
||||||
use crate::{
|
use crate::{commands::Command, context::Context};
|
||||||
commands::Command,
|
|
||||||
context::{Context, PACKAGE_MANAGER_URL},
|
|
||||||
};
|
|
||||||
use leo_package::{
|
use leo_package::{
|
||||||
outputs::OutputsDirectory,
|
outputs::OutputsDirectory,
|
||||||
root::{ZipFile, AUTHOR_PLACEHOLDER},
|
root::{ZipFile, AUTHOR_PLACEHOLDER},
|
||||||
@ -118,7 +115,7 @@ impl Command for Publish {
|
|||||||
|
|
||||||
// Make a request to publish a package
|
// Make a request to publish a package
|
||||||
let response = client
|
let response = client
|
||||||
.post(format!("{}{}", PACKAGE_MANAGER_URL, PUBLISH_URL).as_str())
|
.post(format!("{}{}", context.api.host(), PUBLISH_URL).as_str())
|
||||||
.headers(headers)
|
.headers(headers)
|
||||||
.multipart(form_data)
|
.multipart(form_data)
|
||||||
.send();
|
.send();
|
||||||
|
@ -48,19 +48,19 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new context for the current directory.
|
/// Create a new context for the current directory.
|
||||||
pub fn create_context(path: PathBuf) -> Result<Context> {
|
pub fn create_context(path: PathBuf, api_url: Option<String>) -> Result<Context> {
|
||||||
let token = config::read_token().ok();
|
let token = config::read_token().ok();
|
||||||
|
|
||||||
let api = Api::new(PACKAGE_MANAGER_URL.to_string(), token);
|
let api = Api::new(api_url.unwrap_or_else(|| PACKAGE_MANAGER_URL.to_string()), token);
|
||||||
|
|
||||||
Ok(Context { api, path: Some(path) })
|
Ok(Context { api, path: Some(path) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns project context.
|
/// Returns project context.
|
||||||
pub fn get_context() -> Result<Context> {
|
pub fn get_context(api_url: Option<String>) -> Result<Context> {
|
||||||
let token = config::read_token().ok();
|
let token = config::read_token().ok();
|
||||||
|
|
||||||
let api = Api::new(PACKAGE_MANAGER_URL.to_string(), token);
|
let api = Api::new(api_url.unwrap_or_else(|| PACKAGE_MANAGER_URL.to_string()), token);
|
||||||
|
|
||||||
Ok(Context { api, path: None })
|
Ok(Context { api, path: None })
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,9 @@ struct Opt {
|
|||||||
#[structopt(subcommand)]
|
#[structopt(subcommand)]
|
||||||
command: CommandOpts,
|
command: CommandOpts,
|
||||||
|
|
||||||
|
#[structopt(help = "Custom Aleo PM backend URL", env = "APM_URL")]
|
||||||
|
api: Option<String>,
|
||||||
|
|
||||||
#[structopt(
|
#[structopt(
|
||||||
long,
|
long,
|
||||||
global = true,
|
global = true,
|
||||||
@ -192,8 +195,8 @@ fn main() {
|
|||||||
// Get custom root folder and create context for it.
|
// Get custom root folder and create context for it.
|
||||||
// If not specified, default context will be created in cwd.
|
// If not specified, default context will be created in cwd.
|
||||||
let context = handle_error(match opt.path {
|
let context = handle_error(match opt.path {
|
||||||
Some(path) => context::create_context(path),
|
Some(path) => context::create_context(path, opt.api),
|
||||||
None => context::get_context(),
|
None => context::get_context(opt.api),
|
||||||
});
|
});
|
||||||
|
|
||||||
handle_error(match opt.command {
|
handle_error(match opt.command {
|
||||||
|
@ -152,7 +152,7 @@ pub fn leo_update_and_update_automatic() -> Result<()> {
|
|||||||
/// Create context for Pedersen Hash example
|
/// Create context for Pedersen Hash example
|
||||||
fn context() -> Result<Context> {
|
fn context() -> Result<Context> {
|
||||||
let path = PathBuf::from(&PEDERSEN_HASH_PATH);
|
let path = PathBuf::from(&PEDERSEN_HASH_PATH);
|
||||||
let context = create_context(path)?;
|
let context = create_context(path, None)?;
|
||||||
|
|
||||||
Ok(context)
|
Ok(context)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user