Skip to content

Commit d763c9f

Browse files
committed
Update http module
- Some docs - Add `RequestParams` (extension) - Rename `HttpServer` to `LuaHttpServer`
1 parent b0fc2af commit d763c9f

File tree

11 files changed

+79
-32
lines changed

11 files changed

+79
-32
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ http-serde-ext = { version = "1.0", optional = true }
4545
http-body = { version = "1.0", optional = true }
4646
http-body-util = { version = "0.1", optional = true }
4747
hyper = { version = "1.5", optional = true, features = ["http1", "http2", "server"] }
48-
hyper-util = { version = "0.1", optional = true, features = ["tokio", "server", "server-auto", "server-graceful"] }
48+
hyper-util = { version = "0.1", optional = true, features = ["tokio", "server", "server-auto", "server-graceful", "client-legacy"] }
4949

5050
# reqwest
5151
reqwest = { version = "0.12", features = ["cookies", "gzip", "brotli", "multipart", "stream"], optional = true }

src/http/body.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ impl Default for LuaBody {
4141
}
4242

4343
impl LuaBody {
44+
/// Creates a new empty body.
4445
pub const fn new() -> Self {
4546
LuaBody(Inner::Bytes(Bytes::new()))
4647
}
4748

49+
/// Buffers the entire body into memory.
4850
async fn buffer(&mut self) -> Result<(), Error> {
4951
match self {
5052
LuaBody(Inner::Bytes(_)) => Ok(()),
@@ -56,6 +58,7 @@ impl LuaBody {
5658
}
5759
}
5860

61+
/// Consumes the body if it is not already buffered, returning a buffered body.
5962
fn consume_if_unbuffered(&mut self) -> Self {
6063
match self {
6164
LuaBody(Inner::Bytes(bytes)) => LuaBody(Inner::Bytes(bytes.clone())),
@@ -65,12 +68,14 @@ impl LuaBody {
6568
}
6669

6770
impl From<Bytes> for LuaBody {
71+
#[inline]
6872
fn from(bytes: Bytes) -> Self {
6973
LuaBody(Inner::Bytes(bytes))
7074
}
7175
}
7276

7377
impl From<Incoming> for LuaBody {
78+
#[inline]
7479
fn from(incoming: Incoming) -> Self {
7580
LuaBody(Inner::Incoming {
7681
incoming,

src/http/headers.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ fn set_headers_metatable(lua: &Lua, headers: &Table) -> Result<()> {
197197
headers.set_metatable(Some(metatable))
198198
}
199199

200+
/// Extension trait for converting Lua strings to header names and values.
200201
pub(crate) trait LuaHeaderValueExt {
201202
fn from_lua(value: &LuaString) -> Result<Self>
202203
where
@@ -217,6 +218,7 @@ impl LuaHeaderValueExt for HeaderValue {
217218
}
218219
}
219220

221+
/// Extension trait for [`http::HeaderMap`] to provide Lua-friendly methods.
220222
pub(crate) trait LuaHeaderMapExt {
221223
fn get(&self, lua: &Lua, name: &LuaString) -> Result<Option<LuaString>>;
222224

src/http/method.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use mlua::{ExternalResult, FromLua, Lua, Result, String as LuaString, Value};
22

3-
/// A Lua userdata wrapper around [`http::Method`].
3+
/// A Lua wrapper around [`http::Method`].
44
#[derive(Clone, Default, Debug)]
55
pub struct LuaMethod(pub http::Method);
66

src/http/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ pub use headers::LuaHeaders;
55
pub use method::LuaMethod;
66
pub use request::LuaRequest;
77
pub use response::LuaResponse;
8+
pub use server::LuaHttpServer;
89

9-
#[allow(unused_imports)]
1010
pub(crate) use headers::LuaHeaderMapExt;
1111

1212
/// A loader for the `http` module.
1313
fn loader(lua: &Lua) -> Result<Table> {
1414
let t = lua.create_table()?;
1515
t.set("Headers", lua.create_proxy::<LuaHeaders>()?)?;
16-
t.set("HttpServer", lua.create_proxy::<server::HttpServer>()?)?;
16+
t.set("HttpServer", lua.create_proxy::<LuaHttpServer>()?)?;
1717
t.set("Request", lua.create_proxy::<LuaRequest>()?)?;
1818
t.set("Response", lua.create_proxy::<LuaResponse>()?)?;
1919
Ok(t)

src/http/request.rs

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@ use std::mem;
33
use http::request::{Parts, Request};
44
use http_body_util::Either as EitherBody;
55
use hyper::body::Incoming;
6-
use mlua::{AnyUserData, Error, FromLua, Lua, Result, String as LuaString, UserData, UserDataMethods, Value};
6+
use mlua::{
7+
AnyUserData, Error, FromLua, Lua, MetaMethod, Result, String as LuaString, Table, UserData,
8+
UserDataMethods, Value,
9+
};
710

8-
use super::headers::LuaHeaderMapExt;
9-
use crate::http::{LuaBody, LuaHeaders, LuaMethod};
11+
use crate::http::{LuaBody, LuaHeaderMapExt, LuaHeaders, LuaMethod};
1012
use crate::time::Duration;
1113

12-
/// A Lua-accessible HTTP request
14+
/// A Lua wrapper around [`http::Request`].
1315
pub struct LuaRequest {
1416
pub(crate) head: Parts,
1517
pub(crate) body: EitherBody<LuaBody, AnyUserData>,
16-
pub(crate) timeout: Option<Duration>,
1718
}
1819

1920
impl Default for LuaRequest {
@@ -23,12 +24,12 @@ impl Default for LuaRequest {
2324
LuaRequest {
2425
head,
2526
body: EitherBody::Left(LuaBody::new()),
26-
timeout: None,
2727
}
2828
}
2929
}
3030

3131
impl LuaRequest {
32+
/// Consumes the LuaRequest and returns its parts.
3233
pub fn into_parts(self) -> (Parts, LuaBody) {
3334
let LuaRequest { head, body, .. } = self;
3435
let body = match body {
@@ -37,6 +38,14 @@ impl LuaRequest {
3738
};
3839
(head, body)
3940
}
41+
42+
#[allow(unused)]
43+
pub(crate) fn params(&self) -> RequestParams {
44+
(self.head.extensions)
45+
.get::<RequestParams>()
46+
.cloned()
47+
.unwrap_or_default()
48+
}
4049
}
4150

4251
impl UserData for LuaRequest {
@@ -92,7 +101,7 @@ impl UserData for LuaRequest {
92101
registry.add_method_mut("body", |lua, this, ()| {
93102
match &mut this.body {
94103
EitherBody::Left(body) => {
95-
// Move the body to Lua
104+
// Move the body into Lua
96105
let ud_body = lua.create_userdata(mem::take(body))?;
97106
this.body = EitherBody::Right(ud_body.clone());
98107
Ok(ud_body)
@@ -105,6 +114,18 @@ impl UserData for LuaRequest {
105114
this.body = EitherBody::Left(body);
106115
Ok(())
107116
});
117+
118+
registry.add_meta_method(MetaMethod::ToString, |_, this, ()| {
119+
let mut buf = String::with_capacity(1024);
120+
let (method, uri, version) = (&this.head.method, &this.head.uri, this.head.version);
121+
buf.push_str(&format!("{method} {uri} {version:?}\n"));
122+
// Iterate headers
123+
for (name, value) in &this.head.headers {
124+
let value = String::from_utf8_lossy(value.as_bytes());
125+
buf.push_str(&format!("{name}: {value}\n"));
126+
}
127+
Ok(buf)
128+
});
108129
}
109130
}
110131

@@ -114,7 +135,6 @@ impl From<Request<Incoming>> for LuaRequest {
114135
LuaRequest {
115136
head,
116137
body: EitherBody::Left(LuaBody::from(body)),
117-
timeout: None,
118138
}
119139
}
120140
}
@@ -140,21 +160,36 @@ impl FromLua for LuaRequest {
140160
}
141161
// TODO: json, form, etc
142162

143-
// Additional parameters
144-
let timeout = opt_param!(Duration, Some(&params), "timeout")?;
163+
// Additional custom parameters
164+
head.extensions.insert(RequestParams::from_table(&params)?);
145165

146166
Ok(Self {
147167
head,
148168
body: EitherBody::Left(body),
149-
timeout,
150169
})
151170
}
152171
Value::UserData(ud) if ud.is::<Self>() => ud.take::<Self>(),
153172
_ => Err(Error::FromLuaConversionError {
154173
from: value.type_name(),
155174
to: "Request".to_string(),
156-
message: Some("expected Table or Request".to_string()),
175+
message: Some("expected Table or Request userdata".to_string()),
157176
}),
158177
}
159178
}
160179
}
180+
181+
/// Additional custom request parameters
182+
#[derive(Clone, Debug, Default)]
183+
pub(crate) struct RequestParams {
184+
pub(crate) timeout: Option<Duration>,
185+
}
186+
187+
impl RequestParams {
188+
pub(crate) fn from_table(table: &Table) -> Result<Self> {
189+
let mut params = RequestParams::default();
190+
if let Some(timeout) = opt_param!(Duration, Some(table), "timeout")? {
191+
params.timeout = Some(timeout);
192+
}
193+
Ok(params)
194+
}
195+
}

src/http/response.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,20 @@ use mlua::{
1313
use super::headers::LuaHeaderMapExt;
1414
use crate::http::{LuaBody, LuaHeaders};
1515

16-
/// A Lua-accessible HTTP response
16+
/// A Lua wrapper around [`http::Response`].
1717
pub struct LuaResponse {
1818
pub(crate) head: Parts,
1919
pub(crate) body: EitherBody<LuaBody, AnyUserData>,
2020
}
2121

22+
impl Default for LuaResponse {
23+
fn default() -> Self {
24+
LuaResponse::new(LuaBody::new())
25+
}
26+
}
27+
2228
impl LuaResponse {
23-
/// Create a new Response with the given status code
29+
/// Create a new Response with the given body.
2430
pub fn new(body: LuaBody) -> Self {
2531
let head = Response::new(()).into_parts().0;
2632
let body = EitherBody::Left(body);
@@ -100,11 +106,8 @@ impl UserData for LuaResponse {
100106

101107
registry.add_meta_method(MetaMethod::ToString, |_, this, ()| {
102108
let mut buf = String::with_capacity(1024);
103-
let (version, status, reason) = (
104-
&this.head.version,
105-
this.head.status.as_u16(),
106-
this.head.status.canonical_reason().unwrap_or(""),
107-
);
109+
let (version, status) = (this.head.version, this.head.status);
110+
let reason = status.canonical_reason().unwrap_or("");
108111
buf.push_str(&format!("{version:?} {status} {reason}\n"));
109112
// Iterate headers
110113
for (name, value) in &this.head.headers {

src/http/server.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ where
3434
}
3535

3636
/// HTTP server that can handle HTTP/1 and HTTP/2 connections
37-
pub struct HttpServer {
37+
pub struct LuaHttpServer {
3838
conn: ConnBuilder<LocalExec>,
3939
graceful: Arc<Mutex<GracefulShutdown>>,
4040
shutdown_notify: Arc<Mutex<tokio::sync::watch::Sender<()>>>,
4141
}
4242

43-
impl HttpServer {
43+
impl LuaHttpServer {
4444
pub fn new(params: Option<Table>) -> Result<Self> {
4545
let mut conn = ConnBuilder::new(LocalExec);
4646

@@ -99,7 +99,7 @@ impl HttpServer {
9999
conn.http1().timer(TokioTimer::new());
100100
conn.http2().timer(TokioTimer::new());
101101

102-
Ok(HttpServer {
102+
Ok(LuaHttpServer {
103103
conn,
104104
graceful: Default::default(),
105105
shutdown_notify: Default::default(),
@@ -179,9 +179,9 @@ impl HttpServer {
179179
}
180180
}
181181

182-
impl UserData for HttpServer {
182+
impl UserData for LuaHttpServer {
183183
fn register(registry: &mut UserDataRegistry<Self>) {
184-
registry.add_function("new", |_: &Lua, params| HttpServer::new(params));
184+
registry.add_function("new", |_: &Lua, params| Self::new(params));
185185

186186
registry.add_async_method(
187187
"serve_connection",

src/net/tcp/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use mlua::{Lua, Result, Table};
33
pub use listener::{LuaTcpListener, listen};
44
pub use stream::{LuaTcpStream, connect};
55

6-
use socket::{SocketOptions, LuaTcpSocket};
6+
use socket::{LuaTcpSocket, SocketOptions};
77

88
/// A loader for the `net/tcp` module.
99
fn loader(lua: &Lua) -> Result<Table> {

src/net/tcp/stream.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::time::Duration;
1616
/// Lua wrapper around tokio [`TcpStream`].
1717
pub struct LuaTcpStream {
1818
pub(crate) stream: TcpStream,
19+
#[allow(unused)]
1920
pub(crate) host: Option<String>,
2021
pub(crate) read_timeout: Option<Duration>,
2122
pub(crate) write_timeout: Option<Duration>,

0 commit comments

Comments
 (0)