Skip to content

Commit

Permalink
update apis
Browse files Browse the repository at this point in the history
  • Loading branch information
victorteokw committed Dec 8, 2024
1 parent 220a623 commit 7912496
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 89 deletions.
17 changes: 9 additions & 8 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,27 +257,28 @@ export declare class TestServer {
process(request: TestRequest): Promise<TestResponse>
}
export declare class TestRequest {
constructor(props: { method?: string, uri: string, headers?: { [key: string]: string }, body?: any })
constructor(props: { method?: string, uri: string, headers?: { [key: string]: string }, body?: any, cookies?: Cookie[] })
get method(): string
set method(method: string)
get uri(): string
set uri(uri: string)
insertHeader(key: string, value: string): void
appendHeader(key: string, value: string): void
get headers(): Headers
set headers(headers: Headers)
insertHeader(key: string, value: string): this
appendHeader(key: string, value: string): this
get body(): Buffer
set body(body: Buffer)
get cookies(): Cookies
set cookies(cookies: Cookies)
}
export declare class TestResponse {
get status(): number
get version(): string
body(): Buffer
bodyAsString(): string
bodyAsJson(): any
containsHeader(name: string): boolean
headerValue(name: string): string | null
headerValues(name: string): Array<string>
headerKeys(): string[]
headersLength(): number
get headers(): Headers
get cookies(): Cookies
}
export class TeoError extends Error {
constructor(message: string, code?: number, errors?: { [key: string]: string } | null)
Expand Down
1 change: 1 addition & 0 deletions src/cookies/cookies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use napi::{Env, JsFunction, JsUnknown, Result};
use teo::prelude::cookies::Cookies as OriginalCookies;
use super::cookie::Cookie;

#[derive(Clone)]
#[napi]
pub struct Cookies {
original: OriginalCookies
Expand Down
1 change: 1 addition & 0 deletions src/headers/headers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use teo::prelude::headers::Headers as OriginalHeaders;
use napi::Result;

#[derive(Clone)]
#[napi]
pub struct Headers {
original: OriginalHeaders
Expand Down
2 changes: 1 addition & 1 deletion src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub fn js_any_to_teo_value(any: JsUnknown, env: Env) -> Result<Value> {
let len = object.get_array_length()?;
let mut result: Vec<Value> = vec![];
for n in 0..len {
let item: JsUnknown = object.get_element(n).unwrap();
let item: JsUnknown = object.get_element(n)?;
result.push(js_any_to_teo_value(item, env)?);
}
Value::Array(result)
Expand Down
76 changes: 51 additions & 25 deletions src/test/test_request.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
use std::str::FromStr;
use hyper::{header::{HeaderName, HeaderValue}, HeaderMap, Method};
use napi::{bindgen_prelude::Buffer, Env, JsBuffer, JsFunction, JsObject, JsString, JsUnknown, Result, ValueType};
use napi::{bindgen_prelude::{Buffer, FromNapiRef}, Env, JsBuffer, JsFunction, JsObject, JsString, JsUnknown, NapiRaw, Result, ValueType};
use http_body_util::Full;
use bytes::Bytes;
use crate::{cookies::{Cookie, Cookies}, headers::headers::Headers};

#[napi]
pub struct TestRequest {
method: Method,
uri: String,
headers: HeaderMap,
headers: Headers,
body: Bytes,
cookies: Cookies,
}

#[napi]
impl TestRequest {
#[napi(constructor, ts_args_type = "props: { method?: string, uri: string, headers?: { [key: string]: string }, body?: any }")]
#[napi(constructor, ts_args_type = "props: { method?: string, uri: string, headers?: { [key: string]: string }, body?: any, cookies?: Cookie[] }")]
pub fn new(props: JsObject, env: Env) -> Result<Self> {
let method: Option<String> = props.get_named_property("method")?;
let method = match method {
Expand Down Expand Up @@ -42,6 +44,8 @@ impl TestRequest {
});
}
}
let headers = teo::prelude::headers::Headers::from(headers);
let headers = Headers::from(headers);
let body: Option<JsUnknown> = props.get_named_property("body")?;
let body = match body {
Some(body) => {
Expand Down Expand Up @@ -70,11 +74,23 @@ impl TestRequest {
},
None => Bytes::new(),
};
let mut cookies = vec![];
let cookies_object: Option<JsObject> = props.get_named_property("cookies")?;
if let Some(cookies_object) = cookies_object {
let len = cookies_object.get_array_length()?;
for n in 0..len {
let item_object: JsUnknown = cookies_object.get_element(n)?;
let cookie: &Cookie = unsafe { Cookie::from_napi_ref(env.raw(), item_object.raw())? };
cookies.push(cookie);
}
}
let cookies = Cookies::new(Some(cookies));
Ok(Self {
method,
uri,
headers,
body,
cookies,
})
}

Expand Down Expand Up @@ -104,28 +120,26 @@ impl TestRequest {
self.uri = uri;
}

#[napi(getter)]
pub fn headers(&self) -> Headers {
self.headers.clone()
}

#[napi(setter)]
pub fn set_headers(&mut self, headers: &Headers) {
self.headers = headers.clone();
}

#[napi]
pub fn insert_header(&mut self, key: String, value: String) -> Result<()> {
self.headers.insert(match HeaderName::try_from(key) {
Ok(value) => value,
Err(_) => return Err(teo_result::Error::internal_server_error_message("cannot parse header name").into()),
}, match HeaderValue::from_str(value.as_str()) {
Ok(value) => value,
Err(_) => return Err(teo_result::Error::internal_server_error_message("cannot parse header value").into()),
});
Ok(())
pub fn insert_header(&mut self, key: String, value: String) -> Result<&Self> {
self.headers.set(key, value)?;
Ok(self)
}

#[napi]
pub fn append_header(&mut self, key: String, value: String) -> Result<()> {
self.headers.append(match HeaderName::try_from(key) {
Ok(value) => value,
Err(_) => return Err(teo_result::Error::internal_server_error_message("cannot parse header name").into()),
}, match HeaderValue::from_str(value.as_str()) {
Ok(value) => value,
Err(_) => return Err(teo_result::Error::internal_server_error_message("cannot parse header value").into()),
});
Ok(())
pub fn append_header(&mut self, key: String, value: String) -> Result<&Self> {
self.headers.append(key, value)?;
Ok(self)
}

#[napi(getter)]
Expand All @@ -139,13 +153,25 @@ impl TestRequest {
self.body = Bytes::copy_from_slice(&body_vec);
}

#[napi(getter)]
pub fn cookies(&self) -> Cookies {
self.cookies.clone()
}

#[napi(setter)]
pub fn set_cookies(&mut self, cookies: &Cookies) {
self.cookies = cookies.clone();
}

pub(crate) fn to_hyper_request(&self) -> hyper::Request<Full<Bytes>> {
let mut request = hyper::Request::builder()
let request = hyper::Request::builder()
.method(self.method.clone())
.uri(self.uri.clone());
for (key, value) in self.headers.iter() {
request = request.header(key.clone(), value.clone());
let mut request = request.body(Full::new(self.body.clone())).unwrap();
self.headers.original().extend_to(request.headers_mut());
for cookie in self.cookies.original().iter() {
request.headers_mut().append("Cookie", HeaderValue::try_from(cookie.encoded()).unwrap());
}
request.body(Full::new(self.body.clone())).unwrap()
request
}
}
74 changes: 20 additions & 54 deletions src/test/test_response.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
use napi::{bindgen_prelude::Buffer, Env, JsFunction, JsGlobal, JsObject, JsUnknown, Result};
use teo::server::test_response::TestResponse as OriginalTestResponse;
use crate::{cookies::Cookies, headers::headers::Headers};

#[napi]
pub struct TestResponse {
teo_test_response: teo::server::test_response::TestResponse,
original: OriginalTestResponse,
}

impl From<OriginalTestResponse> for TestResponse {
fn from(original: OriginalTestResponse) -> Self {
Self { original }
}
}

#[napi]
impl TestResponse {
pub(super) fn new(teo_test_response: teo::server::test_response::TestResponse) -> Self {
Self {
teo_test_response,
}
}

#[napi(getter)]
pub fn status(&self) -> u16 {
self.teo_test_response.status().as_u16()
self.original.status().as_u16()
}

#[napi(getter)]
pub fn version(&self) -> String {
format!("{:?}", self.teo_test_response.version())
format!("{:?}", self.original.version())
}

#[napi]
pub fn body(&self) -> Buffer {
Buffer::from(Vec::<u8>::from(self.teo_test_response.body().clone()))
Buffer::from(Vec::<u8>::from(self.original.body().clone()))
}

#[napi]
pub fn body_as_string(&self) -> String {
self.teo_test_response.body_as_string()
self.original.body_as_string()
}

#[napi(ts_return_type = "any")]
pub fn body_as_json(&self, env: Env) -> Result<JsUnknown> {
let string = self.teo_test_response.body_as_string();
let string = self.original.body_as_string();
let js_string = env.create_string(&string)?;
let global: JsGlobal = env.get_global()?;
let json: JsObject = global.get_named_property("JSON")?;
Expand All @@ -44,50 +47,13 @@ impl TestResponse {
Ok(json_result)
}

#[napi]
pub fn contains_header(&self, name: String) -> bool {
self.teo_test_response.headers().contains_key(name.as_str())
}

#[napi]
pub fn header_value(&self, name: String) -> Result<Option<&str>> {
let header_value = self.teo_test_response.headers().get(name.as_str());
match header_value {
None => Ok(None),
Some(header_value) => {
let header_value = header_value.to_str().map_err(|_| {
teo_result::Error::internal_server_error_message(format!("cannot read request header value: {}", name))
})?;
Ok(Some(header_value))
}
}
}

#[napi]
pub fn header_values(&self, name: String) -> Result<Vec<&str>> {
let header_values = self.teo_test_response.headers().get_all(name.as_str());
let mut result = Vec::new();
for header_value in header_values {
let header_value = header_value.to_str().map_err(|_| {
teo_result::Error::internal_server_error_message(format!("cannot read request header value: {}", name))
})?;
result.push(header_value);
}
Ok(result)
}

#[napi(js_name = "headerKeys", ts_return_type = "string[]")]
pub fn header_keys(&self) -> Vec<&str> {
let header_map = self.teo_test_response.headers();
let mut result = vec![];
header_map.keys().for_each(|k| {
result.push(k.as_str());
});
result
#[napi(getter)]
pub fn headers(&self) -> Headers {
Headers::from(self.original.headers().clone())
}

#[napi]
pub fn headers_length(&self) -> i64 {
self.teo_test_response.headers().len() as i64
#[napi(getter)]
pub fn cookies(&self) -> Cookies {
Cookies::from(self.original.cookies().clone())
}
}
2 changes: 1 addition & 1 deletion src/test/test_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ impl TestServer {
pub async fn process(&self, request: &TestRequest) -> Result<TestResponse> {
let hyper_request = request.to_hyper_request();
let response = self.server.process_test_request_with_hyper_request(hyper_request).await?;
Ok(TestResponse::new(response))
Ok(TestResponse::from(response))
}
}

0 comments on commit 7912496

Please sign in to comment.