mirror of
https://github.com/lune-org/lune.git
synced 2025-05-04 10:43:57 +01:00
Initial working request function in net
This commit is contained in:
parent
f9fc1c6de1
commit
07744d0079
8 changed files with 169 additions and 8 deletions
22
Cargo.lock
generated
22
Cargo.lock
generated
|
@ -1336,6 +1336,19 @@ dependencies = [
|
||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http-body-util"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"http 1.3.1",
|
||||||
|
"http-body 1.0.1",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httparse"
|
name = "httparse"
|
||||||
version = "1.10.1"
|
version = "1.10.1"
|
||||||
|
@ -1379,9 +1392,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
|
checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-util",
|
||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
|
"httparse",
|
||||||
|
"httpdate",
|
||||||
|
"itoa",
|
||||||
|
"pin-project-lite",
|
||||||
|
"smallvec",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"want",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1839,6 +1860,7 @@ dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"futures-rustls",
|
"futures-rustls",
|
||||||
|
"http-body-util",
|
||||||
"hyper 1.6.0",
|
"hyper 1.6.0",
|
||||||
"lune-std-serde",
|
"lune-std-serde",
|
||||||
"lune-utils",
|
"lune-utils",
|
||||||
|
|
|
@ -24,7 +24,8 @@ blocking = "1.6"
|
||||||
bstr = "1.9"
|
bstr = "1.9"
|
||||||
futures-lite = "2.6"
|
futures-lite = "2.6"
|
||||||
futures-rustls = "0.26"
|
futures-rustls = "0.26"
|
||||||
hyper = "1.6"
|
http-body-util = "0.1"
|
||||||
|
hyper = { version = "1.6", features = ["http1", "client", "server"] }
|
||||||
pin-project-lite = "0.2"
|
pin-project-lite = "0.2"
|
||||||
rustls = "0.23"
|
rustls = "0.23"
|
||||||
rustls-pki-types = "1.11"
|
rustls-pki-types = "1.11"
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
mod hyper;
|
mod request;
|
||||||
mod stream;
|
mod stream;
|
||||||
|
|
||||||
|
pub use self::request::{Request, Response};
|
||||||
|
|
115
crates/lune-std-net/src/client/request.rs
Normal file
115
crates/lune-std-net/src/client/request.rs
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
use bstr::BString;
|
||||||
|
use futures_lite::prelude::*;
|
||||||
|
use http_body_util::{BodyStream, Full};
|
||||||
|
use hyper::{
|
||||||
|
body::{Bytes, Incoming},
|
||||||
|
client::conn::http1::handshake,
|
||||||
|
Method, Request as HyperRequest, Response as HyperResponse,
|
||||||
|
};
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
client::stream::HttpRequestStream,
|
||||||
|
shared::hyper::{HyperExecutor, HyperIo},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Request {
|
||||||
|
inner: HyperRequest<Full<Bytes>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Request {
|
||||||
|
pub async fn send(self, lua: Lua) -> LuaResult<Response> {
|
||||||
|
let stream = HttpRequestStream::connect(self.inner.uri()).await?;
|
||||||
|
|
||||||
|
let (mut sender, conn) = handshake(HyperIo::from(stream))
|
||||||
|
.await
|
||||||
|
.map_err(LuaError::external)?;
|
||||||
|
|
||||||
|
HyperExecutor::execute(lua, conn);
|
||||||
|
|
||||||
|
let incoming = sender
|
||||||
|
.send_request(self.inner)
|
||||||
|
.await
|
||||||
|
.map_err(LuaError::external)?;
|
||||||
|
|
||||||
|
Response::from_incoming(incoming).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromLua for Request {
|
||||||
|
fn from_lua(value: LuaValue, _lua: &Lua) -> LuaResult<Self> {
|
||||||
|
if let LuaValue::String(s) = value {
|
||||||
|
// We got a string, assume it's a URL + GET method
|
||||||
|
let uri = s.to_str()?;
|
||||||
|
Ok(Self {
|
||||||
|
inner: HyperRequest::builder()
|
||||||
|
.uri(uri.as_ref())
|
||||||
|
.body(Full::new(Bytes::new()))
|
||||||
|
.into_lua_err()?,
|
||||||
|
})
|
||||||
|
} else if let LuaValue::Table(t) = value {
|
||||||
|
// URL is always required with table options
|
||||||
|
let url = t.get::<String>("url")?;
|
||||||
|
let builder = HyperRequest::builder().uri(url);
|
||||||
|
|
||||||
|
// Add method, if provided
|
||||||
|
let builder = match t.get::<Option<String>>("method") {
|
||||||
|
Ok(Some(method)) => builder.method(method.as_str()),
|
||||||
|
Ok(None) => builder.method(Method::GET),
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add body, if provided
|
||||||
|
let builder = match t.get::<Option<BString>>("body") {
|
||||||
|
Ok(Some(body)) => builder.body(Full::new(body.to_vec().into())),
|
||||||
|
Ok(None) => builder.body(Full::new(Bytes::new())),
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
inner: builder.into_lua_err()?,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(LuaError::FromLuaConversionError {
|
||||||
|
from: value.type_name(),
|
||||||
|
to: String::from("HttpRequest"),
|
||||||
|
message: Some(String::from("HttpRequest must be a string or table")),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Response {
|
||||||
|
inner: HyperResponse<Full<Bytes>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Response {
|
||||||
|
pub async fn from_incoming(incoming: HyperResponse<Incoming>) -> LuaResult<Self> {
|
||||||
|
let (parts, body) = incoming.into_parts();
|
||||||
|
|
||||||
|
let body = BodyStream::new(body)
|
||||||
|
.try_fold(Vec::<u8>::new(), |mut body, chunk| {
|
||||||
|
if let Some(chunk) = chunk.data_ref() {
|
||||||
|
body.extend_from_slice(chunk);
|
||||||
|
}
|
||||||
|
Ok(body)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.into_lua_err()?;
|
||||||
|
|
||||||
|
let bytes = Full::new(Bytes::from(body));
|
||||||
|
let inner = HyperResponse::from_parts(parts, bytes);
|
||||||
|
|
||||||
|
Ok(Self { inner })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaUserData for Response {
|
||||||
|
fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_get("ok", |_, this| Ok(this.inner.status().is_success()));
|
||||||
|
fields.add_field_method_get("status", |_, this| Ok(this.inner.status().as_u16()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ pub enum HttpRequestStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HttpRequestStream {
|
impl HttpRequestStream {
|
||||||
pub async fn connect(url: Uri) -> Result<Self, io::Error> {
|
pub async fn connect(url: &Uri) -> Result<Self, io::Error> {
|
||||||
let Some(host) = url.host() else {
|
let Some(host) = url.host() else {
|
||||||
return Err(make_err("unknown or missing host"));
|
return Err(make_err("unknown or missing host"));
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,10 @@ mod client;
|
||||||
mod server;
|
mod server;
|
||||||
mod url;
|
mod url;
|
||||||
|
|
||||||
|
use self::client::{Request, Response};
|
||||||
|
|
||||||
|
pub(crate) mod shared;
|
||||||
|
|
||||||
const TYPEDEFS: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/types.d.luau"));
|
const TYPEDEFS: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/types.d.luau"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,10 +31,14 @@ pub fn typedefs() -> String {
|
||||||
*/
|
*/
|
||||||
pub fn module(lua: Lua) -> LuaResult<LuaTable> {
|
pub fn module(lua: Lua) -> LuaResult<LuaTable> {
|
||||||
TableBuilder::new(lua)?
|
TableBuilder::new(lua)?
|
||||||
// .with_async_function("request", net_request)?
|
.with_async_function("request", net_request)?
|
||||||
// .with_async_function("socket", net_socket)?
|
// .with_async_function("socket", net_socket)?
|
||||||
// .with_async_function("serve", net_serve)?
|
// .with_async_function("serve", net_serve)?
|
||||||
// .with_function("urlEncode", net_url_encode)?
|
// .with_function("urlEncode", net_url_encode)?
|
||||||
// .with_function("urlDecode", net_url_decode)?
|
// .with_function("urlDecode", net_url_decode)?
|
||||||
.build_readonly()
|
.build_readonly()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn net_request(lua: Lua, req: Request) -> LuaResult<Response> {
|
||||||
|
req.send(lua).await
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::{
|
||||||
|
|
||||||
use async_io::Timer;
|
use async_io::Timer;
|
||||||
use futures_lite::prelude::*;
|
use futures_lite::prelude::*;
|
||||||
use hyper::rt::{self, ReadBufCursor};
|
use hyper::rt::{self, Executor, ReadBufCursor};
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
use mlua_luau_scheduler::LuaSpawnExt;
|
use mlua_luau_scheduler::LuaSpawnExt;
|
||||||
|
|
||||||
|
@ -20,9 +20,21 @@ pub struct HyperExecutor {
|
||||||
lua: Lua,
|
lua: Lua,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Lua> for HyperExecutor {
|
#[allow(dead_code)]
|
||||||
fn from(lua: Lua) -> Self {
|
impl HyperExecutor {
|
||||||
Self { lua }
|
pub fn execute<Fut>(lua: Lua, fut: Fut)
|
||||||
|
where
|
||||||
|
Fut: Future + Send + 'static,
|
||||||
|
Fut::Output: Send + 'static,
|
||||||
|
{
|
||||||
|
let exec = if let Some(exec) = lua.app_data_ref::<Self>() {
|
||||||
|
exec
|
||||||
|
} else {
|
||||||
|
lua.set_app_data(Self { lua: lua.clone() });
|
||||||
|
lua.app_data_ref::<Self>().unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
exec.execute(fut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
crates/lune-std-net/src/shared/mod.rs
Normal file
1
crates/lune-std-net/src/shared/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod hyper;
|
Loading…
Add table
Reference in a new issue