rupring v0.14.0 ๋ฐฐํฌ
https://github.com/myyrakle/rupring/releases/tag/v0.14.0
์ฐ๋์ฐ๋ ์ข ์น๋ค๊ฐ ๊ฐ๋ง์ ๋ฐฐํฌ ํ๋ฒ ๋ง์๋ค.
์ฃผ์ ๋ณ๊ฒฝ์ฌํญ๋ค์ ๋ค์๊ณผ ๊ฐ๋ค.
1. HTTP2 ์ง์ ์ ๊ฑฐ
์๊ฐํด๋ณด๋๊น, ์ฌ์ค ์ด๊ฑฐ ์ธ ์ผ์ด ๋ฑํ ์์ด์ ๊ฑท์ด๋๋ค.
๋๋ถ๋ถ์ ์๋ฒ ์ธํ๋ผ ํ๊ฒฝ์์๋ HTTP1.1๋ก ์ถฉ๋ถํ ํจ์จ์ฑ์ด ๋์ค๋๋ฐ๋ค, ์๋ฒ๋ง๋ค TLS ๋ถ์ด๋ ๊ฑด ๊ฑฐ์ ๋์ ์ ๊ฐ๊น๊ธฐ ๋๋ฌธ์ด๋ค.
๊ฒ๋ค๊ฐ ์ด๊ฑฐ ํ๋๋๋ฌธ์ ์ฝ๋๋ฒ ์ด์ค ๊ด๋ฆฌ๊ฐ ๋๋ฌด ๋ณต์กํด์ง๋ ๋ฉด๋ ์์๋ค. ๋์ค์ ๋ค์ ์ถ๊ฐํ ์ผ์ด ์๊ธธ์ง๋ ๋ชจ๋ฅด์ง๋ง, ์ผ๋จ์ ๋ฒ๋ฆฐ๋ค.
2. Streaming ๋ฐ SSE ์ง์
์ด์ SSE๊ฐ ๋ฐ๋ก ์ง์๋๋ค.
์ฌ์ฉ ๊ตฌ์กฐ๋ ์ต๋ํ ๋จ์ํ๊ณ ์ง๊ด์ ์ธ ํํ๋ก ์ก์๋ดค๋ค.
#[rupring::Get(path = /sse)]
#[tags = [user]]
#[summary = "SSE ํ์ด์ง"]
pub fn serve_sse(request: rupring::Request) -> rupring::Response {
rupring::Response::new()
.sse_stream(async move |stream_handler| {
let mut count = 0;
loop {
if stream_handler.is_closed() {
println!("Client disconnected, stopping SSE");
break;
}
let event = rupring::http::sse::Event::new()
.event("custom-event")
.id("event-id-1")
.retry(300)
.data(format!("This is custom event number {}", count));
if let Err(e) = stream_handler.send_event(event).await {
eprintln!("Error sending message: {}", e);
}
count += 1;
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
}
})
}
๊ทธ๋ฅ ์ด๋ฐ ์์ผ๋ก ์ฝ๋ฐฑ ๋ฃ๊ณ ๋๋ฆฌ๋ฉด ๋๋ค.
์ปค๋ฅ์
์ค๋จ ๊ฐ์ง๋ ์ง์ ํด์ผํ๋ค.
๊ทธ๋ฌ๋ฉด ์ด๋ ๊ฒ ์ ๋๋ค.
3. ๋ฉํฐํํธ ํ์ฑ ๊ธฐ๋ฅ ์ถ๊ฐ
์ด์ ๋ฉํฐํํธ ํ์ฑ์ ์ง์ ์ง์ํ๋ค.
๋ฐ๋ก ๋ฉํฐํํธ ํํ๋ก ํ์ผ์ ๋ฐ์๋ค๊ฐ ์ฒ๋ฆฌํ ์ ์๋ค.
#[rupring::Post(path = /multipart-upload)]
#[summary = "๋จ์ ํ์ผ ์
๋ก๋ API์
๋๋ค."]
#[description = "๋ณ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์์ต๋๋ค."]
#[tags = [root]]
pub fn multipart(mut request: rupring::Request) -> rupring::Response {
for (i, file) in request.files.iter().enumerate() {
std::fs::write(format!("{i}.foo"), &file.data).unwrap();
}
rupring::Response::new().text("Hello, World!")
}
#[rupring::Get(path = /multipart-upload-page)]
#[summary = "๋จ์ ํ์ผ ์
๋ก๋ API์
๋๋ค."]
#[description = "๋ณ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์์ต๋๋ค."]
#[tags = [root]]
pub fn multipart_page(request: rupring::Request) -> rupring::Response {
rupring::Response::new().html(
r#"
<html>
<body>
<form action="/multipart-upload" method="post" enctype="multipart/form-data">
<input type="file" name="file1" />
<input type="file" name="file2" />
<input type="submit" value="Submit" />
</form>
</body>
</html>
"#,
)
}4. ๊ธฐํ๋ฑ๋ฑ
- ํธ์์ฉ Response::download ํจ์๊ฐ ์ถ๊ฐ๋๋ค. ์ด๊ฑธ ์ฐ๋ฉด ๋ฐ๋ก content_disposition ํค๋๋ฅผ ์กฐ์ ํด์ ๋ธ๋ผ์ฐ์ ์์ ์ฆ์ ๋ค์ด๋ก๋๋ฅผ ํ๋๋ก ๋์์ ์ ์ํ๋ค.
- Response::html ์์ปท ํจ์๊ฐ ์ถ๊ฐ๋๋ค. ๊ทธ๋ฅ text์ ํ ์ข ๋ฅ์ธ๋ฐ content-type๋ง ์์์ ์ ์กฐ์ ํด์ค๋ค.
- Response::cache_control ํจ์๊ฐ ์ถ๊ฐ๋๋ค. ์ด๋ฅผ ํตํด ๋ช ์์ ์ผ๋ก ์บ์ ์ ์ฑ ์ ์กฐ์ ํ ์ ์๋ค.
- ์ฟ ํค๋ฅผ ์๋์ผ๋ก ํ์ฑํด์ ๋ฃ์ด์ฃผ๋ ํ๋๊ทธ "server.cookie.auto-parsing-enabled"๊ฐ ์ถ๊ฐ๋๋ค. ์ด๊ฒ ์ผ์ง๋ฉด request ์ปจํ ์คํธ์ header์ ์๋์ผ๋ก ์ฟ ํค ๊ฐ์ด ํ์ฑ๋ผ์ ๋ค์ด๊ฐ๋ค.
- URI ๊ธธ์ด ์ ํ ํ๋๊ทธ "server.request.uri.max-length"๊ฐ ์ถ๊ฐ๋๋ค. ์ด๊ณผํ๋ฉด 414๊ฐ ๋จ์ด์ง๋ค.
- ํค๋ ํฌ๊ธฐ ์ ํ ํ๋๊ทธ "server.request.header.max-length"์ "server.request.header.max-number-of-headers"๊ฐ ์ถ๊ฐ๋๋ค. ์ด๊ณผํ๋ฉด 400์ด ๋จ์ด์ง๋ค.
- request body ํฌ๊ธฐ๋ฅผ ์ ํํ๋ "server.request.body.max-length" ํ๋๊ทธ๊ฐ ์ถ๊ฐ๋๋ค.
- reqeust context์ ip, protocol ๋ฑ์ ๊ฐ์ ํฌํจํ๋ metadata ํ๋๊ฐ ์ถ๊ฐ๋๋ค.
- ๊ธฐํ ๋ฒ๊ทธ ์์