Skip to content

Commit 6cd9bfd

Browse files
committed
[server] correctly set the max size of incoming data
1 parent 6fdb61c commit 6cd9bfd

File tree

3 files changed

+66
-34
lines changed

3 files changed

+66
-34
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ aho-corasick = "^0.7"
1616
bytes = "^0.5"
1717
clap = "^2.33"
1818
enum-iterator = "^0.6"
19+
futures = "^0.3"
1920
fxhash = "0.2"
2021
globset = "^0.4"
2122
json = "^0.12"

src/web/server.rs

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use actix_rt::Runtime;
22
use actix_web::{
3-
dev::Body, guard, http, web, web::Query, App, FromRequest, HttpRequest, HttpResponse,
4-
HttpServer,
3+
dev::Body,
4+
guard, http,
5+
web::{self, BytesMut, Query},
6+
App, FromRequest, HttpRequest, HttpResponse, HttpServer,
57
};
6-
use bytes::Bytes;
8+
use futures::StreamExt;
79
use std::path::PathBuf;
810

911
use super::ast::{AstCallback, AstCfg, AstPayload};
@@ -22,7 +24,16 @@ struct Error {
2224
error: &'static str,
2325
}
2426

25-
fn ast_parser(item: web::Json<AstPayload>, _req: HttpRequest) -> HttpResponse {
27+
async fn get_code(mut body: web::Payload) -> Result<Vec<u8>, actix_web::Error> {
28+
let mut code = BytesMut::new();
29+
while let Some(item) = body.next().await {
30+
code.extend_from_slice(&item?);
31+
}
32+
33+
Ok(code.to_vec())
34+
}
35+
36+
fn ast_parser(item: web::Json<AstPayload>) -> HttpResponse {
2637
let path = PathBuf::from(&item.file_name);
2738
let payload = item.into_inner();
2839
let buf = payload.code.into_bytes();
@@ -50,7 +61,7 @@ fn ast_parser(item: web::Json<AstPayload>, _req: HttpRequest) -> HttpResponse {
5061
}
5162
}
5263

53-
fn comment_removal_json(item: web::Json<WebCommentPayload>, _req: HttpRequest) -> HttpResponse {
64+
fn comment_removal_json(item: web::Json<WebCommentPayload>) -> HttpResponse {
5465
let path = PathBuf::from(&item.file_name);
5566
let payload = item.into_inner();
5667
let buf = payload.code.into_bytes();
@@ -77,30 +88,33 @@ fn comment_removal_json(item: web::Json<WebCommentPayload>, _req: HttpRequest) -
7788
}
7889
}
7990

80-
fn comment_removal_plain(code: Bytes, info: Query<WebCommentInfo>) -> HttpResponse {
91+
async fn comment_removal_plain(
92+
body: web::Payload,
93+
info: Query<WebCommentInfo>,
94+
) -> Result<HttpResponse, actix_web::Error> {
95+
let buf = get_code(body).await?;
8196
let path = PathBuf::from(&info.file_name);
82-
let buf = code.to_vec();
8397
let (language, _) = guess_language(&buf, &path);
8498
if let Some(language) = language {
8599
let cfg = WebCommentCfg { id: "".to_string() };
86100
let res = action::<WebCommentCallback>(&language, buf, &PathBuf::from(""), None, cfg);
87101
if let Some(res_code) = res.code {
88-
HttpResponse::Ok()
102+
Ok(HttpResponse::Ok()
89103
.header(http::header::CONTENT_TYPE, "application/octet-stream")
90-
.body(res_code)
104+
.body(res_code))
91105
} else {
92-
HttpResponse::NoContent()
106+
Ok(HttpResponse::NoContent()
93107
.header(http::header::CONTENT_TYPE, "application/octet-stream")
94-
.body(Body::Empty)
108+
.body(Body::Empty))
95109
}
96110
} else {
97-
HttpResponse::NotFound()
111+
Ok(HttpResponse::NotFound()
98112
.header(http::header::CONTENT_TYPE, "text/plain")
99-
.body(format!("error: {}", INVALID_LANGUAGE))
113+
.body(format!("error: {}", INVALID_LANGUAGE)))
100114
}
101115
}
102116

103-
fn metrics_json(item: web::Json<WebMetricsPayload>, _req: HttpRequest) -> HttpResponse {
117+
fn metrics_json(item: web::Json<WebMetricsPayload>) -> HttpResponse {
104118
let path = PathBuf::from(&item.file_name);
105119
let payload = item.into_inner();
106120
let buf = payload.code.into_bytes();
@@ -127,9 +141,12 @@ fn metrics_json(item: web::Json<WebMetricsPayload>, _req: HttpRequest) -> HttpRe
127141
}
128142
}
129143

130-
fn metrics_plain(code: Bytes, info: Query<WebMetricsInfo>) -> HttpResponse {
144+
async fn metrics_plain(
145+
body: web::Payload,
146+
info: Query<WebMetricsInfo>,
147+
) -> Result<HttpResponse, actix_web::Error> {
148+
let buf = get_code(body).await?;
131149
let path = PathBuf::from(&info.file_name);
132-
let buf = code.to_vec();
133150
let (language, name) = guess_language(&buf, &path);
134151
if let Some(language) = language {
135152
let cfg = WebMetricsCfg {
@@ -141,17 +158,17 @@ fn metrics_plain(code: Bytes, info: Query<WebMetricsInfo>) -> HttpResponse {
141158
.map_or(false, |s| s == "1" || s == "true"),
142159
language: name,
143160
};
144-
HttpResponse::Ok().json(action::<WebMetricsCallback>(
161+
Ok(HttpResponse::Ok().json(action::<WebMetricsCallback>(
145162
&language,
146163
buf,
147164
&PathBuf::from(""),
148165
None,
149166
cfg,
150-
))
167+
)))
151168
} else {
152-
HttpResponse::NotFound()
169+
Ok(HttpResponse::NotFound()
153170
.header(http::header::CONTENT_TYPE, "text/plain")
154-
.body(format!("error: {}", INVALID_LANGUAGE))
171+
.body(format!("error: {}", INVALID_LANGUAGE)))
155172
}
156173
}
157174

@@ -177,23 +194,26 @@ fn function_json(item: web::Json<WebFunctionPayload>, _req: HttpRequest) -> Http
177194
}
178195
}
179196

180-
fn function_plain(code: Bytes, info: Query<WebFunctionInfo>) -> HttpResponse {
197+
async fn function_plain(
198+
body: web::Payload,
199+
info: Query<WebFunctionInfo>,
200+
) -> Result<HttpResponse, actix_web::Error> {
201+
let buf = get_code(body).await?;
181202
let path = PathBuf::from(&info.file_name);
182-
let buf = code.to_vec();
183203
let (language, _) = guess_language(&buf, &path);
184204
if let Some(language) = language {
185205
let cfg = WebFunctionCfg { id: "".to_string() };
186-
HttpResponse::Ok().json(action::<WebFunctionCallback>(
206+
Ok(HttpResponse::Ok().json(action::<WebFunctionCallback>(
187207
&language,
188208
buf,
189209
&PathBuf::from(""),
190210
None,
191211
cfg,
192-
))
212+
)))
193213
} else {
194-
HttpResponse::NotFound()
214+
Ok(HttpResponse::NotFound()
195215
.header(http::header::CONTENT_TYPE, "text/plain")
196-
.body(format!("error: {}", INVALID_LANGUAGE))
216+
.body(format!("error: {}", INVALID_LANGUAGE)))
197217
}
198218
}
199219

@@ -204,49 +224,59 @@ fn ping() -> HttpResponse {
204224
pub fn run(host: String, port: u16, n_threads: usize) -> std::io::Result<()> {
205225
let _ = actix_rt::System::new("server");
206226
let mut rt = Runtime::new()?;
227+
let max_size = 1024 * 1024 * 4;
207228

208229
rt.block_on(async move {
209-
HttpServer::new(|| {
230+
HttpServer::new(move || {
210231
App::new()
211232
.service(
212233
web::resource("/ast")
213-
.data(web::JsonConfig::default().limit(std::u32::MAX as usize))
234+
.guard(guard::Header("content-type", "application/json"))
235+
.app_data(web::Json::<AstPayload>::configure(|cfg| {
236+
cfg.limit(max_size)
237+
}))
214238
.route(web::post().to(ast_parser)),
215239
)
216240
.service(
217241
web::resource("/comment")
218242
.guard(guard::Header("content-type", "application/json"))
219-
.data(web::JsonConfig::default().limit(std::u32::MAX as usize))
243+
.app_data(web::Json::<WebCommentPayload>::configure(|cfg| {
244+
cfg.limit(max_size)
245+
}))
220246
.route(web::post().to(comment_removal_json)),
221247
)
222248
.service(
223249
web::resource("/comment")
224250
.guard(guard::Header("content-type", "application/octet-stream"))
225-
.data(Bytes::configure(|cfg| cfg.limit(std::u32::MAX as usize)))
251+
.data(web::PayloadConfig::default().limit(max_size))
226252
.route(web::post().to(comment_removal_plain)),
227253
)
228254
.service(
229255
web::resource("/metrics")
230256
.guard(guard::Header("content-type", "application/json"))
231-
.data(web::JsonConfig::default().limit(std::u32::MAX as usize))
257+
.app_data(web::Json::<WebMetricsPayload>::configure(|cfg| {
258+
cfg.limit(max_size)
259+
}))
232260
.route(web::post().to(metrics_json)),
233261
)
234262
.service(
235263
web::resource("/metrics")
236264
.guard(guard::Header("content-type", "application/octet-stream"))
237-
.data(Bytes::configure(|cfg| cfg.limit(std::u32::MAX as usize)))
265+
.data(web::PayloadConfig::default().limit(max_size))
238266
.route(web::post().to(metrics_plain)),
239267
)
240268
.service(
241269
web::resource("/function")
242270
.guard(guard::Header("content-type", "application/json"))
243-
.data(web::JsonConfig::default().limit(std::u32::MAX as usize))
271+
.app_data(web::Json::<WebFunctionPayload>::configure(|cfg| {
272+
cfg.limit(max_size)
273+
}))
244274
.route(web::post().to(function_json)),
245275
)
246276
.service(
247277
web::resource("/function")
248278
.guard(guard::Header("content-type", "application/octet-stream"))
249-
.data(Bytes::configure(|cfg| cfg.limit(std::u32::MAX as usize)))
279+
.data(web::PayloadConfig::default().limit(max_size))
250280
.route(web::post().to(function_plain)),
251281
)
252282
.service(web::resource("/ping").route(web::get().to(ping)))

0 commit comments

Comments
 (0)