LCOV - differential code coverage report
Current view: top level - libs/utils/src/http - request.rs (source / functions) Coverage Total Hit UBC CBC
Current: cd44433dd675caa99df17a61b18949c8387e2242.info Lines: 81.5 % 65 53 12 53
Current Date: 2024-01-09 02:06:09 Functions: 56.7 % 30 17 13 17
Baseline: 66c52a629a0f4a503e193045e0df4c77139e344b.info
Baseline Date: 2024-01-08 15:34:46

           TLA  Line data    Source code
       1                 : use core::fmt;
       2                 : use std::{borrow::Cow, str::FromStr};
       3                 : 
       4                 : use super::error::ApiError;
       5                 : use anyhow::anyhow;
       6                 : use hyper::{body::HttpBody, Body, Request};
       7                 : use routerify::ext::RequestExt;
       8                 : 
       9 CBC       16249 : pub fn get_request_param<'a>(
      10           16249 :     request: &'a Request<Body>,
      11           16249 :     param_name: &str,
      12           16249 : ) -> Result<&'a str, ApiError> {
      13           16249 :     match request.param(param_name) {
      14           16249 :         Some(arg) => Ok(arg),
      15 UBC           0 :         None => Err(ApiError::BadRequest(anyhow!(
      16               0 :             "no {param_name} specified in path param",
      17               0 :         ))),
      18                 :     }
      19 CBC       16249 : }
      20                 : 
      21           14002 : pub fn parse_request_param<T: FromStr>(
      22           14002 :     request: &Request<Body>,
      23           14002 :     param_name: &str,
      24           14002 : ) -> Result<T, ApiError> {
      25           14002 :     match get_request_param(request, param_name)?.parse() {
      26           14002 :         Ok(v) => Ok(v),
      27 UBC           0 :         Err(_) => Err(ApiError::BadRequest(anyhow!(
      28               0 :             "failed to parse {param_name}",
      29               0 :         ))),
      30                 :     }
      31 CBC       14002 : }
      32                 : 
      33            3521 : fn get_query_param<'a>(
      34            3521 :     request: &'a Request<Body>,
      35            3521 :     param_name: &str,
      36            3521 : ) -> Result<Option<Cow<'a, str>>, ApiError> {
      37            3521 :     let query = match request.uri().query() {
      38             230 :         Some(q) => q,
      39            3291 :         None => return Ok(None),
      40                 :     };
      41             230 :     let mut values = url::form_urlencoded::parse(query.as_bytes())
      42             359 :         .filter_map(|(k, v)| if k == param_name { Some(v) } else { None })
      43             230 :         // we call .next() twice below. If it's None the first time, .fuse() ensures it's None afterwards
      44             230 :         .fuse();
      45             230 : 
      46             230 :     let value1 = values.next();
      47             230 :     if values.next().is_some() {
      48 UBC           0 :         return Err(ApiError::BadRequest(anyhow!(
      49               0 :             "param {param_name} specified more than once"
      50               0 :         )));
      51 CBC         230 :     }
      52             230 :     Ok(value1)
      53            3521 : }
      54                 : 
      55              25 : pub fn must_get_query_param<'a>(
      56              25 :     request: &'a Request<Body>,
      57              25 :     param_name: &str,
      58              25 : ) -> Result<Cow<'a, str>, ApiError> {
      59              25 :     get_query_param(request, param_name)?.ok_or_else(|| {
      60 UBC           0 :         ApiError::BadRequest(anyhow!("no {param_name} specified in query parameters"))
      61 CBC          25 :     })
      62              25 : }
      63                 : 
      64            3496 : pub fn parse_query_param<E: fmt::Display, T: FromStr<Err = E>>(
      65            3496 :     request: &Request<Body>,
      66            3496 :     param_name: &str,
      67            3496 : ) -> Result<Option<T>, ApiError> {
      68            3496 :     get_query_param(request, param_name)?
      69            3496 :         .map(|v| {
      70             190 :             v.parse().map_err(|e| {
      71 UBC           0 :                 ApiError::BadRequest(anyhow!("cannot parse query param {param_name}: {e}"))
      72 CBC         190 :             })
      73            3496 :         })
      74            3496 :         .transpose()
      75            3496 : }
      76                 : 
      77              20 : pub async fn ensure_no_body(request: &mut Request<Body>) -> Result<(), ApiError> {
      78              20 :     match request.body_mut().data().await {
      79 UBC           0 :         Some(_) => Err(ApiError::BadRequest(anyhow!("Unexpected request body"))),
      80 CBC          20 :         None => Ok(()),
      81                 :     }
      82              20 : }
        

Generated by: LCOV version 2.1-beta