1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#![cfg_attr(feature = "unstable-doc", feature(external_doc))]
// Warnings (other than unused variables) in doctests are promoted to errors.
#![doc(test(attr(deny(warnings))))]
#![doc(test(attr(allow(dead_code))))]
#![doc(test(attr(allow(unused_variables))))]
// #![warn(missing_docs)]

//! User API for Compute@Edge.
//!
//! **Note**: this is currently a beta preview of an upcoming `fastly` crate version. In particular,
//! the documentation is not yet complete, and may contain some inaccuracies where content is left
//! over from the previous versions.
//!
#![cfg_attr(not(feature = "unstable-doc"), doc = "# ⚠ Warning: incomplete docs!")]
#![cfg_attr(
    not(feature = "unstable-doc"),
    doc = "The rustdoc for this crate relies on nightly features."
)]
#![cfg_attr(
    not(feature = "unstable-doc"),
    doc = "To build the complete documentation, run:"
)]
#![cfg_attr(
    not(feature = "unstable-doc"),
    doc = "```text\ncargo +nightly doc --features unstable-doc\n```"
)]
mod abi;

/// Backends.
mod backend;
/// HTTP bodies.
mod body;
pub mod convert;
/// Edge dictionary lookup functions.
pub mod dictionary;
/// Error-handling.
pub mod error;
/// Geographic data for IP addresses.
pub mod geo;
pub mod handle;
pub mod limits;
/// Logging utilities.
pub mod log;
/// HTTP responses.
#[macro_use]
pub mod response;
/// HTTP requests.
pub mod request;

pub use crate::backend::{Backend, BackendError};
pub use crate::body::{Body, StreamingBody};
pub use crate::convert::{ToHeaderName, ToHeaderValue};
pub use crate::error::{Error, SendError};
pub use crate::request::{select, PendingRequest, Request};
pub use crate::response::Response;
pub use fastly_macros::main;
pub use http::{self, Method};
pub use mime::{self, Mime};
pub use url::Url;

/// Parse a user agent string.
pub fn uap_parse(
    user_agent: &str,
) -> Result<(String, Option<String>, Option<String>, Option<String>), Error> {
    let user_agent: &[u8] = user_agent.as_ref();
    let max_length = 255;
    let mut family = Vec::with_capacity(max_length);
    let mut major = Vec::with_capacity(max_length);
    let mut minor = Vec::with_capacity(max_length);
    let mut patch = Vec::with_capacity(max_length);
    let mut family_nwritten = 0;
    let mut major_nwritten = 0;
    let mut minor_nwritten = 0;
    let mut patch_nwritten = 0;

    let status = unsafe {
        abi::fastly_uap::parse(
            user_agent.as_ptr(),
            user_agent.len(),
            family.as_mut_ptr(),
            family.capacity(),
            &mut family_nwritten,
            major.as_mut_ptr(),
            major.capacity(),
            &mut major_nwritten,
            minor.as_mut_ptr(),
            minor.capacity(),
            &mut minor_nwritten,
            patch.as_mut_ptr(),
            patch.capacity(),
            &mut patch_nwritten,
        )
    };
    if status.is_err() {
        return Err(Error::msg("fastly_uap::parse failed"));
    }
    assert!(
        family_nwritten <= family.capacity(),
        "fastly_uap::parse wrote too many bytes for family"
    );
    unsafe {
        family.set_len(family_nwritten);
    }
    assert!(
        major_nwritten <= major.capacity(),
        "fastly_uap::parse wrote too many bytes for major"
    );
    unsafe {
        major.set_len(major_nwritten);
    }
    assert!(
        minor_nwritten <= minor.capacity(),
        "fastly_uap::parse wrote too many bytes for minor"
    );
    unsafe {
        minor.set_len(minor_nwritten);
    }
    assert!(
        patch_nwritten <= patch.capacity(),
        "fastly_uap::parse wrote too many bytes for patch"
    );
    unsafe {
        patch.set_len(patch_nwritten);
    }
    Ok((
        String::from_utf8_lossy(&family).to_string(),
        Some(String::from_utf8_lossy(&major).to_string()),
        Some(String::from_utf8_lossy(&minor).to_string()),
        Some(String::from_utf8_lossy(&patch).to_string()),
    ))
}

/// Tell the runtime what ABI version this program is using.
pub fn init() {
    unsafe { abi::fastly_abi::init(abi::FASTLY_ABI_VERSION) };
}