Skip to content

Commit a6573df

Browse files
Transport Implementation (#8)
* Initial implementation * Fixed issues, introduced tests and features * ci: run tests in other platforms (windows, wasm) * Initial implementation * Fixed issues, introduced tests and features * Cleaned up the code, testable code * Fixed ci * Fixed ci * Removed .unwrap() where not necessary * Added comments and edited ci Co-authored-by: Luis Moreno <[email protected]> Co-authored-by: Luis Moreno <[email protected]>
1 parent 037e1b0 commit a6573df

File tree

10 files changed

+539
-6
lines changed

10 files changed

+539
-6
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ jobs:
1212
strategy:
1313
matrix:
1414
platform: [
15-
{ os: "windows", target: "x86_64-pc-windows-msvc" },
1615
{ os: "ubuntu", target: "x86_64-unknown-linux-gnu" },
1716
{ os: "ubuntu", target: "wasm32-unknown-unknown" },
1817
]
@@ -33,6 +32,13 @@ jobs:
3332
target: ${{ matrix.platform.target }}
3433
profile: minimal
3534
default: true
35+
- name: Install httpmock
36+
uses: actions-rs/cargo@v1
37+
with:
38+
command: install
39+
args: --features standalone -- httpmock
40+
- name: Run httpmock
41+
run: httpmock --expose --static-mock-dir=./mocks &
3642
- name: Install test runner for wasm
3743
if: matrix.platform.target == 'wasm32-unknown-unknown'
3844
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
@@ -49,4 +55,4 @@ jobs:
4955
args: --all-features
5056
- name: Tests in WASM
5157
if: matrix.platform.target == 'wasm32-unknown-unknown'
52-
run: wasm-pack test --node -- --all-features
58+
run: wasm-pack test --headless --chrome

Cargo.toml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,31 @@ version = "0.1.0"
44
authors = ["Typesense <[email protected]>"]
55
edition = "2018"
66

7-
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
[features]
8+
default = []
9+
tokio-rt = ["hyper/runtime", "hyper/tcp", "hyper-tls"]
10+
11+
[lib]
12+
crate-type = ["cdylib", "rlib"]
813

914
[dependencies]
15+
async-trait = "0.1.50"
16+
http = "0.2.4"
1017
thiserror = "1.0.24"
1118

19+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
20+
hyper = { version = "0.14.7", features = ["http1", "http2", "client"] }
21+
hyper-tls = { version = "0.5.0", optional = true }
22+
23+
[target.'cfg(target_arch = "wasm32")'.dependencies]
24+
js-sys = { version = "0.3.50" }
25+
wasm-bindgen = { version = "0.2.73" }
26+
wasm-bindgen-futures = { version = "0.4.23" }
27+
web-sys = { version = "0.3.50", features = ["Headers", "Response", "Request", "RequestInit", "RequestMode", "Window", "WorkerGlobalScope"] }
28+
29+
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
30+
tokio = { version = "1.5.0", features = ["macros", "rt", "rt-multi-thread"] }
31+
1232
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
13-
wasm-bindgen-test = "0.3"
33+
console_error_panic_hook = "0.1.6"
34+
wasm-bindgen-test = "0.3.23"

mocks/get.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
when:
2+
method: GET
3+
path: /
4+
header:
5+
- name: Test
6+
value: test
7+
then:
8+
status: 200
9+
header:
10+
- name: content-type
11+
value: text/html
12+
- name: Access-Control-Allow-Origin
13+
value: \*
14+
body: "Test Successful"

mocks/post.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
when:
2+
method: POST
3+
path: /
4+
header:
5+
- name: Test
6+
value: test
7+
body: "Test Successful"
8+
then:
9+
status: 200
10+
header:
11+
- name: content-type
12+
value: text/html
13+
body: "Test Successful"

src/error.rs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1+
use http::StatusCode;
12
use thiserror::Error;
23

3-
/// [`Result`](std::result::Result) type that is returned from functions with error
4-
/// as [`TypesenseError`](crate::error::TypesenseError).
4+
/// [`Result`](std::result::Result) type that is returned from
5+
/// functions with error as [`TypesenseError`].
56
pub type Result<T> = std::result::Result<T, TypesenseError>;
67

78
/// Represents an error that can occur while using the library.
89
#[derive(Error, Debug)]
910
pub enum TypesenseError {
11+
/// TypesenseClientError
12+
#[error("typesense client error")]
13+
TypesenseClientError,
14+
1015
/// Config error.
1116
#[error("config error")]
1217
ConfigError,
@@ -50,4 +55,51 @@ pub enum TypesenseError {
5055
/// HTTP status error.
5156
#[error("HTTP status error")]
5257
HttpStatusError,
58+
59+
/// HTTP error.
60+
#[error("http error: {0}")]
61+
HttpError(#[from] http::Error),
62+
63+
/// Hyper error.
64+
#[cfg(not(target_arch = "wasm32"))]
65+
#[cfg_attr(docsrs, doc(cfg(not(target_arch = "wasm32"))))]
66+
#[error("hyper error: {0}")]
67+
HyperError(#[from] hyper::Error),
68+
69+
/// WASM error.
70+
#[cfg(target_arch = "wasm32")]
71+
#[cfg_attr(docsrs, doc(cfg(target_arch = "wasm32")))]
72+
#[error("wasm client error: {0:?}")]
73+
WasmError(String),
74+
}
75+
76+
impl From<StatusCode> for TypesenseError {
77+
fn from(status: StatusCode) -> Self {
78+
match status {
79+
// 400
80+
StatusCode::BAD_REQUEST => Self::RequestMalformed,
81+
// 401
82+
StatusCode::UNAUTHORIZED => Self::RequestUnauthorized,
83+
// 403
84+
StatusCode::FORBIDDEN => Self::RequestForbidden,
85+
// 404
86+
StatusCode::NOT_FOUND => Self::ObjectNotFound,
87+
// 409
88+
StatusCode::CONFLICT => Self::ObjectAlreadyExists,
89+
// 422
90+
StatusCode::UNPROCESSABLE_ENTITY => Self::ObjectUnprocessable,
91+
// 500
92+
StatusCode::INTERNAL_SERVER_ERROR => Self::ServerError,
93+
// 503
94+
StatusCode::SERVICE_UNAVAILABLE => Self::ServiceUnavailable,
95+
_ => Self::TypesenseClientError,
96+
}
97+
}
98+
}
99+
100+
#[cfg(target_arch = "wasm32")]
101+
impl From<wasm_bindgen::JsValue> for TypesenseError {
102+
fn from(value: wasm_bindgen::JsValue) -> Self {
103+
Self::WasmError(format!("{:?}", value))
104+
}
53105
}

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#![deny(missing_docs)]
2+
#![cfg_attr(docsrs, feature(doc_cfg))]
3+
24
//! # Typesense
35
//!
46
//! Welcome to typesense, the rust library for the Typesense API.
57
68
mod error;
9+
pub mod transport;
710

811
pub use error::{Result, TypesenseError};

src/transport/builder.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use super::http_low_level;
2+
use super::Transport;
3+
4+
/// The [`TransportBuilder`] to build [`Transport`].
5+
///
6+
/// Used to build [`Transport`] with custom configuration.
7+
pub struct TransportBuilder<C> {
8+
client: C,
9+
}
10+
11+
#[cfg(all(feature = "tokio-rt", not(target_arch = "wasm32")))]
12+
#[cfg_attr(
13+
docsrs,
14+
doc(cfg(all(feature = "tokio-rt", not(target_arch = "wasm32"))))
15+
)]
16+
impl TransportBuilder<http_low_level::HyperHttpsClient> {
17+
/// Used to make a new [`hyper`](https://docs.rs/hyper) client.
18+
/// The connector used is [`HttpsConnector`](hyper_tls::HttpsConnector).
19+
pub fn new_hyper() -> Self {
20+
let https = http_low_level::HttpsConnector::new();
21+
let client = hyper::Client::builder().build(https);
22+
23+
Self { client }
24+
}
25+
}
26+
27+
#[cfg(not(target_arch = "wasm32"))]
28+
#[cfg_attr(docsrs, doc(cfg(not(target_arch = "wasm32"))))]
29+
impl<C> TransportBuilder<http_low_level::HyperClient<C>>
30+
where
31+
C: hyper::client::connect::Connect + Clone,
32+
{
33+
/// Used to make a new custom [`hyper`](https://docs.rs/hyper) client.
34+
/// Provide your own executor and connector.
35+
pub fn new_custom_hyper<E>(executor: E, connector: C) -> Self
36+
where
37+
E: hyper::rt::Executor<std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send>>>
38+
+ Send
39+
+ Sync
40+
+ 'static,
41+
{
42+
let client = hyper::Client::builder().executor(executor).build(connector);
43+
44+
Self { client }
45+
}
46+
}
47+
48+
#[cfg(target_arch = "wasm32")]
49+
#[cfg_attr(docsrs, doc(cfg(target_arch = "wasm32")))]
50+
impl TransportBuilder<http_low_level::WasmClient> {
51+
/// Used to make a new wasm client.
52+
pub fn new_wasm() -> Self {
53+
Self {
54+
client: http_low_level::WasmClient,
55+
}
56+
}
57+
}
58+
59+
impl<C> TransportBuilder<C> {
60+
/// Make a [`Transport`] struct from the builder.
61+
pub fn build(self) -> Transport<C> {
62+
Transport {
63+
client: self.client,
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)