#[cfg(feature = "timezone")]
use crate::Result;
use serde::de::DeserializeOwned;
use wasm_bindgen::JsCast;
#[derive(Debug, Clone)]
pub struct Cf {
inner: worker_sys::IncomingRequestCfProperties,
}
unsafe impl Send for Cf {}
unsafe impl Sync for Cf {}
impl Cf {
#[cfg(feature = "http")]
pub(crate) fn new(inner: worker_sys::IncomingRequestCfProperties) -> Self {
Self { inner }
}
#[cfg(feature = "http")]
pub(crate) fn inner(&self) -> &worker_sys::IncomingRequestCfProperties {
&self.inner
}
pub fn colo(&self) -> String {
self.inner.colo().unwrap()
}
pub fn asn(&self) -> u32 {
self.inner.asn().unwrap()
}
pub fn as_organization(&self) -> String {
self.inner.as_organization().unwrap()
}
pub fn country(&self) -> Option<String> {
self.inner.country().unwrap()
}
pub fn http_protocol(&self) -> String {
self.inner.http_protocol().unwrap()
}
pub fn request_priority(&self) -> Option<RequestPriority> {
if let Some(priority) = self.inner.request_priority().unwrap() {
let mut weight = 1;
let mut exclusive = false;
let mut group = 0;
let mut group_weight = 0;
priority
.as_str()
.split(';')
.map(|key_value_pair| {
let mut iter = key_value_pair.split('=');
let key = iter.next().unwrap(); let value = iter.next().unwrap(); (key, value)
})
.for_each(|(key, value)| match key {
"weight" => weight = value.parse().unwrap(),
"exclusive" => exclusive = value == "1",
"group" => group = value.parse().unwrap(),
"group-weight" => group_weight = value.parse().unwrap(),
_ => unreachable!(),
});
Some(RequestPriority {
weight,
exclusive,
group,
group_weight,
})
} else {
None
}
}
pub fn tls_cipher(&self) -> String {
self.inner.tls_cipher().unwrap()
}
pub fn tls_client_auth(&self) -> Option<TlsClientAuth> {
self.inner.tls_client_auth().unwrap().map(Into::into)
}
pub fn tls_version(&self) -> String {
self.inner.tls_version().unwrap()
}
pub fn city(&self) -> Option<String> {
self.inner.city().unwrap()
}
pub fn continent(&self) -> Option<String> {
self.inner.continent().unwrap()
}
pub fn coordinates(&self) -> Option<(f32, f32)> {
let lat_opt = self.inner.latitude().unwrap();
let lon_opt = self.inner.longitude().unwrap();
match (lat_opt, lon_opt) {
(Some(lat_str), Some(lon_str)) => {
let lat = lat_str.parse().unwrap();
let lon = lon_str.parse().unwrap();
Some((lat, lon))
}
_ => None,
}
}
pub fn postal_code(&self) -> Option<String> {
self.inner.postal_code().unwrap()
}
pub fn metro_code(&self) -> Option<String> {
self.inner.metro_code().unwrap()
}
pub fn region(&self) -> Option<String> {
self.inner.region().unwrap()
}
pub fn region_code(&self) -> Option<String> {
self.inner.region_code().unwrap()
}
#[cfg(feature = "timezone")]
pub fn timezone(&self) -> Result<impl chrono::TimeZone> {
let tz = self.inner.timezone()?;
Ok(tz.parse::<chrono_tz::Tz>()?)
}
pub fn timezone_name(&self) -> String {
self.inner.timezone().unwrap()
}
pub fn is_eu_country(&self) -> bool {
self.inner.is_eu_country().unwrap() == Some("1".to_string())
}
pub fn host_metadata<T: serde::de::DeserializeOwned>(&self) -> crate::Result<Option<T>> {
let host_metadata = self.inner.host_metadata()?;
if host_metadata.is_undefined() {
Ok(None)
} else {
serde_wasm_bindgen::from_value(host_metadata)
.map(Some)
.map_err(|e| wasm_bindgen::JsValue::from(e.to_string()))
}
.map_err(crate::Error::from)
}
}
#[derive(Debug, Clone, Copy)]
pub struct RequestPriority {
pub weight: usize,
pub exclusive: bool,
pub group: usize,
pub group_weight: usize,
}
impl From<worker_sys::IncomingRequestCfProperties> for Cf {
fn from(inner: worker_sys::IncomingRequestCfProperties) -> Self {
Self { inner }
}
}
#[derive(Debug)]
pub struct TlsClientAuth {
inner: worker_sys::TlsClientAuth,
}
impl TlsClientAuth {
pub fn cert_issuer_dn_legacy(&self) -> String {
self.inner.cert_issuer_dn_legacy().unwrap()
}
pub fn cert_issuer_dn(&self) -> String {
self.inner.cert_issuer_dn().unwrap()
}
pub fn cert_issuer_dn_rfc2253(&self) -> String {
self.inner.cert_issuer_dn_rfc2253().unwrap()
}
pub fn cert_subject_dn_legacy(&self) -> String {
self.inner.cert_subject_dn_legacy().unwrap()
}
pub fn cert_verified(&self) -> String {
self.inner.cert_verified().unwrap()
}
pub fn cert_not_after(&self) -> String {
self.inner.cert_not_after().unwrap()
}
pub fn cert_subject_dn(&self) -> String {
self.inner.cert_subject_dn().unwrap()
}
pub fn cert_fingerprint_sha1(&self) -> String {
self.inner.cert_fingerprint_sha1().unwrap()
}
pub fn cert_fingerprint_sha256(&self) -> String {
self.inner.cert_fingerprint_sha256().unwrap()
}
pub fn cert_not_before(&self) -> String {
self.inner.cert_not_before().unwrap()
}
pub fn cert_serial(&self) -> String {
self.inner.cert_serial().unwrap()
}
pub fn cert_presented(&self) -> String {
self.inner.cert_presented().unwrap()
}
pub fn cert_subject_dn_rfc2253(&self) -> String {
self.inner.cert_subject_dn_rfc2253().unwrap()
}
}
impl From<worker_sys::TlsClientAuth> for TlsClientAuth {
fn from(inner: worker_sys::TlsClientAuth) -> Self {
Self { inner }
}
}
#[derive(Clone)]
pub struct CfResponseProperties(pub(crate) js_sys::Object);
impl CfResponseProperties {
pub fn into_raw(self) -> js_sys::Object {
self.0
}
pub fn try_into<T: DeserializeOwned>(self) -> crate::Result<T> {
Ok(serde_wasm_bindgen::from_value(self.0.unchecked_into())?)
}
}
unsafe impl Send for CfResponseProperties {}
unsafe impl Sync for CfResponseProperties {}