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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
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]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.26"
|
version = "0.3.26"
|
||||||
@ -237,6 +246,16 @@ dependencies = [
|
|||||||
"want",
|
"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]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.9.2"
|
version = "1.9.2"
|
||||||
@ -389,6 +408,12 @@ dependencies = [
|
|||||||
"windows-sys 0.45.0",
|
"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]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.9"
|
version = "0.2.9"
|
||||||
@ -524,8 +549,24 @@ dependencies = [
|
|||||||
"mlua",
|
"mlua",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"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]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.25.0"
|
version = "1.25.0"
|
||||||
@ -603,12 +644,38 @@ version = "0.2.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-bidi"
|
||||||
|
version = "0.3.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
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]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|||||||
@ -29,3 +29,4 @@ mlua = { version = "0.8", features = [
|
|||||||
] }
|
] }
|
||||||
serde_json = { version = "1.0" }
|
serde_json = { version = "1.0" }
|
||||||
tokio = { version = "1.0", features = ["full"] }
|
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::rc::Rc;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use tokio::task::spawn_local;
|
use tokio::task::spawn_local;
|
||||||
|
use url::form_urlencoded;
|
||||||
|
|
||||||
use crate::internal::lua::req::Req;
|
use crate::internal::lua::req::Req;
|
||||||
use crate::internal::lua::res::Res;
|
use crate::internal::lua::res::Res;
|
||||||
@ -34,7 +35,7 @@ impl Service<Request<Body>> for Svc {
|
|||||||
let addr = self.1.clone();
|
let addr = self.1.clone();
|
||||||
let router = self.2.clone();
|
let router = self.2.clone();
|
||||||
Box::pin(async move {
|
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()) {
|
let lua_handle_match = match router.at(uri.as_str()) {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
@ -52,30 +53,44 @@ impl Service<Request<Body>> for Svc {
|
|||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
let body_bytes = to_bytes(body).await.unwrap();
|
let mut params_map: HashMap<String, String> = HashMap::new();
|
||||||
let body_str = String::from_utf8(body_bytes.to_vec()).unwrap();
|
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();
|
let mut headers_map: HashMap<String, String> = HashMap::new();
|
||||||
for (k, v) in parts.headers {
|
for (k, v) in parts.headers {
|
||||||
headers_map.insert(k.unwrap().to_string(), v.to_str().unwrap().to_string());
|
headers_map.insert(k.unwrap().to_string(), v.to_str().unwrap().to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut params_map: HashMap<String, String> = HashMap::new();
|
let form_content_type = "application/x-www-form-urlencoded";
|
||||||
for (k, v) in lua_handle_match.params.iter() {
|
|
||||||
params_map.insert(k.to_string(), v.to_string());
|
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 {
|
let req = Req {
|
||||||
body: body_str,
|
body: body_str,
|
||||||
headers: headers_map,
|
headers: headers_map,
|
||||||
|
form: form_map,
|
||||||
method: lua_handle_match.value.method.to_string(),
|
method: lua_handle_match.value.method.to_string(),
|
||||||
params: params_map,
|
params: params_map,
|
||||||
socket_addr: addr.to_string(),
|
socket_addr: addr.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = Res {
|
let res = Res {
|
||||||
body: "".to_string(),
|
|
||||||
status: StatusCode::OK,
|
status: StatusCode::OK,
|
||||||
|
body: "".to_string(),
|
||||||
|
json: "".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let handler: Function = lua
|
let handler: Function = lua
|
||||||
@ -168,6 +183,7 @@ mod tests {
|
|||||||
Ok(Res {
|
Ok(Res {
|
||||||
status: StatusCode::IM_A_TEAPOT,
|
status: StatusCode::IM_A_TEAPOT,
|
||||||
body: "Hello, World!".to_string(),
|
body: "Hello, World!".to_string(),
|
||||||
|
json: "".to_string(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@ -5,6 +5,7 @@ use mlua::{LuaSerdeExt, UserData, UserDataFields};
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Req {
|
pub struct Req {
|
||||||
pub body: String,
|
pub body: String,
|
||||||
|
pub form: HashMap<String, String>,
|
||||||
pub headers: HashMap<String, String>,
|
pub headers: HashMap<String, String>,
|
||||||
pub method: String,
|
pub method: String,
|
||||||
pub params: HashMap<String, 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| {
|
fields.add_field_method_set("headers", |_, this, value| {
|
||||||
this.headers = value;
|
this.headers = value;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -20,16 +20,23 @@ pub fn json_encode(value: LuaValue, pretty: Option<bool>) -> Result<Option<Strin
|
|||||||
pub struct Res {
|
pub struct Res {
|
||||||
pub status: StatusCode,
|
pub status: StatusCode,
|
||||||
pub body: String,
|
pub body: String,
|
||||||
|
pub json: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for Res {
|
impl UserData for Res {
|
||||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_set("body", |_, this, value| {
|
fields.add_field_method_set("body", |_, this, value| {
|
||||||
this.body = json_encode(value, None).unwrap().unwrap();
|
this.body = value;
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
fields.add_field_method_get("body", |_, this| Ok(this.body.to_owned()));
|
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| {
|
fields.add_field_method_set("status", |_, this, value: String| {
|
||||||
this.status = StatusCode::from_str(value.as_str()).unwrap();
|
this.status = StatusCode::from_str(value.as_str()).unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user