Skip to content

Commit

Permalink
remove url deps
Browse files Browse the repository at this point in the history
  • Loading branch information
SteelAlloy committed Sep 15, 2024
1 parent 08282ad commit ae2e8b9
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 163 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ jobs:
- uses: actions/checkout@v4
- name: Build
run: cargo build --verbose
- name: Clippy
run: cargo clippy --verbose
- name: Run tests
run: cargo test --verbose
93 changes: 1 addition & 92 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "thumbor"
description = "A Rust client for the Thumbor image service"
version = "0.0.4"
version = "0.1.0"
repository = "https://github.com/SteelAlloy/thumbor-rs"
documentation = "https://docs.rs/thumbor"
readme = "README.md"
Expand All @@ -20,10 +20,8 @@ cargo = "deny"
pedantic = "deny"

[dependencies]
url = "2.5.2"
strum = { version = "0.26.3", features = ["derive"] }
thiserror = "1.0.63"
http = "1.1.0"
hmac = "0.12.1"
sha1 = "0.10.6"
base64ct = { version = "1.6.0", features = ["alloc"] }
Expand Down
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,29 @@

## Usage

In short :

```rust
use thumbor::Server;

let url = Server::new("http://localhost:8888", "my-security-key")
.unwrap()
.settings_builder()
.resize((300, 200))
.smart(true)
.build()
.to_url("path/to/my/image.jpg");
```

```rust
use thumbor::Server;

let server = Server::new_secured("http://localhost:8888", "my-security-key");
let server = Server::new("http://localhost:8888", "my-security-key").unwrap();

let builder = server.url_builder()
let settings_builder = server.settings_builder()
.resize((300, 200))
.smart(true)
.build();

let url = builder.build("/path/to/my/image.jpg");
let url = settings_builder.to_url("path/to/my/image.jpg");
```
7 changes: 1 addition & 6 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("{0}")]
UrlParseError(#[from] url::ParseError),
#[error("URL cannot be a base")]
UrlCannotBeABase,
}
pub enum Error {}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![deny(clippy::unwrap_used)]

pub mod error;
pub mod geometry;
mod server;
Expand Down
46 changes: 31 additions & 15 deletions src/server.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::settings::{Settings, SettingsBuilder};
use hmac::Hmac;
use hmac::{digest::InvalidLength, Hmac, Mac};
use sha1::Sha1;

pub type HmacSha1 = Hmac<Sha1>;
Expand All @@ -8,20 +8,22 @@ pub type HmacSha1 = Hmac<Sha1>;
pub enum Security {
#[default]
Unsafe,
Hmac(String),
Hmac(HmacSha1),
}

impl From<String> for Security {
fn from(value: String) -> Self {
Security::Hmac(value)
impl TryFrom<String> for Security {
type Error = InvalidLength;

fn try_from(value: String) -> Result<Self, Self::Error> {
let hmac = HmacSha1::new_from_slice(value.as_bytes())?;
Ok(Security::Hmac(hmac))
}
}

/// ```
/// use thumbor::Server;
///
/// let server = Server::new_secured("http://localhost:8888", "my-security-key");
/// let server = Server::new_unsafe("http://localhost:8888"); // Don't use this in production !
///
/// let server = Server::new("http://localhost:8888", "my-security-key").unwrap();
/// ```
#[derive(Default, Clone)]
pub struct Server {
Expand All @@ -30,20 +32,34 @@ pub struct Server {
}

impl Server {
pub fn new_unsafe(origin: impl Into<String>) -> Self {
Server {
pub fn new(origin: impl Into<String>, key: impl Into<String>) -> Result<Self, InvalidLength> {
Ok(Server {
origin: origin.into(),
security: Security::Unsafe,
}
security: key.into().try_into()?,
})
}
pub fn new_secured(origin: impl Into<String>, key: impl Into<String>) -> Self {

/// ```
/// use thumbor::Server;
///
/// // Don't use this in production !
/// let server = Server::new_unsafe("http://localhost:8888");
/// ```
pub fn new_unsafe(origin: impl Into<String>) -> Self {
Server {
origin: origin.into(),
security: Security::Hmac(key.into()),
security: Security::Unsafe,
}
}

pub fn url_builder(&self) -> SettingsBuilder {
/// Create a new SettingsBuilder with the current Server.
/// ```
/// use thumbor::Server;
///
/// let server = Server::new("http://localhost:8888", "my-security-key").unwrap();
/// let builder = server.settings_builder();
/// ```
pub fn settings_builder(&self) -> SettingsBuilder {
Settings::with_server(self.clone())
}
}
38 changes: 10 additions & 28 deletions src/settings/builder.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
use super::{FitIn, ResponseMode, Settings, Trim};
use crate::server::Security;
use base64ct::{Base64Url, Encoding};
use hmac::Mac;
use http::Uri;

use crate::{
error::Error,
server::{HmacSha1, Security},
};

use super::{FitIn, ResponseMode, Settings, Trim};

impl Settings {
fn build_path(&self, image_uri: &str) -> String {
Expand Down Expand Up @@ -80,36 +74,24 @@ impl Settings {
path.join("/")
}

/// # Errors
/// - `Error::UrlParseError`: URL parsing failed.
/// - `Error::UrlCannotBeABase`: this URL is cannot-be-a-base.
/// # Panics
/// TODO: doc
pub fn build(&self, image_uri: &str) -> Result<String, Error> {
pub fn to_path(&self, image_uri: &str) -> String {
let path = self.build_path(image_uri);

let security = match &self.server.security {
Security::Unsafe => "unsafe".to_owned(),
Security::Hmac(secret_key) => {
let mut mac = HmacSha1::new_from_slice(secret_key.as_bytes()).unwrap();

Security::Unsafe => "unsafe",
Security::Hmac(hmac) => {
let mut mac = hmac.clone();
mac.update(path.as_bytes());

let signature = mac.finalize().into_bytes();

Base64Url::encode_string(&signature)
&Base64Url::encode_string(&signature)
}
};

Ok(format!("{}/{}/{}", self.server.origin, security, path))
format!("/{security}/{path}")
}

/// # Errors
/// - `Error::UrlParseError`: URL parsing failed.
/// - `Error::UrlCannotBeABase`: this URL is cannot-be-a-base.
/// # Panics
/// TODO: doc
pub fn build_uri(&self, image_uri: &str) -> Result<Uri, Error> {
Ok(self.build(image_uri).unwrap().parse::<Uri>().unwrap())
pub fn to_url(&self, image_uri: &str) -> String {
format!("{}{}", self.server.origin, self.to_path(image_uri))
}
}
Loading

0 comments on commit ae2e8b9

Please sign in to comment.