summaryrefslogtreecommitdiffstats
path: root/server/src/srv.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/srv.cpp')
-rw-r--r--server/src/srv.cpp113
1 files changed, 111 insertions, 2 deletions
diff --git a/server/src/srv.cpp b/server/src/srv.cpp
index dc9c814..5de0fc5 100644
--- a/server/src/srv.cpp
+++ b/server/src/srv.cpp
@@ -30,7 +30,7 @@ namespace routemon::srv {
30class gpx_parse_error_category_impl : public std::error_category 30class gpx_parse_error_category_impl : public std::error_category
31{ 31{
32public: 32public:
33 char const* name() const noexcept override { return "gpx_parse"; } 33 auto name() const noexcept -> char const* override { return "gpx_parse"; }
34 34
35 auto message(int condition) const noexcept -> std::string override 35 auto message(int condition) const noexcept -> std::string override
36 { 36 {
@@ -330,12 +330,120 @@ struct raw_deflate_body
330 }; 330 };
331}; 331};
332 332
333auto parse_timestamp(std::string_view in) -> std::optional<time::timestamp>
334{
335 auto res = time::timestamp{};
336 auto is = std::istringstream{in};
337 is >> std::chrono::parse("%Y-%m-%dT%H:%MZ", res);
338 return is.fail() ? std::nullopt : std::make_optional(res);
339}
340
333auto handler::handle_process_gpx(l0_ctx ctx, http::readable_request r) 341auto handler::handle_process_gpx(l0_ctx ctx, http::readable_request r)
334 -> net::awaitable<http::presponse> 342 -> net::awaitable<http::presponse>
335{ 343{
336 auto l = 344 auto l =
337 l_.sub("handle_process_gpx").with("trace_id", ctx.trace_id.as_string()); 345 l_.sub("handle_process_gpx").with("trace_id", ctx.trace_id.as_string());
338 346
347 auto cp_begin = time::timestamp{};
348 auto cp_end = time::timestamp{};
349
350 auto const params = ctx.target.params();
351 if (auto it = params.find("cpbegin"); it != params.end())
352 {
353 auto mts = parse_timestamp((*it).value);
354 if (!mts)
355 {
356 auto tpl = problem::tpl{
357 .status = bhttp::status::bad_request,
358 .title = translate("Query parameter has bad value"),
359 .type_uri =
360 "https://routemon.fautchen.eu/problems/query-param-bad-value",
361 };
362 co_return http::problem_rsp(
363 ctx, tpl.instantiate(), http::keep_alive{false});
364 }
365 cp_begin = *mts;
366
367 ++it;
368 if (it != params.end() && (*it).key == "cpbegin")
369 {
370 auto tpl = problem::tpl{
371 .status = bhttp::status::bad_request,
372 .title = translate("Query parameter provided too many times"),
373 .type_uri = "https://routemon.fautchen.eu/problems/"
374 "query-param-too-many-occurrences",
375 };
376 co_return http::problem_rsp(
377 ctx, tpl.instantiate(), http::keep_alive{false});
378 }
379 }
380 else
381 {
382 auto tpl = problem::tpl{
383 .status = bhttp::status::bad_request,
384 .title = translate("Required query parameter not provided"),
385 .type_uri = "https://routemon.fautchen.eu/problems/"
386 "required-query-param-not-provided",
387 };
388 co_return http::problem_rsp(
389 ctx, tpl.instantiate(), http::keep_alive{false});
390 }
391 if (auto it = params.find("cpend"); it != params.end())
392 {
393 auto mts = parse_timestamp((*it).value);
394 if (!mts)
395 {
396 auto tpl = problem::tpl{
397 .status = bhttp::status::bad_request,
398 .title = translate("Query parameter has bad value"),
399 .type_uri =
400 "https://routemon.fautchen.eu/problems/query-param-bad-value",
401 };
402 co_return http::problem_rsp(
403 ctx, tpl.instantiate(), http::keep_alive{false});
404 }
405 cp_end = *mts;
406
407 ++it;
408 if (it != params.end() && (*it).key == "cpend")
409 {
410 auto tpl = problem::tpl{
411 .status = bhttp::status::bad_request,
412 .title = translate("Query parameter provided too many times"),
413 .type_uri = "https://routemon.fautchen.eu/problems/"
414 "query-param-too-many-occurrences",
415 };
416 co_return http::problem_rsp(
417 ctx, tpl.instantiate(), http::keep_alive{false});
418 }
419 }
420 else
421 {
422 auto tpl = problem::tpl{
423 .status = bhttp::status::bad_request,
424 .title = translate("Required query parameter not provided"),
425 .type_uri = "https://routemon.fautchen.eu/problems/"
426 "required-query-param-not-provided",
427 };
428 co_return http::problem_rsp(
429 ctx, tpl.instantiate(), http::keep_alive{false});
430 }
431
432 if (cp_begin >= cp_end)
433 {
434 auto tpl = problem::tpl{
435 .status = bhttp::status::bad_request,
436 .title = translate("Invalid check period provided"),
437 .type_uri = "https://routemon.fautchen.eu/problems/invalid-check-period",
438 };
439 co_return http::problem_rsp(
440 ctx,
441 tpl.instantiate().set_detail(translate(
442 "Begin of check period must be before end of check period")),
443 http::keep_alive{false});
444 }
445 auto cp = time::period{cp_begin, cp_end};
446
339 auto gpx_file = gpx::file{}; 447 auto gpx_file = gpx::file{};
340 try 448 try
341 { 449 {
@@ -378,7 +486,8 @@ auto handler::handle_process_gpx(l0_ctx ctx, http::readable_request r)
378 486
379 // TODO: catch handler exceptions and return 500 when raised? 487 // TODO: catch handler exceptions and return 500 when raised?
380 // (keep-alive depends on whether whole request was read) 488 // (keep-alive depends on whether whole request was read)
381 auto mres = inner_.process_gpx(ctx.trace_id, std::move(gpx_file)); 489 auto mres = inner_.process_gpx(
490 ctx.trace_id, std::move(gpx_file), time::period_seq{cp});
382 if (!mres) 491 if (!mres)
383 { 492 {
384 auto tpl = problem::tpl{ 493 auto tpl = problem::tpl{