feat: handle content-type x-www-form-urlencoded
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
c091528f9f
commit
e8cdc93ebd
67
Cargo.lock
generated
67
Cargo.lock
generated
@ -56,6 +56,15 @@ version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.26"
|
||||
@ -237,6 +246,16 @@ dependencies = [
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
@ -389,6 +408,12 @@ dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
@ -524,8 +549,24 @@ dependencies = [
|
||||
"mlua",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.25.0"
|
||||
@ -603,12 +644,38 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.0"
|
||||
|
||||
@ -29,3 +29,4 @@ mlua = { version = "0.8", features = [
|
||||
] }
|
||||
serde_json = { version = "1.0" }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
url = { version = "2.3" }
|
||||
|
||||
22
examples/html.lua
Normal file
22
examples/html.lua
Normal file
@ -0,0 +1,22 @@
|
||||
local app = create_app()
|
||||
|
||||
app:get("/", function(req, res)
|
||||
res.body = [[
|
||||
<html>
|
||||
<body>
|
||||
<form action="/submit" method="post">
|
||||
<input name="hello" value="Hello, World!" />
|
||||
<button type="submit">submit</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
]]
|
||||
return res
|
||||
end)
|
||||
|
||||
app:post("/submit", function(req, res)
|
||||
res.body = req.form.hello
|
||||
return res
|
||||
end)
|
||||
|
||||
app:run(3000)
|
||||
@ -11,6 +11,7 @@ use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll};
|
||||
use tokio::task::spawn_local;
|
||||
use url::form_urlencoded;
|
||||
|
||||
use crate::internal::lua::req::Req;
|
||||
use crate::internal::lua::res::Res;
|
||||
@ -34,7 +35,7 @@ impl Service<Request<Body>> for Svc {
|
||||
let addr = self.1.clone();
|
||||
let router = self.2.clone();
|
||||
Box::pin(async move {
|
||||
let uri = parts.uri.to_string();
|
||||
let uri = parts.uri.path().to_string();
|
||||
let lua_handle_match = match router.at(uri.as_str()) {
|
||||
Ok(res) => res,
|
||||
Err(_) => {
|
||||
@ -52,30 +53,44 @@ impl Service<Request<Body>> for Svc {
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
let body_bytes = to_bytes(body).await.unwrap();
|
||||
let body_str = String::from_utf8(body_bytes.to_vec()).unwrap();
|
||||
let mut params_map: HashMap<String, String> = HashMap::new();
|
||||
for (k, v) in lua_handle_match.params.iter() {
|
||||
params_map.insert(k.to_string(), v.to_string());
|
||||
}
|
||||
|
||||
let mut headers_map: HashMap<String, String> = HashMap::new();
|
||||
for (k, v) in parts.headers {
|
||||
headers_map.insert(k.unwrap().to_string(), v.to_str().unwrap().to_string());
|
||||
}
|
||||
|
||||
let mut params_map: HashMap<String, String> = HashMap::new();
|
||||
for (k, v) in lua_handle_match.params.iter() {
|
||||
params_map.insert(k.to_string(), v.to_string());
|
||||
let form_content_type = "application/x-www-form-urlencoded";
|
||||
|
||||
let body_bytes = to_bytes(body).await.unwrap();
|
||||
|
||||
let mut form_map: HashMap<String, String> = HashMap::new();
|
||||
if let Some(content_type) = headers_map.get("content-type") {
|
||||
if content_type.eq_ignore_ascii_case(form_content_type) {
|
||||
form_map = form_urlencoded::parse(&body_bytes.as_ref())
|
||||
.into_owned()
|
||||
.collect::<HashMap<String, String>>();
|
||||
}
|
||||
}
|
||||
|
||||
let body_str = String::from_utf8(body_bytes.to_vec()).unwrap();
|
||||
|
||||
let req = Req {
|
||||
body: body_str,
|
||||
headers: headers_map,
|
||||
form: form_map,
|
||||
method: lua_handle_match.value.method.to_string(),
|
||||
params: params_map,
|
||||
socket_addr: addr.to_string(),
|
||||
};
|
||||
|
||||
let res = Res {
|
||||
body: "".to_string(),
|
||||
status: StatusCode::OK,
|
||||
body: "".to_string(),
|
||||
json: "".to_string(),
|
||||
};
|
||||
|
||||
let handler: Function = lua
|
||||
@ -168,6 +183,7 @@ mod tests {
|
||||
Ok(Res {
|
||||
status: StatusCode::IM_A_TEAPOT,
|
||||
body: "Hello, World!".to_string(),
|
||||
json: "".to_string(),
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
@ -5,6 +5,7 @@ use mlua::{LuaSerdeExt, UserData, UserDataFields};
|
||||
#[derive(Clone)]
|
||||
pub struct Req {
|
||||
pub body: String,
|
||||
pub form: HashMap<String, String>,
|
||||
pub headers: HashMap<String, String>,
|
||||
pub method: String,
|
||||
pub params: HashMap<String, String>,
|
||||
@ -24,6 +25,12 @@ impl UserData for Req {
|
||||
}
|
||||
});
|
||||
|
||||
fields.add_field_method_set("form", |_, this, value| {
|
||||
this.form = value;
|
||||
Ok(())
|
||||
});
|
||||
fields.add_field_method_get("form", |_, this| Ok(this.form.to_owned()));
|
||||
|
||||
fields.add_field_method_set("headers", |_, this, value| {
|
||||
this.headers = value;
|
||||
Ok(())
|
||||
|
||||
@ -20,16 +20,23 @@ pub fn json_encode(value: LuaValue, pretty: Option<bool>) -> Result<Option<Strin
|
||||
pub struct Res {
|
||||
pub status: StatusCode,
|
||||
pub body: String,
|
||||
pub json: String,
|
||||
}
|
||||
|
||||
impl UserData for Res {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_set("body", |_, this, value| {
|
||||
this.body = json_encode(value, None).unwrap().unwrap();
|
||||
this.body = value;
|
||||
Ok(())
|
||||
});
|
||||
fields.add_field_method_get("body", |_, this| Ok(this.body.to_owned()));
|
||||
|
||||
fields.add_field_method_set("json", |_, this, value| {
|
||||
this.json = json_encode(value, None).unwrap().unwrap();
|
||||
Ok(())
|
||||
});
|
||||
fields.add_field_method_get("json", |_, this| Ok(this.json.to_owned()));
|
||||
|
||||
fields.add_field_method_set("status", |_, this, value: String| {
|
||||
this.status = StatusCode::from_str(value.as_str()).unwrap();
|
||||
Ok(())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user