From 32cdd40e00748f77722a57b095bcb35e31c362ca Mon Sep 17 00:00:00 2001 From: Rick Arendsen Date: Tue, 16 May 2023 11:08:02 +0200 Subject: [PATCH 1/2] [0.2.0-rc.1] - Add Builder Pattern, Clean Files --- Cargo.toml | 10 ++-- src/endpoint.rs | 65 ++++++++++++++++++++++ src/http.rs | 98 ++++++++++++++++++++++++++++++++++ src/lib.rs | 4 +- src/objects/client.rs | 13 ----- src/objects/endpoint.rs | 23 -------- src/objects/httpclient.rs | 28 ---------- src/objects/mod.rs | 3 -- src/tests/client_tests.rs | 9 ---- src/tests/endpoint_tests.rs | 19 ------- src/tests/http_client_tests.rs | 12 ----- src/tests/mod.rs | 8 --- 12 files changed, 169 insertions(+), 123 deletions(-) create mode 100644 src/endpoint.rs create mode 100644 src/http.rs delete mode 100644 src/objects/client.rs delete mode 100644 src/objects/endpoint.rs delete mode 100644 src/objects/httpclient.rs delete mode 100644 src/objects/mod.rs delete mode 100644 src/tests/client_tests.rs delete mode 100644 src/tests/endpoint_tests.rs delete mode 100644 src/tests/http_client_tests.rs delete mode 100644 src/tests/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 799e93d..b377772 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "multisafepay-rust-sdk" -version = "0.1.0" +version = "0.2.0" edition = "2021" authors = ["Rick Arendsen"] readme = "README.md" @@ -8,16 +8,14 @@ repository = "https://github.com/rikkertthedeveloper/multisafepay-rust-sdk" keywords = ["multisafepay", "ecommerce"] [dependencies] -minreq = { version = "2.8.0", features = ["https"] } - -[dev-dependencies] -pretty_assertions = "1" +curl = "0.4.44" [profile.release] -panic = "unwind" +panic = "abort" opt-level = 3 [profile.production] +panic = "abort" inherits = "release" lto = true codegen-units = 1 diff --git a/src/endpoint.rs b/src/endpoint.rs new file mode 100644 index 0000000..bc1cb02 --- /dev/null +++ b/src/endpoint.rs @@ -0,0 +1,65 @@ +use crate::http::HttpMethod; + +pub enum EndpointAction { + CreateTransaction, +} + +impl EndpointAction { + pub fn builder() -> EndpointActionBuilder { + EndpointActionBuilder::new() + } + + pub fn endpoint(&self, api_key: String) -> Endpoint { + match self { + Self::CreateTransaction => Endpoint::new( + "https://testapi.multisafepay.com/v1/json/orders".to_owned(), + HttpMethod::POST, + api_key, + ), + } + } +} + +pub struct EndpointActionBuilder { + api_key: Option, +} + +impl EndpointActionBuilder { + pub fn new() -> Self { + Self { api_key: None } + } + + pub fn api_key(mut self, api_key: String) -> Self { + self.api_key = Some(api_key); + self + } + + pub fn build(self, action: EndpointAction) -> Endpoint { + let api_key = self.api_key.expect("API key not specified"); + action.endpoint(api_key) + } +} + +pub struct Endpoint { + url: String, + method: HttpMethod, + api_key: String, +} + +impl Endpoint { + pub fn new(url: String, method: HttpMethod, api_key: String) -> Self { + Self { + url, + method, + api_key, + } + } + + pub fn get_method(&self) -> &HttpMethod { + &self.method + } + + pub fn get_url(&self) -> &str { + &self.url + } +} diff --git a/src/http.rs b/src/http.rs new file mode 100644 index 0000000..598d6d3 --- /dev/null +++ b/src/http.rs @@ -0,0 +1,98 @@ +use curl::easy::{Easy, List}; + +#[derive(Debug, Clone)] +pub enum HttpMethod { + GET, + POST, + PUT, + PATCH, +} + +impl HttpMethod { + fn as_str(&self) -> &'static str { + match self { + HttpMethod::GET => "GET", + HttpMethod::POST => "POST", + HttpMethod::PUT => "PUT", + HttpMethod::PATCH => "PATCH", + } + } +} + +pub struct HttpRequestBuilder<'a> { + easy: Easy, + method: Option, + url: Option<&'a str>, + payload: Option<&'a str>, + api_key: Option<&'a str>, +} + +impl<'a> HttpRequestBuilder<'a> { + pub fn new() -> Self { + Self { + easy: Easy::new(), + method: None, + url: None, + payload: None, + api_key: None, + } + } + + pub fn method(mut self, method: HttpMethod) -> Self { + self.method = Some(method); + self + } + + pub fn url(mut self, url: &'a str) -> Self { + self.url = Some(url); + self + } + + pub fn payload(mut self, payload: &'a str) -> Self { + self.payload = Some(payload); + self + } + + pub fn api_key(mut self, api_key: &'a str) -> Self { + self.api_key = Some(api_key); + self + } + + pub fn execute(&mut self) -> Result { + let method = self + .method + .as_ref() + .expect("HTTP method not specified") + .as_str(); + let url = self.url.expect("URL not specified"); + + self.easy.url(url)?; + self.easy.custom_request(method)?; + + if let Some(payload_data) = self.payload { + self.easy.post(true)?; + self.easy.post_fields_copy(payload_data.as_bytes())?; + } + + if let Some(api_key) = self.api_key { + let mut headers = List::new(); + headers.append(&format!("api_key: {}", api_key))?; + headers.append("accept: application/json")?; + headers.append("content-type: application/json")?; + self.easy.http_headers(headers)?; + } + + let mut response_data = Vec::new(); + { + let mut transfer = self.easy.transfer(); + transfer.write_function(|data| { + response_data.extend_from_slice(data); + Ok(data.len()) + })?; + transfer.perform()?; + } + + let response_string = String::from_utf8_lossy(&response_data).to_string(); + Ok(response_string) + } +} diff --git a/src/lib.rs b/src/lib.rs index 2bf4753..be6bd44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,2 @@ -mod objects; -mod tests; +pub mod endpoint; +pub mod http; diff --git a/src/objects/client.rs b/src/objects/client.rs deleted file mode 100644 index 90da590..0000000 --- a/src/objects/client.rs +++ /dev/null @@ -1,13 +0,0 @@ -pub struct Client { - api_key: String, -} - -impl Client { - pub fn new(api_key: String) -> Self { - Self { api_key } - } - - pub fn verify(&self) -> bool { - !self.api_key.is_empty() - } -} diff --git a/src/objects/endpoint.rs b/src/objects/endpoint.rs deleted file mode 100644 index ebf5e48..0000000 --- a/src/objects/endpoint.rs +++ /dev/null @@ -1,23 +0,0 @@ -pub struct Endpoint { - url: String, - api_key: String, -} - -impl Endpoint { - pub fn new(url: String, api_key: String) -> Self { - Self { url, api_key } - } - - pub fn format(&self) -> String { - assert!(self.verify(), "Failed to verify endpoint string."); - format!("{}?api-key={}", self.url, self.api_key) - } - - fn verify_format(&self) -> bool { - self.url.is_empty() || !self.api_key.is_empty() - } - - pub fn verify(&self) -> bool { - self.verify_format() - } -} diff --git a/src/objects/httpclient.rs b/src/objects/httpclient.rs deleted file mode 100644 index 9138927..0000000 --- a/src/objects/httpclient.rs +++ /dev/null @@ -1,28 +0,0 @@ -use minreq::{self, Response, Error}; - -pub struct HttpClient { - url: String, - method: String, -} - -impl HttpClient { - pub fn new(url: String, method: String) -> Self { - Self { url, method } - } - - pub fn post(&self, payload: String) -> Result { - let response = minreq::post(self.url.to_owned()) - .with_body(payload) - .send()?; - - let parsed = response.as_str()?; - Ok(parsed.to_owned()) - } - - pub fn get(&self) -> Result { - let response: Response = minreq::get(self.url.to_owned()).send()?; - let parsed = response.as_str()?; - - Ok(parsed.to_owned()) - } -} diff --git a/src/objects/mod.rs b/src/objects/mod.rs deleted file mode 100644 index 2019b0a..0000000 --- a/src/objects/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub(crate) mod endpoint; -pub(crate) mod client; -pub(crate) mod httpclient; diff --git a/src/tests/client_tests.rs b/src/tests/client_tests.rs deleted file mode 100644 index ac8d5b8..0000000 --- a/src/tests/client_tests.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::objects::client::Client as Client; - -#[test] -fn test_client_verification() { - let api_key = "my-api-key"; - let my_client = Client::new(api_key.to_owned()); - - assert!(my_client.verify()) -} diff --git a/src/tests/endpoint_tests.rs b/src/tests/endpoint_tests.rs deleted file mode 100644 index 9abf3f4..0000000 --- a/src/tests/endpoint_tests.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::objects::endpoint::Endpoint as Endpoint; - -#[test] -fn test_endpoint_formatting() { - let endpoint_url: &str = "https://my-url.com"; - let endpoint_api_key: &str = "my-api-key"; - let my_endpoint: Endpoint = Endpoint::new(endpoint_url.to_string(), endpoint_api_key.to_string()); - - assert_eq!(my_endpoint.format(), format!("{}?api-key={}", endpoint_url.clone(), endpoint_api_key.clone())); -} - -#[test] -fn test_endpoint_verification() { - let endpoint_url: &str = "https://my-url.com"; - let endpoint_api_key: &str = "my-api-key"; - let my_endpoint: Endpoint = Endpoint::new(endpoint_url.to_string(), endpoint_api_key.to_string()); - - assert!(my_endpoint.verify()) -} diff --git a/src/tests/http_client_tests.rs b/src/tests/http_client_tests.rs deleted file mode 100644 index 0ca3232..0000000 --- a/src/tests/http_client_tests.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::objects::httpclient::HttpClient as HttpClient; - -#[test] -fn http_get_functionality() { - let endpoint_url = "https://dummyjson.com/test"; - let endpoint_method = "GET"; - - let my_client = HttpClient::new(endpoint_url.to_owned(), endpoint_method.to_owned()); - let http_result = my_client.get(); - - assert_ne!(http_result.unwrap(), "") -} diff --git a/src/tests/mod.rs b/src/tests/mod.rs deleted file mode 100644 index 412116a..0000000 --- a/src/tests/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[cfg(test)] -mod client_tests; - -#[cfg(test)] -mod endpoint_tests; - -#[cfg(test)] -mod http_client_tests; From 94e88d4328e149e9879bb2b48f8c92e937297218 Mon Sep 17 00:00:00 2001 From: Rick Arendsen Date: Tue, 16 May 2023 11:30:46 +0200 Subject: [PATCH 2/2] [0.2.1-rc.1] - Add Tests, Fix crates.io prerequisites. --- Cargo.toml | 8 +++++++- LICENSE.txt | 21 +++++++++++++++++++++ README.md | 3 --- src/endpoint.rs | 8 +++----- src/lib.rs | 1 + src/tests/endpoint_test.rs | 11 +++++++++++ src/tests/http_test.rs | 12 ++++++++++++ src/tests/mod.rs | 6 ++++++ 8 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 LICENSE.txt create mode 100644 src/tests/endpoint_test.rs create mode 100644 src/tests/http_test.rs create mode 100644 src/tests/mod.rs diff --git a/Cargo.toml b/Cargo.toml index b377772..e042612 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,15 @@ [package] name = "multisafepay-rust-sdk" -version = "0.2.0" +version = "0.2.1" +description="A MultiSafePay SDK for the Rust Programming Language" edition = "2021" authors = ["Rick Arendsen"] readme = "README.md" repository = "https://github.com/rikkertthedeveloper/multisafepay-rust-sdk" keywords = ["multisafepay", "ecommerce"] +license-file = "LICENSE.txt" +categories = ["sdk", "multisafepay"] +documentation = "https://docs.rs/multisafepay-rust-sdk" [dependencies] curl = "0.4.44" @@ -13,6 +17,8 @@ curl = "0.4.44" [profile.release] panic = "abort" opt-level = 3 +lto = true +codegen-units = 1 [profile.production] panic = "abort" diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..5db3132 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Rick Arendsen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 44433be..526d11c 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,3 @@ The MultiSafePay Rust SDK makes use of the "Cargo" toolchain included within rus ## Tests The tests within this project can be ran with the `cargo test` command. This project has built-in tests for all classes associated with the libary. - -### Offline testing -This library makes use of mockup data sites such as **DummyJSON** in order to test it's internal parsing tools. If you'd like to fully test offline, you can add the `--offline` flag to your `cargo test` command. diff --git a/src/endpoint.rs b/src/endpoint.rs index bc1cb02..660fb88 100644 --- a/src/endpoint.rs +++ b/src/endpoint.rs @@ -11,11 +11,9 @@ impl EndpointAction { pub fn endpoint(&self, api_key: String) -> Endpoint { match self { - Self::CreateTransaction => Endpoint::new( - "https://testapi.multisafepay.com/v1/json/orders".to_owned(), - HttpMethod::POST, - api_key, - ), + Self::CreateTransaction => { + Endpoint::new("https://testapi.multisafepay.com/v1/json/orders".to_owned(), HttpMethod::POST, api_key) + } } } } diff --git a/src/lib.rs b/src/lib.rs index be6bd44..f16f4ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ pub mod endpoint; pub mod http; +pub mod tests; diff --git a/src/tests/endpoint_test.rs b/src/tests/endpoint_test.rs new file mode 100644 index 0000000..b6b7822 --- /dev/null +++ b/src/tests/endpoint_test.rs @@ -0,0 +1,11 @@ +use crate::endpoint::{EndpointActionBuilder, EndpointAction}; + +#[test] +fn test_endpoint_url() { + let api_key = "testing-api_key"; + let my_endpoint = EndpointActionBuilder::new() + .api_key(api_key.to_owned()) + .build(EndpointAction::CreateTransaction); + + assert_eq!(my_endpoint.get_url(), "https://testapi.multisafepay.com/v1/json/orders") +} diff --git a/src/tests/http_test.rs b/src/tests/http_test.rs new file mode 100644 index 0000000..bd93131 --- /dev/null +++ b/src/tests/http_test.rs @@ -0,0 +1,12 @@ +use crate::http::{HttpMethod, HttpRequestBuilder}; + +#[test] +fn test_endpoint_url() { + let http_result = HttpRequestBuilder::new() + .api_key("my-api-key") + .url("https://example.com") + .method(HttpMethod::GET) + .execute(); + + assert!(http_result.is_ok()); +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs new file mode 100644 index 0000000..b717362 --- /dev/null +++ b/src/tests/mod.rs @@ -0,0 +1,6 @@ +#[cfg(test)] + +mod endpoint_test; +#[cfg(test)] + +mod http_test;