2020-04-18 20:23:42 -04:00
|
|
|
use std::cell::RefCell;
|
2020-04-17 17:38:01 -04:00
|
|
|
use std::collections::HashMap;
|
2020-04-18 20:23:42 -04:00
|
|
|
use std::rc::Rc;
|
2020-04-17 17:38:01 -04:00
|
|
|
|
2020-04-18 20:23:42 -04:00
|
|
|
use bstr::BString;
|
|
|
|
use hyper::{body::Body as HyperBody, Client as HyperClient};
|
|
|
|
use tokio::stream::StreamExt;
|
2020-04-17 17:38:01 -04:00
|
|
|
|
2020-04-18 20:23:42 -04:00
|
|
|
use mlua::{Error, Lua, Result, UserData, UserDataMethods};
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
struct BodyReader(Rc<RefCell<HyperBody>>);
|
|
|
|
|
|
|
|
impl BodyReader {
|
|
|
|
fn new(body: HyperBody) -> Self {
|
|
|
|
BodyReader(Rc::new(RefCell::new(body)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UserData for BodyReader {
|
|
|
|
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
|
|
|
methods.add_async_method("read", |_, reader, ()| async move {
|
|
|
|
let mut reader = reader.0.borrow_mut();
|
|
|
|
let bytes = reader.try_next().await.map_err(Error::external)?;
|
|
|
|
if let Some(bytes) = bytes {
|
|
|
|
return Ok(Some(BString::from(bytes.as_ref())));
|
|
|
|
}
|
|
|
|
Ok(None)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2020-04-17 17:38:01 -04:00
|
|
|
|
|
|
|
#[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();
|
|
|
|
let uri = uri.parse().map_err(Error::external)?;
|
|
|
|
let resp = client.get(uri).await.map_err(Error::external)?;
|
|
|
|
|
|
|
|
let lua_resp = lua.create_table()?;
|
|
|
|
lua_resp.set("status", resp.status().as_u16())?;
|
|
|
|
|
|
|
|
let mut headers = HashMap::new();
|
|
|
|
for (key, value) in resp.headers().iter() {
|
2020-04-17 17:43:50 -04:00
|
|
|
headers
|
|
|
|
.entry(key.as_str())
|
|
|
|
.or_insert(Vec::new())
|
|
|
|
.push(value.to_str().unwrap());
|
2020-04-17 17:38:01 -04:00
|
|
|
}
|
|
|
|
|
2020-04-18 20:23:42 -04:00
|
|
|
lua_resp.set("headers", headers)?;
|
|
|
|
lua_resp.set("body", BodyReader::new(resp.into_body()))?;
|
2020-04-17 17:38:01 -04:00
|
|
|
|
|
|
|
Ok(lua_resp)
|
|
|
|
})?;
|
|
|
|
|
|
|
|
let globals = lua.globals();
|
|
|
|
globals.set("fetch_url", fetch_url)?;
|
|
|
|
|
2020-04-18 20:23:42 -04:00
|
|
|
let f = lua
|
2020-04-17 17:38:01 -04:00
|
|
|
.load(
|
|
|
|
r#"
|
2020-04-18 20:23:42 -04:00
|
|
|
local res = fetch_url(...);
|
|
|
|
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)
|
2020-04-17 17:38:01 -04:00
|
|
|
end
|
2020-04-18 20:23:42 -04:00
|
|
|
until not body
|
2020-04-17 17:38:01 -04:00
|
|
|
"#,
|
|
|
|
)
|
2020-04-18 20:23:42 -04:00
|
|
|
.into_function()?;
|
2020-04-17 17:38:01 -04:00
|
|
|
|
2020-04-18 20:23:42 -04:00
|
|
|
f.call_async("http://httpbin.org/ip").await
|
2020-04-17 17:38:01 -04:00
|
|
|
}
|