Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion shippo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "shippo"
description = "An API client for Shippo"
version = "0.1.29"
version = "0.2.0"
authors = ["Jess Frazelle <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
Expand All @@ -14,3 +14,8 @@ reqwest = { version = "0.11", features = ["json"] }
schemars = { version = "0.8", features = ["chrono", "uuid"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

[dev-dependencies]
httpmock = "0.6"
serde_json = "1.0"
tokio = { version = "1.17.0", features = ["macros"] }
98 changes: 59 additions & 39 deletions shippo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,53 +34,73 @@ use serde::{
Deserialize, Serialize,
};

/// Endpoint for the Shippo API.
const ENDPOINT: &str = "https://api.goshippo.com/";
/// URL for the Shippo API.
const BASE_URL: &str = "https://api.goshippo.com/";

/// Entrypoint for interacting with the Shippo API.
pub struct Shippo {
/// Options for requests to API.
pub struct ApiOpt {
base_url: Url,
token: String,
}

/// Entrypoint for interacting with the Shippo API.
pub struct Shippo {
client: Arc<Client>,
opt: ApiOpt,
}

impl Shippo {
/// Create a new Shippo client struct. It takes a type that can convert into
/// an &str (`String` or `Vec<u8>` for example). As long as the function is
/// given a valid API Token your requests will work.
/// Create a new Shippo client.
///
/// # Arguments
///
/// * `token` - Shippo API authentication
///
/// # Examples
///
/// ```ignore
/// let client = Shippo::new("secret");
/// let client2 = Shippo::new_from_env();
/// ```
pub fn new<K>(token: K) -> Self
where
K: ToString,
{
let client = Client::builder().build();
match client {
Ok(c) => Self {
token: token.to_string(),

client: Arc::new(c),
opt: ApiOpt {
token: token.to_string(),
base_url: Url::parse(BASE_URL).unwrap(),
},
},
Err(e) => panic!("creating client failed: {:?}", e),
}
}

/// Create a new Shippo client struct from environment variables. It
/// takes a type that can convert into
/// an &str (`String` or `Vec<u8>` for example). As long as the function is
/// given a valid API Token and your requests will work.
/// Create a new Shippo client struct from environment variables:
/// env::var(SHIPPO_API_TOKEN) - used for API authentication header
pub fn new_from_env() -> Self {
let token = env::var("SHIPPO_API_TOKEN").unwrap();

Shippo::new(token)
}

/// Set the base url for `Shippo`
pub fn base_url(mut self, base_url: Url) -> Self {
self.opt.base_url = base_url;
self
}

fn request<B>(&self, method: Method, path: &str, body: B, query: Option<Vec<(String, String)>>) -> Request
where
B: Serialize,
{
let base = Url::parse(ENDPOINT).unwrap();
let base = &self.opt.base_url;
let url = base.join(path).unwrap();

let bt = format!("ShippoToken {}", self.token);
let bt = format!("ShippoToken {}", self.opt.token);
let bearer = header::HeaderValue::from_str(&bt).unwrap();

// Set the default headers.
Expand Down Expand Up @@ -522,7 +542,7 @@ impl error::Error for APIError {
}

/// The data type for an API response.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct APIResponse {
#[serde(
default,
Expand All @@ -542,7 +562,7 @@ pub struct APIResponse {
}

/// The data type for an API response.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct OrdersAPIResponse {
#[serde(
default,
Expand All @@ -562,7 +582,7 @@ pub struct OrdersAPIResponse {
}

/// The data type for an API response for carrier accounts.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct CarrierAccountsAPIResponse {
#[serde(
default,
Expand All @@ -582,7 +602,7 @@ pub struct CarrierAccountsAPIResponse {
}

/// The data type for a transactions API response.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct TransactionsAPIResponse {
#[serde(
default,
Expand All @@ -603,7 +623,7 @@ pub struct TransactionsAPIResponse {

/// The data type for a Shipment.
/// FROM: https://goshippo.com/docs/reference#shipments
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Shipment {
/// "Waiting" shipments have been successfully submitted but not yet been
/// processed. "Queued" shipments are currently being processed. "Success"
Expand Down Expand Up @@ -661,7 +681,7 @@ pub struct Shipment {

/// The data type for a carrier account.
/// FROM: https://goshippo.com/docs/reference#carrier-accounts
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize, PartialEq)]
pub struct CarrierAccount {
/// Unique identifier of the given CarrierAccount object.
pub object_id: String,
Expand Down Expand Up @@ -690,7 +710,7 @@ pub struct CarrierAccount {

/// The data type for an address.
/// FROM: https://goshippo.com/docs/reference#addresses
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize, PartialEq)]
pub struct Address {
/// Unique identifier of the given Address object. This ID is required to
/// create a Shipment object.
Expand Down Expand Up @@ -786,7 +806,7 @@ impl Address {

/// The data type for a parcel.
/// FROM: https://goshippo.com/docs/reference#parcels
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct Parcel {
/// A Parcel will only be valid when all required values have been sent and
/// validated successfully.
Expand Down Expand Up @@ -846,7 +866,7 @@ pub struct Parcel {
/// A rate is an available service of a shipping provider for a given shipment,
/// typically including the price and transit time.
/// FROM: https://goshippo.com/docs/reference#rates
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Rate {
/// Unique identifier of the given Rate object.
#[serde(default, skip_serializing_if = "String::is_empty")]
Expand Down Expand Up @@ -911,7 +931,7 @@ pub struct Rate {
}

/// The service level data type.
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize, PartialEq)]
pub struct ServiceLevel {
/// Name of the Rate's servicelevel, e.g. "International Priority" or
/// "Standard Post".
Expand Down Expand Up @@ -940,7 +960,7 @@ pub struct ServiceLevel {
pub terms: String,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct NewShipment {
/// Address object that should be used as sender Address.
#[serde(default)]
Expand All @@ -958,7 +978,7 @@ pub struct NewShipment {

/// The data type for a pickup.
/// FROM: https://goshippo.com/docs/reference#pickups
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Pickup {
/// Unique identifier of the given Pickup object.
#[serde(default, skip_serializing_if = "String::is_empty")]
Expand Down Expand Up @@ -1023,7 +1043,7 @@ pub struct Pickup {
}

/// The location data type.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct Location {
/// Where your parcels will be available for pickup.
/// "Security Deck" and "Shipping Dock" are only supported for DHL Express.
Expand All @@ -1047,7 +1067,7 @@ pub struct Location {
pub address: Address,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct NewPickup {
#[serde(default)]
pub carrier_account: String,
Expand All @@ -1065,7 +1085,7 @@ pub struct NewPickup {
/// The data type for a transaction.
/// A transaction is the purchase of a shipping label from a shipping provider for a specific service.
/// FROM: https://goshippo.com/docs/reference#transactions
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Transaction {
/// Unique identifier of the given Transaction object.
#[serde(default, skip_serializing_if = "String::is_empty")]
Expand Down Expand Up @@ -1150,7 +1170,7 @@ pub struct Transaction {
pub test: bool,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct NewTransaction {
pub rate: String,
#[serde(default, skip_serializing_if = "String::is_empty")]
Expand All @@ -1161,7 +1181,7 @@ pub struct NewTransaction {
pub r#async: bool,
}

#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize, PartialEq)]
pub struct Message {
#[serde(default, skip_serializing_if = "String::is_empty")]
pub source: String,
Expand All @@ -1171,7 +1191,7 @@ pub struct Message {
pub text: String,
}

#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize, PartialEq)]
pub struct ValidationResults {
#[serde(default)]
pub is_valid: bool,
Expand All @@ -1185,7 +1205,7 @@ pub struct ValidationResults {
/// The data type for a tracking status.
/// Tracking Status objects are used to track shipments.
/// FROM: https://goshippo.com/docs/reference#tracks
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize, PartialEq)]
pub struct TrackingStatus {
/// Name of the carrier of the shipment to track.
#[serde(
Expand Down Expand Up @@ -1248,7 +1268,7 @@ pub struct TrackingStatus {
pub metadata: String,
}

#[derive(Clone, Default, Debug, JsonSchema, Serialize, Deserialize)]
#[derive(Clone, Default, Debug, JsonSchema, Serialize, Deserialize, PartialEq)]
pub struct Status {
/// Indicates the high level status of the shipment.
/// 'UNKNOWN' | 'PRE_TRANSIT' | 'TRANSIT' | 'DELIVERED' | 'RETURNED' | 'FAILURE'
Expand Down Expand Up @@ -1277,7 +1297,7 @@ pub struct Status {
pub location: Option<TrackingLocation>,
}

#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, JsonSchema, Serialize, Deserialize, PartialEq)]
pub struct TrackingLocation {
#[serde(
default,
Expand Down Expand Up @@ -1323,7 +1343,7 @@ impl TrackingLocation {
/// Customs declarations are relevant information, including one or multiple
/// customs items, you need to provide for customs clearance for your international shipments.
/// FROM: https://goshippo.com/docs/reference#customs-declarations
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct CustomsDeclaration {
/// Unique identifier of the given object.
#[serde(default, skip_serializing_if = "String::is_empty")]
Expand Down Expand Up @@ -1406,7 +1426,7 @@ pub struct CustomsDeclaration {

/// An order object.
/// FROM: https://goshippo.com/docs/reference#orders
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Order {
/// Unique identifier of the given object.
#[serde(default, skip_serializing_if = "String::is_empty")]
Expand Down Expand Up @@ -1506,7 +1526,7 @@ pub struct Order {
/// A customs item object.
/// Customs items are distinct items in your international shipment parcel.
/// FROM: https://goshippo.com/docs/reference#customs-items
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct CustomsItem {
/// Unique identifier of the given object.
#[serde(default, skip_serializing_if = "String::is_empty")]
Expand Down
Loading