kong_rs 0.2.0

Plugin Development Kit for developing Kong plugins in Rust
Documentation
use http::HeaderMap;
use kong_rs_protos::RawBodyResult;
use strum::{EnumString, IntoStaticStr};

use crate::{stream::Stream, KongError, KongResult};

pub enum Body {
  Content(Vec<u8>),
  Path(String),
  Empty
}

#[derive(Debug, PartialEq, IntoStaticStr, EnumString)]
pub(crate) enum Methods {
  #[strum(serialize = "kong.request.get_scheme")]
  GetScheme,
  #[strum(serialize = "kong.request.get_host")]
  GetHost,
  #[strum(serialize = "kong.request.get_port")]
  GetPort,
  #[strum(serialize = "kong.request.get_forwarded_scheme")]
  GetForwardedScheme,
  #[strum(serialize = "kong.request.get_forwarded_host")]
  GetForwardedHost,
  #[strum(serialize = "kong.request.get_forwarded_port")]
  GetForwardedPort,
  #[strum(serialize = "kong.request.get_http_version")]
  GetHttpVersion,
  #[strum(serialize = "kong.request.get_method")]
  GetMethod,
  #[strum(serialize = "kong.request.get_path")]
  GetPath,
  #[strum(serialize = "kong.request.get_path_with_query")]
  GetPathWithQuery,
  #[strum(serialize = "kong.request.get_raw_query")]
  GetRawQuery,
  #[strum(serialize = "kong.request.get_query_arg")]
  GetQueryArg,
  #[strum(serialize = "kong.request.get_query")]
  GetQuery,
  #[strum(serialize = "kong.request.get_header")]
  GetHeader,
  #[strum(serialize = "kong.request.get_headers")]
  GetHeaders,
  #[strum(serialize = "kong.request.get_raw_body")]
  GetRawBody,
}

#[derive(Clone)]
pub struct RequestPDK {
  stream: Stream,
}

impl RequestPDK {
  pub fn new(stream: Stream) -> Self {
    Self { stream }
  }

  pub async fn get_scheme(&self) -> KongResult<String> {
    self.stream.ask_string(Methods::GetScheme.into()).await
  }

  pub async fn get_host(&self) -> KongResult<String> {
    self.stream.ask_string(Methods::GetHost.into()).await
  }

  pub async fn get_port(&self) -> KongResult<usize> {
    self.stream
      .ask_int(Methods::GetPort.into())
      .await
      .map(|port| port as usize)
  }

  pub async fn get_forwarded_scheme(&self) -> KongResult<String> {
    self.stream
      .ask_string(Methods::GetForwardedScheme.into())
      .await
  }

  pub async fn get_forwarded_host(&self) -> KongResult<String> {
    self.stream
      .ask_string(Methods::GetForwardedHost.into())
      .await
  }

  pub async fn get_forwarded_port(&self) -> KongResult<usize> {
    self.stream
      .ask_int(Methods::GetForwardedPort.into())
      .await
      .map(|port| port as usize)
  }

  pub async fn get_http_version(&self) -> KongResult<f64> {
    self.stream
      .ask_number(Methods::GetForwardedPort.into())
      .await
  }

  pub async fn get_method(&self) -> KongResult<String> {
    self.stream.ask_string(Methods::GetMethod.into()).await
  }

  pub async fn get_path(&self) -> KongResult<String> {
    self.stream.ask_string(Methods::GetPath.into()).await
  }

  pub async fn get_path_with_query(&self) -> KongResult<String> {
    self.stream
      .ask_string(Methods::GetPathWithQuery.into())
      .await
  }

  pub async fn get_raw_query(&self) -> KongResult<String> {
    self.stream.ask_string(Methods::GetRawQuery.into()).await
  }

  pub async fn get_query_arg(&self, name: String) -> KongResult<String> {
    self.stream
      .ask_string_with_args(Methods::GetQueryArg.into(), &kong_rs_protos::String { v: name })
      .await
  }

  pub async fn get_query(&self, max_args: Option<usize>) -> KongResult<HeaderMap> {
    let max_args = max_args.unwrap_or(100);
    let headers: prost_types::Struct = self.stream.ask_message_with_args(
      Methods::GetQuery.into(),
      &kong_rs_protos::Int { v: max_args as i32 }
    ).await?;
    self.stream.unwrap_headers(headers)
  }

  pub async fn get_header(&self, name: String) -> KongResult<String> {
    self.stream
      .ask_string_with_args(Methods::GetHeader.into(), &kong_rs_protos::String { v: name })
      .await
  }

  pub async fn get_headers(&self, max_headers: Option<usize>) -> KongResult<HeaderMap> {
    let max_headers = max_headers.unwrap_or(100);
    let headers: prost_types::Struct = self.stream.ask_message_with_args(
      Methods::GetHeaders.into(),
      &kong_rs_protos::Int { v: max_headers as i32 }
    ).await?;
    self.stream.unwrap_headers(headers)
  }

  pub async fn get_raw_body(&self) -> KongResult<Body> {
    let body: RawBodyResult = self.stream.ask_message(Methods::GetRawBody.into()).await?;
    match body.kind {
      Some(kind) => match kind {
        kong_rs_protos::raw_body_result::Kind::Content(items) => {
          Ok(Body::Content(items))
        },
        kong_rs_protos::raw_body_result::Kind::BodyFilepath(path) => {
          Ok(Body::Path(path))
        },
        kong_rs_protos::raw_body_result::Kind::Error(err) => {
          Err(KongError::BodyError(format!("Body Error: {}", err)))
        },
      },
      None => Ok(Body::Empty),
    }
  }
}