use rune::{Any, Module, Value, ContextError};
use rune::runtime::{Bytes, Protocol};
use std::fmt;
use std::fmt::Write;
pub fn module(_stdio: bool) -> Result<Module, ContextError> {
let mut module = Module::with_crate("http");
module.ty::<Client>()?;
module.ty::<Response>()?;
module.ty::<RequestBuilder>()?;
module.ty::<StatusCode>()?;
module.ty::<Error>()?;
module.function(["Client", "new"], Client::new)?;
module.async_function(["get"], get)?;
module.async_inst_fn("get", Client::get)?;
module.async_inst_fn("post", Client::post)?;
module.async_inst_fn("text", Response::text)?;
module.async_inst_fn("json", Response::json)?;
module.inst_fn("status", Response::status)?;
module.async_inst_fn("send", RequestBuilder::send)?;
module.inst_fn("header", RequestBuilder::header)?;
module.async_inst_fn("body_bytes", RequestBuilder::body_bytes)?;
module.inst_fn(Protocol::STRING_DISPLAY, Error::display)?;
module.inst_fn(Protocol::STRING_DISPLAY, StatusCode::display)?;
Ok(module)
}
#[derive(Debug, Any)]
pub struct Error {
inner: reqwest::Error,
}
impl From<reqwest::Error> for Error {
fn from(inner: reqwest::Error) -> Self {
Self { inner }
}
}
impl Error {
fn display(&self, buf: &mut String) -> fmt::Result {
write!(buf, "{}", self.inner)
}
}
#[derive(Debug, Any)]
struct Client {
client: reqwest::Client,
}
#[derive(Debug, Any)]
pub struct Response {
response: reqwest::Response,
}
#[derive(Debug, Any)]
pub struct StatusCode {
inner: reqwest::StatusCode,
}
impl StatusCode {
fn display(&self, buf: &mut String) -> fmt::Result {
write!(buf, "{}", self.inner)
}
}
impl Response {
async fn text(self) -> Result<String, Error> {
let text = self.response.text().await?;
Ok(text)
}
async fn json(self) -> Result<Value, Error> {
let text = self.response.json().await?;
Ok(text)
}
fn status(&self) -> StatusCode {
let inner = self.response.status();
StatusCode { inner }
}
}
#[derive(Debug, Any)]
pub struct RequestBuilder {
request: reqwest::RequestBuilder,
}
impl RequestBuilder {
async fn send(self) -> Result<Response, Error> {
let response = self.request.send().await?;
Ok(Response { response })
}
fn header(self, key: &str, value: &str) -> Self {
Self {
request: self.request.header(key, value),
}
}
async fn body_bytes(self, bytes: Bytes) -> Result<Self, Error> {
let bytes = bytes.into_vec();
Ok(Self {
request: self.request.body(bytes),
})
}
}
impl Client {
fn new() -> Self {
Self {
client: reqwest::Client::new(),
}
}
async fn get(&self, url: &str) -> Result<RequestBuilder, Error> {
let request = self.client.get(url);
Ok(RequestBuilder { request })
}
async fn post(&self, url: &str) -> Result<RequestBuilder, Error> {
let request = self.client.post(url);
Ok(RequestBuilder { request })
}
}
async fn get(url: &str) -> Result<Response, Error> {
Ok(Response {
response: reqwest::get(url).await?,
})
}