mlua/examples/async_http_client.rs

78 lines
2.1 KiB
Rust
Raw Normal View History

use std::collections::HashMap;
2020-05-05 21:32:05 -04:00
use std::sync::Arc;
2021-01-16 09:07:26 -05:00
use hyper::body::{Body as HyperBody, HttpBody as _};
use hyper::Client as HyperClient;
use tokio::sync::Mutex;
use mlua::{chunk, ExternalResult, Lua, Result, UserData, UserDataMethods};
2020-04-18 20:23:42 -04:00
#[derive(Clone)]
2020-05-05 21:32:05 -04:00
struct BodyReader(Arc<Mutex<HyperBody>>);
2020-04-18 20:23:42 -04:00
impl BodyReader {
fn new(body: HyperBody) -> Self {
2020-05-05 21:32:05 -04:00
BodyReader(Arc::new(Mutex::new(body)))
2020-04-18 20:23:42 -04:00
}
}
impl UserData for BodyReader {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
2021-06-03 18:52:29 -04:00
methods.add_async_method("read", |lua, reader, ()| async move {
2020-05-05 21:32:05 -04:00
let mut reader = reader.0.lock().await;
2021-01-16 09:07:26 -05:00
if let Some(bytes) = reader.data().await {
2021-06-03 18:52:29 -04:00
let bytes = bytes.to_lua_err()?;
return Some(lua.create_string(&bytes)).transpose();
2020-04-18 20:23:42 -04:00
}
Ok(None)
});
}
}
#[tokio::main]
async fn main() -> Result<()> {
let lua = Lua::new();
let fetch_url = lua.create_async_function(|lua, uri: String| async move {
let client = HyperClient::new();
2021-06-03 18:52:29 -04:00
let uri = uri.parse().to_lua_err()?;
let resp = client.get(uri).await.to_lua_err()?;
let lua_resp = lua.create_table()?;
lua_resp.set("status", resp.status().as_u16())?;
let mut headers = HashMap::new();
2021-06-03 18:52:29 -04:00
for (key, value) in resp.headers() {
headers
.entry(key.as_str())
.or_insert(Vec::new())
2021-06-03 18:52:29 -04:00
.push(value.to_str().to_lua_err()?);
}
2020-04-18 20:23:42 -04:00
lua_resp.set("headers", headers)?;
lua_resp.set("body", BodyReader::new(resp.into_body()))?;
Ok(lua_resp)
})?;
2020-04-18 20:23:42 -04:00
let f = lua
.load(chunk! {
local res = $fetch_url(...)
2020-04-18 20:23:42 -04:00
print(res.status)
for key, vals in pairs(res.headers) do
for _, val in ipairs(vals) do
print(key..": "..val)
end
end
repeat
local body = res.body:read()
if body then
print(body)
end
2020-04-18 20:23:42 -04:00
until not body
})
2020-04-18 20:23:42 -04:00
.into_function()?;
2020-04-18 20:23:42 -04:00
f.call_async("http://httpbin.org/ip").await
}