LCOV - code coverage report
Current view: top level - libs/utils/src/http - request.rs (source / functions) Coverage Total Hit
Test: 32f4a56327bc9da697706839ed4836b2a00a408f.info Lines: 81.5 % 65 53
Test Date: 2024-02-07 07:37:29 Functions: 58.1 % 31 18

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

Generated by: LCOV version 2.1-beta