1use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt};
2use hyper::{Request, Response, StatusCode, Body, HeaderMap};
3use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE};
4use log::warn;
5#[allow(unused_imports)]
6use std::convert::{TryFrom, TryInto};
7use std::error::Error;
8use std::future::Future;
9use std::marker::PhantomData;
10use std::task::{Context, Poll};
11use swagger::{ApiError, BodyExt, Has, RequestParser, XSpanIdString};
12pub use swagger::auth::Authorization;
13use swagger::auth::Scopes;
14use url::form_urlencoded;
15
16#[allow(unused_imports)]
17use crate::{models, header, AuthenticationApi};
18
19pub use crate::context;
20
21type ServiceFuture = BoxFuture<'static, Result<Response<Body>, crate::ServiceError>>;
22
23use crate::{Api,
24 BobbyDeleteResponse,
25 GamePostResponse,
26 MapsGetResponse,
27 RegisterPostResponse,
28 StatisticsGetResponse,
29 MapLevelGetResponse,
30 StatisticsUuidGetResponse,
31 UserUuidGetResponse
32};
33
34mod server_auth;
35
36mod paths {
37 use lazy_static::lazy_static;
38
39 lazy_static! {
40 pub static ref GLOBAL_REGEX_SET: regex::RegexSet = regex::RegexSet::new(vec![
41 r"^/bobby$",
42 r"^/game$",
43 r"^/map/(?P<level>[^/?#]*)$",
44 r"^/maps$",
45 r"^/register$",
46 r"^/statistics$",
47 r"^/statistics/(?P<UUID>[^/?#]*)$",
48 r"^/user/(?P<UUID>[^/?#]*)$"
49 ])
50 .expect("Unable to create global regex set");
51 }
52 pub(crate) static ID_BOBBY: usize = 0;
53 pub(crate) static ID_GAME: usize = 1;
54 pub(crate) static ID_MAP_LEVEL: usize = 2;
55 lazy_static! {
56 pub static ref REGEX_MAP_LEVEL: regex::Regex =
57 #[allow(clippy::invalid_regex)]
58 regex::Regex::new(r"^/map/(?P<level>[^/?#]*)$")
59 .expect("Unable to create regex for MAP_LEVEL");
60 }
61 pub(crate) static ID_MAPS: usize = 3;
62 pub(crate) static ID_REGISTER: usize = 4;
63 pub(crate) static ID_STATISTICS: usize = 5;
64 pub(crate) static ID_STATISTICS_UUID: usize = 6;
65 lazy_static! {
66 pub static ref REGEX_STATISTICS_UUID: regex::Regex =
67 #[allow(clippy::invalid_regex)]
68 regex::Regex::new(r"^/statistics/(?P<UUID>[^/?#]*)$")
69 .expect("Unable to create regex for STATISTICS_UUID");
70 }
71 pub(crate) static ID_USER_UUID: usize = 7;
72 lazy_static! {
73 pub static ref REGEX_USER_UUID: regex::Regex =
74 #[allow(clippy::invalid_regex)]
75 regex::Regex::new(r"^/user/(?P<UUID>[^/?#]*)$")
76 .expect("Unable to create regex for USER_UUID");
77 }
78}
79
80
81pub struct MakeService<T, C> where
82 T: Api<C> + Clone + Send + 'static,
83 C: Has<XSpanIdString> + Send + Sync + 'static
84{
85 api_impl: T,
86 marker: PhantomData<C>,
87}
88
89impl<T, C> MakeService<T, C> where
90 T: Api<C> + Clone + Send + 'static,
91 C: Has<XSpanIdString> + Send + Sync + 'static
92{
93 pub fn new(api_impl: T) -> Self {
94 MakeService {
95 api_impl,
96 marker: PhantomData
97 }
98 }
99}
100
101impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
102 T: Api<C> + Clone + Send + 'static,
103 C: Has<XSpanIdString> + Send + Sync + 'static
104{
105 type Response = Service<T, C>;
106 type Error = crate::ServiceError;
107 type Future = future::Ready<Result<Self::Response, Self::Error>>;
108
109 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
110 Poll::Ready(Ok(()))
111 }
112
113 fn call(&mut self, target: Target) -> Self::Future {
114 let service = Service::new(self.api_impl.clone());
115
116 future::ok(service)
117 }
118}
119
120fn method_not_allowed() -> Result<Response<Body>, crate::ServiceError> {
121 Ok(
122 Response::builder().status(StatusCode::METHOD_NOT_ALLOWED)
123 .body(Body::empty())
124 .expect("Unable to create Method Not Allowed response")
125 )
126}
127
128pub struct Service<T, C> where
129 T: Api<C> + Clone + Send + 'static,
130 C: Has<XSpanIdString> + Send + Sync + 'static
131{
132 api_impl: T,
133 marker: PhantomData<C>,
134}
135
136impl<T, C> Service<T, C> where
137 T: Api<C> + Clone + Send + 'static,
138 C: Has<XSpanIdString> + Send + Sync + 'static
139{
140 pub fn new(api_impl: T) -> Self {
141 Service {
142 api_impl,
143 marker: PhantomData
144 }
145 }
146}
147
148impl<T, C> Clone for Service<T, C> where
149 T: Api<C> + Clone + Send + 'static,
150 C: Has<XSpanIdString> + Send + Sync + 'static
151{
152 fn clone(&self) -> Self {
153 Service {
154 api_impl: self.api_impl.clone(),
155 marker: self.marker,
156 }
157 }
158}
159
160impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
161 T: Api<C> + Clone + Send + Sync + 'static,
162 C: Has<XSpanIdString> + Send + Sync + 'static
163{
164 type Response = Response<Body>;
165 type Error = crate::ServiceError;
166 type Future = ServiceFuture;
167
168 fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
169 self.api_impl.poll_ready(cx)
170 }
171
172 fn call(&mut self, req: (Request<Body>, C)) -> Self::Future {
173 async fn run<T, C>(
174 mut api_impl: T,
175 req: (Request<Body>, C),
176 ) -> Result<Response<Body>, crate::ServiceError> where
177 T: Api<C> + Clone + Send + 'static,
178 C: Has<XSpanIdString> + Send + Sync + 'static
179 {
180 let (request, context) = req;
181 let (parts, body) = request.into_parts();
182 let (method, uri, headers) = (parts.method, parts.uri, parts.headers);
183 let path = paths::GLOBAL_REGEX_SET.matches(uri.path());
184
185 match method {
186
187 hyper::Method::DELETE if path.matched(paths::ID_BOBBY) => {
189 let result = api_impl.bobby_delete(
190 &context
191 ).await;
192 let mut response = Response::new(Body::empty());
193 response.headers_mut().insert(
194 HeaderName::from_static("x-span-id"),
195 HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().as_str())
196 .expect("Unable to create X-Span-ID header value"));
197
198 match result {
199 Ok(rsp) => match rsp {
200 BobbyDeleteResponse::DroppedAllData
201 => {
202 *response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
203
204 },
205 BobbyDeleteResponse::WrongPassphraseProvided
206 => {
207 *response.status_mut() = StatusCode::from_u16(409).expect("Unable to turn 409 into a StatusCode");
208
209 },
210 },
211 Err(_) => {
212 *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
215 *response.body_mut() = Body::from("An internal error occurred");
216 },
217 }
218
219 Ok(response)
220 },
221
222 hyper::Method::POST if path.matched(paths::ID_GAME) => {
224 let result = body.into_raw().await;
228 match result {
229 Ok(body) => {
230 let mut unused_elements : Vec<String> = vec![];
231 let param_game_end_dto: Option<models::GameEndDto> = if !body.is_empty() {
232 let deserializer = &mut serde_json::Deserializer::from_slice(&*body);
233 match serde_ignored::deserialize(deserializer, |path| {
234 warn!("Ignoring unknown field in body: {}", path);
235 unused_elements.push(path.to_string());
236 }) {
237 Ok(param_game_end_dto) => param_game_end_dto,
238 Err(e) => return Ok(Response::builder()
239 .status(StatusCode::BAD_REQUEST)
240 .body(Body::from(format!("Couldn't parse body parameter GameEndDto - doesn't match schema: {}", e)))
241 .expect("Unable to create Bad Request response for invalid body parameter GameEndDto due to schema")),
242 }
243 } else {
244 None
245 };
246 let param_game_end_dto = match param_game_end_dto {
247 Some(param_game_end_dto) => param_game_end_dto,
248 None => return Ok(Response::builder()
249 .status(StatusCode::BAD_REQUEST)
250 .body(Body::from("Missing required body parameter GameEndDto"))
251 .expect("Unable to create Bad Request response for missing body parameter GameEndDto")),
252 };
253
254
255 let result = api_impl.game_post(
256 param_game_end_dto,
257 &context
258 ).await;
259 let mut response = Response::new(Body::empty());
260 response.headers_mut().insert(
261 HeaderName::from_static("x-span-id"),
262 HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().as_str())
263 .expect("Unable to create X-Span-ID header value"));
264
265 if !unused_elements.is_empty() {
266 response.headers_mut().insert(
267 HeaderName::from_static("warning"),
268 HeaderValue::from_str(format!("Ignoring unknown fields in body: {:?}", unused_elements).as_str())
269 .expect("Unable to create Warning header value"));
270 }
271 match result {
272 Ok(rsp) => match rsp {
273 GamePostResponse::GameResultDetails
274 (body)
275 => {
276 *response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
277 response.headers_mut().insert(
278 CONTENT_TYPE,
279 HeaderValue::from_str("application/json")
280 .expect("Unable to create Content-Type header for application/json"));
281 let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
283 *response.body_mut() = Body::from(body);
284
285 },
286 },
287 Err(_) => {
288 *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
291 *response.body_mut() = Body::from("An internal error occurred");
292 },
293 }
294
295 Ok(response)
296 },
297 Err(e) => Ok(Response::builder()
298 .status(StatusCode::BAD_REQUEST)
299 .body(Body::from(format!("Unable to read body: {}", e)))
300 .expect("Unable to create Bad Request response due to unable to read body")),
301 }
302 },
303
304 hyper::Method::GET if path.matched(paths::ID_MAPS) => {
306 let result = api_impl.maps_get(
307 &context
308 ).await;
309 let mut response = Response::new(Body::empty());
310 response.headers_mut().insert(
311 HeaderName::from_static("x-span-id"),
312 HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().as_str())
313 .expect("Unable to create X-Span-ID header value"));
314
315 match result {
316 Ok(rsp) => match rsp {
317 MapsGetResponse::ListOfTheIdsOfAllExistingMaps
318 (body)
319 => {
320 *response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
321 response.headers_mut().insert(
322 CONTENT_TYPE,
323 HeaderValue::from_str("application/json")
324 .expect("Unable to create Content-Type header for application/json"));
325 let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
327 *response.body_mut() = Body::from(body);
328
329 },
330 MapsGetResponse::NoMapsInDatabase
331 => {
332 *response.status_mut() = StatusCode::from_u16(500).expect("Unable to turn 500 into a StatusCode");
333
334 },
335 },
336 Err(_) => {
337 *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
340 *response.body_mut() = Body::from("An internal error occurred");
341 },
342 }
343
344 Ok(response)
345 },
346
347 hyper::Method::POST if path.matched(paths::ID_REGISTER) => {
349 let result = body.into_raw().await;
353 match result {
354 Ok(body) => {
355 let mut unused_elements : Vec<String> = vec![];
356 let param_create_user_dto: Option<models::CreateUserDto> = if !body.is_empty() {
357 let deserializer = &mut serde_json::Deserializer::from_slice(&*body);
358 match serde_ignored::deserialize(deserializer, |path| {
359 warn!("Ignoring unknown field in body: {}", path);
360 unused_elements.push(path.to_string());
361 }) {
362 Ok(param_create_user_dto) => param_create_user_dto,
363 Err(e) => return Ok(Response::builder()
364 .status(StatusCode::BAD_REQUEST)
365 .body(Body::from(format!("Couldn't parse body parameter CreateUserDto - doesn't match schema: {}", e)))
366 .expect("Unable to create Bad Request response for invalid body parameter CreateUserDto due to schema")),
367 }
368 } else {
369 None
370 };
371 let param_create_user_dto = match param_create_user_dto {
372 Some(param_create_user_dto) => param_create_user_dto,
373 None => return Ok(Response::builder()
374 .status(StatusCode::BAD_REQUEST)
375 .body(Body::from("Missing required body parameter CreateUserDto"))
376 .expect("Unable to create Bad Request response for missing body parameter CreateUserDto")),
377 };
378
379
380 let result = api_impl.register_post(
381 param_create_user_dto,
382 &context
383 ).await;
384 let mut response = Response::new(Body::empty());
385 response.headers_mut().insert(
386 HeaderName::from_static("x-span-id"),
387 HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().as_str())
388 .expect("Unable to create X-Span-ID header value"));
389
390 if !unused_elements.is_empty() {
391 response.headers_mut().insert(
392 HeaderName::from_static("warning"),
393 HeaderValue::from_str(format!("Ignoring unknown fields in body: {:?}", unused_elements).as_str())
394 .expect("Unable to create Warning header value"));
395 }
396 match result {
397 Ok(rsp) => match rsp {
398 RegisterPostResponse::Created
399 => {
400 *response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
401
402 },
403 RegisterPostResponse::UserWithThatIDDoesAlreadyExist
404 => {
405 *response.status_mut() = StatusCode::from_u16(409).expect("Unable to turn 409 into a StatusCode");
406
407 },
408 },
409 Err(_) => {
410 *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
413 *response.body_mut() = Body::from("An internal error occurred");
414 },
415 }
416
417 Ok(response)
418 },
419 Err(e) => Ok(Response::builder()
420 .status(StatusCode::BAD_REQUEST)
421 .body(Body::from(format!("Unable to read body: {}", e)))
422 .expect("Unable to create Bad Request response due to unable to read body")),
423 }
424 },
425
426 hyper::Method::GET if path.matched(paths::ID_STATISTICS) => {
428 let result = api_impl.statistics_get(
429 &context
430 ).await;
431 let mut response = Response::new(Body::empty());
432 response.headers_mut().insert(
433 HeaderName::from_static("x-span-id"),
434 HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().as_str())
435 .expect("Unable to create X-Span-ID header value"));
436
437 match result {
438 Ok(rsp) => match rsp {
439 StatisticsGetResponse::GameResultDetails
440 (body)
441 => {
442 *response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
443 response.headers_mut().insert(
444 CONTENT_TYPE,
445 HeaderValue::from_str("application/json")
446 .expect("Unable to create Content-Type header for application/json"));
447 let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
449 *response.body_mut() = Body::from(body);
450
451 },
452 },
453 Err(_) => {
454 *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
457 *response.body_mut() = Body::from("An internal error occurred");
458 },
459 }
460
461 Ok(response)
462 },
463
464 hyper::Method::GET if path.matched(paths::ID_MAP_LEVEL) => {
466 let path: &str = uri.path();
468 let path_params =
469 paths::REGEX_MAP_LEVEL
470 .captures(path)
471 .unwrap_or_else(||
472 panic!("Path {} matched RE MAP_LEVEL in set but failed match against \"{}\"", path, paths::REGEX_MAP_LEVEL.as_str())
473 );
474
475 let param_level = match percent_encoding::percent_decode(path_params["level"].as_bytes()).decode_utf8() {
476 Ok(param_level) => match param_level.parse::<String>() {
477 Ok(param_level) => param_level,
478 Err(e) => return Ok(Response::builder()
479 .status(StatusCode::BAD_REQUEST)
480 .body(Body::from(format!("Couldn't parse path parameter level: {}", e)))
481 .expect("Unable to create Bad Request response for invalid path parameter")),
482 },
483 Err(_) => return Ok(Response::builder()
484 .status(StatusCode::BAD_REQUEST)
485 .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["level"])))
486 .expect("Unable to create Bad Request response for invalid percent decode"))
487 };
488
489 let result = api_impl.map_level_get(
490 param_level,
491 &context
492 ).await;
493 let mut response = Response::new(Body::empty());
494 response.headers_mut().insert(
495 HeaderName::from_static("x-span-id"),
496 HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().as_str())
497 .expect("Unable to create X-Span-ID header value"));
498
499 match result {
500 Ok(rsp) => match rsp {
501 MapLevelGetResponse::BeatMap
502 (body)
503 => {
504 *response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
505 response.headers_mut().insert(
506 CONTENT_TYPE,
507 HeaderValue::from_str("application/json")
508 .expect("Unable to create Content-Type header for application/json"));
509 let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
511 *response.body_mut() = Body::from(body);
512
513 },
514 MapLevelGetResponse::ThisMapDoesNotExist
515 => {
516 *response.status_mut() = StatusCode::from_u16(404).expect("Unable to turn 404 into a StatusCode");
517
518 },
519 },
520 Err(_) => {
521 *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
524 *response.body_mut() = Body::from("An internal error occurred");
525 },
526 }
527
528 Ok(response)
529 },
530
531 hyper::Method::GET if path.matched(paths::ID_STATISTICS_UUID) => {
533 let path: &str = uri.path();
535 let path_params =
536 paths::REGEX_STATISTICS_UUID
537 .captures(path)
538 .unwrap_or_else(||
539 panic!("Path {} matched RE STATISTICS_UUID in set but failed match against \"{}\"", path, paths::REGEX_STATISTICS_UUID.as_str())
540 );
541
542 let param_uuid = match percent_encoding::percent_decode(path_params["UUID"].as_bytes()).decode_utf8() {
543 Ok(param_uuid) => match param_uuid.parse::<String>() {
544 Ok(param_uuid) => param_uuid,
545 Err(e) => return Ok(Response::builder()
546 .status(StatusCode::BAD_REQUEST)
547 .body(Body::from(format!("Couldn't parse path parameter UUID: {}", e)))
548 .expect("Unable to create Bad Request response for invalid path parameter")),
549 },
550 Err(_) => return Ok(Response::builder()
551 .status(StatusCode::BAD_REQUEST)
552 .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["UUID"])))
553 .expect("Unable to create Bad Request response for invalid percent decode"))
554 };
555
556 let result = api_impl.statistics_uuid_get(
557 param_uuid,
558 &context
559 ).await;
560 let mut response = Response::new(Body::empty());
561 response.headers_mut().insert(
562 HeaderName::from_static("x-span-id"),
563 HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().as_str())
564 .expect("Unable to create X-Span-ID header value"));
565
566 match result {
567 Ok(rsp) => match rsp {
568 StatisticsUuidGetResponse::GameResultDetails
569 (body)
570 => {
571 *response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
572 response.headers_mut().insert(
573 CONTENT_TYPE,
574 HeaderValue::from_str("application/json")
575 .expect("Unable to create Content-Type header for application/json"));
576 let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
578 *response.body_mut() = Body::from(body);
579
580 },
581 StatisticsUuidGetResponse::ThisStatisticDoesNotExist
582 => {
583 *response.status_mut() = StatusCode::from_u16(404).expect("Unable to turn 404 into a StatusCode");
584
585 },
586 },
587 Err(_) => {
588 *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
591 *response.body_mut() = Body::from("An internal error occurred");
592 },
593 }
594
595 Ok(response)
596 },
597
598 hyper::Method::GET if path.matched(paths::ID_USER_UUID) => {
600 let path: &str = uri.path();
602 let path_params =
603 paths::REGEX_USER_UUID
604 .captures(path)
605 .unwrap_or_else(||
606 panic!("Path {} matched RE USER_UUID in set but failed match against \"{}\"", path, paths::REGEX_USER_UUID.as_str())
607 );
608
609 let param_uuid = match percent_encoding::percent_decode(path_params["UUID"].as_bytes()).decode_utf8() {
610 Ok(param_uuid) => match param_uuid.parse::<String>() {
611 Ok(param_uuid) => param_uuid,
612 Err(e) => return Ok(Response::builder()
613 .status(StatusCode::BAD_REQUEST)
614 .body(Body::from(format!("Couldn't parse path parameter UUID: {}", e)))
615 .expect("Unable to create Bad Request response for invalid path parameter")),
616 },
617 Err(_) => return Ok(Response::builder()
618 .status(StatusCode::BAD_REQUEST)
619 .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["UUID"])))
620 .expect("Unable to create Bad Request response for invalid percent decode"))
621 };
622
623 let result = api_impl.user_uuid_get(
624 param_uuid,
625 &context
626 ).await;
627 let mut response = Response::new(Body::empty());
628 response.headers_mut().insert(
629 HeaderName::from_static("x-span-id"),
630 HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().as_str())
631 .expect("Unable to create X-Span-ID header value"));
632
633 match result {
634 Ok(rsp) => match rsp {
635 UserUuidGetResponse::SuccessfullyFetchedUserData
636 (body)
637 => {
638 *response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
639 response.headers_mut().insert(
640 CONTENT_TYPE,
641 HeaderValue::from_str("application/json")
642 .expect("Unable to create Content-Type header for application/json"));
643 let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
645 *response.body_mut() = Body::from(body);
646
647 },
648 UserUuidGetResponse::UserWithThatIDDoesExist
649 => {
650 *response.status_mut() = StatusCode::from_u16(404).expect("Unable to turn 404 into a StatusCode");
651
652 },
653 },
654 Err(_) => {
655 *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
658 *response.body_mut() = Body::from("An internal error occurred");
659 },
660 }
661
662 Ok(response)
663 },
664
665 _ if path.matched(paths::ID_BOBBY) => method_not_allowed(),
666 _ if path.matched(paths::ID_GAME) => method_not_allowed(),
667 _ if path.matched(paths::ID_MAP_LEVEL) => method_not_allowed(),
668 _ if path.matched(paths::ID_MAPS) => method_not_allowed(),
669 _ if path.matched(paths::ID_REGISTER) => method_not_allowed(),
670 _ if path.matched(paths::ID_STATISTICS) => method_not_allowed(),
671 _ if path.matched(paths::ID_STATISTICS_UUID) => method_not_allowed(),
672 _ if path.matched(paths::ID_USER_UUID) => method_not_allowed(),
673 _ => Ok(Response::builder().status(StatusCode::NOT_FOUND)
674 .body(Body::empty())
675 .expect("Unable to create Not Found response"))
676 }
677 }
678 Box::pin(run(
679 self.api_impl.clone(),
680 req,
681 ))
682 }
683}
684
685pub struct ApiRequestParser;
687impl<T> RequestParser<T> for ApiRequestParser {
688 fn parse_operation_id(request: &Request<T>) -> Option<&'static str> {
689 let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path());
690 match *request.method() {
691 hyper::Method::DELETE if path.matched(paths::ID_BOBBY) => Some("BobbyDelete"),
693 hyper::Method::POST if path.matched(paths::ID_GAME) => Some("GamePost"),
695 hyper::Method::GET if path.matched(paths::ID_MAPS) => Some("MapsGet"),
697 hyper::Method::POST if path.matched(paths::ID_REGISTER) => Some("RegisterPost"),
699 hyper::Method::GET if path.matched(paths::ID_STATISTICS) => Some("StatisticsGet"),
701 hyper::Method::GET if path.matched(paths::ID_MAP_LEVEL) => Some("MapLevelGet"),
703 hyper::Method::GET if path.matched(paths::ID_STATISTICS_UUID) => Some("StatisticsUuidGet"),
705 hyper::Method::GET if path.matched(paths::ID_USER_UUID) => Some("UserUuidGet"),
707 _ => None,
708 }
709 }
710}