Skip to content

Commit 0ed045f

Browse files
authored
Merge pull request #11 from jmjoy/0.2.0-alpha.2-dev
2 parents 107d40b + a6326f6 commit 0ed045f

File tree

21 files changed

+546
-86
lines changed

21 files changed

+546
-86
lines changed

examples/hello/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub fn get_module() -> Module {
6262
);
6363

6464
// register classes
65-
let mut foo_class = DynamicClass::new();
65+
let mut foo_class = DynamicClass::new("FooClass");
6666
foo_class.add_property("foo", "100".to_string());
6767
foo_class.add_method(
6868
"getFoo",
@@ -80,7 +80,7 @@ pub fn get_module() -> Module {
8080
},
8181
vec![Argument::by_val("foo")],
8282
);
83-
module.add_class("FooClass", foo_class);
83+
module.add_class(foo_class);
8484

8585
module
8686
}

examples/hello/tests/php/test.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@
2626

2727
function assert_eq($left, $right) {
2828
if ($left !== $right) {
29-
throw new Exception(sprintf("left != right,\n left: %s,\n right: %s", var_export($left, true), var_export($right, true)));
29+
throw new AssertionError(sprintf("left != right,\n left: %s,\n right: %s", var_export($left, true), var_export($right, true)));
3030
}
3131
}

examples/http-client/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@ license = "Unlicense"
1212
crate-type = ["cdylib"]
1313

1414
[dependencies]
15+
anyhow = "1.0.40"
16+
bytes = "1.0.1"
17+
indexmap = "1.6.2"
1518
phper = { version = "0.2.0-alpha.2", path = "../../phper" }
1619
reqwest = { version = "0.11.3", features = ["blocking"] }
20+
thiserror = "1.0.24"
1721

1822
[dev-dependencies]
1923
phper-test = { version = "0.2.0-alpha.2", path = "../../phper-test" }

examples/http-client/src/client.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use crate::{
2+
errors::HttpClientError,
3+
response::{ReadiedResponse, RESPONSE_CLASS_NAME},
4+
};
5+
6+
use phper::{classes::DynamicClass, functions::Argument, objects::Object};
7+
use reqwest::blocking::{Client, ClientBuilder};
8+
use std::time::Duration;
9+
10+
const HTTP_CLIENT_CLASS_NAME: &'static str = "HttpClient\\HttpClient";
11+
12+
pub fn make_client_class() -> DynamicClass<Client> {
13+
let mut class = DynamicClass::new_with_constructor(HTTP_CLIENT_CLASS_NAME, || {
14+
let client = ClientBuilder::new()
15+
.timeout(Duration::from_secs(15))
16+
.build()?;
17+
Ok::<_, HttpClientError>(client)
18+
});
19+
20+
class.add_method(
21+
"get",
22+
|this, arguments| {
23+
let url = arguments[0].as_string()?;
24+
let client = this.as_state();
25+
let response = client.get(url).send()?;
26+
27+
let readied_response = ReadiedResponse {
28+
status: response.status(),
29+
remote_addr: response.remote_addr(),
30+
headers: response.headers().clone(),
31+
body: response.bytes()?,
32+
};
33+
34+
let mut response_object =
35+
Object::<Option<ReadiedResponse>>::new_by_class_name(RESPONSE_CLASS_NAME)?;
36+
*response_object.as_mut_state() = Some(readied_response);
37+
38+
Ok::<_, HttpClientError>(response_object)
39+
},
40+
vec![Argument::by_val("url")],
41+
);
42+
43+
class
44+
}

examples/http-client/src/errors.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use phper::{
2+
classes::{ClassEntry, DynamicClass, StatelessClassEntry},
3+
errors::Throwable,
4+
};
5+
6+
const EXCEPTION_CLASS_NAME: &'static str = "HttpClient\\HttpClientException";
7+
8+
#[derive(thiserror::Error, Debug)]
9+
pub enum HttpClientError {
10+
#[error(transparent)]
11+
Phper(#[from] phper::Error),
12+
13+
#[error(transparent)]
14+
Reqwest(#[from] reqwest::Error),
15+
}
16+
17+
impl Throwable for HttpClientError {
18+
fn class_entry(&self) -> &StatelessClassEntry {
19+
ClassEntry::from_globals(EXCEPTION_CLASS_NAME).unwrap()
20+
}
21+
}
22+
23+
pub fn make_exception_class() -> DynamicClass<()> {
24+
let mut exception_class = DynamicClass::new(EXCEPTION_CLASS_NAME);
25+
exception_class.extends("Exception");
26+
exception_class
27+
}

examples/http-client/src/http_client.rs

Lines changed: 0 additions & 15 deletions
This file was deleted.

examples/http-client/src/lib.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
use phper::{classes::DynamicClass, modules::Module, php_get_module};
1+
use crate::{
2+
client::make_client_class, errors::make_exception_class, response::make_response_class,
3+
};
4+
use phper::{modules::Module, php_get_module};
25

3-
pub mod http_client;
6+
pub mod client;
7+
pub mod errors;
8+
pub mod response;
49

510
#[php_get_module]
611
pub fn get_module() -> Module {
@@ -10,9 +15,9 @@ pub fn get_module() -> Module {
1015
env!("CARGO_PKG_AUTHORS"),
1116
);
1217

13-
// let client = HttpClient::new();
14-
let client_class: DynamicClass<()> = DynamicClass::new();
15-
module.add_class("HttpClient", client_class);
18+
module.add_class(make_client_class());
19+
module.add_class(make_exception_class());
20+
module.add_class(make_response_class());
1621

1722
module
1823
}

examples/http-client/src/response.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use bytes::Bytes;
2+
use indexmap::map::IndexMap;
3+
use phper::classes::DynamicClass;
4+
use reqwest::{header::HeaderMap, StatusCode};
5+
use std::{convert::Infallible, net::SocketAddr};
6+
7+
pub const RESPONSE_CLASS_NAME: &'static str = "HttpClient\\Response";
8+
9+
pub struct ReadiedResponse {
10+
pub status: StatusCode,
11+
pub remote_addr: Option<SocketAddr>,
12+
pub headers: HeaderMap,
13+
pub body: Bytes,
14+
}
15+
16+
pub fn make_response_class() -> DynamicClass<Option<ReadiedResponse>> {
17+
let mut class = DynamicClass::new_with_constructor(RESPONSE_CLASS_NAME, || {
18+
Ok::<Option<ReadiedResponse>, Infallible>(None)
19+
});
20+
21+
class.add_method(
22+
"body",
23+
|this, _arguments| {
24+
let readied_response = this.as_state().as_ref().unwrap();
25+
let body: &[u8] = readied_response.body.as_ref();
26+
body.to_vec()
27+
},
28+
vec![],
29+
);
30+
31+
class.add_method(
32+
"status",
33+
|this, _arguments| {
34+
let readied_response = this.as_state().as_ref().unwrap();
35+
readied_response.status.as_u16() as i64
36+
},
37+
vec![],
38+
);
39+
40+
class.add_method(
41+
"headers",
42+
|this, _arguments| {
43+
let readied_response = this.as_state().as_ref().unwrap();
44+
let headers_map =
45+
readied_response
46+
.headers
47+
.iter()
48+
.fold(IndexMap::new(), |mut acc, (key, value)| {
49+
acc.entry(key.as_str().to_owned())
50+
.or_insert(vec![])
51+
.push(value.as_bytes().to_owned());
52+
acc
53+
});
54+
headers_map
55+
},
56+
vec![],
57+
);
58+
59+
class
60+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use phper_test::test_php_scripts;
2+
use std::{env, path::Path};
3+
4+
#[test]
5+
fn test_php() {
6+
test_php_scripts(
7+
env!("CARGO_BIN_EXE_http-client"),
8+
&[&Path::new(env!("CARGO_MANIFEST_DIR"))
9+
.join("tests")
10+
.join("php")
11+
.join("test.php")],
12+
);
13+
}
Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11
<?php
22

3+
use HttpClient\HttpClient;
4+
use HttpClient\HttpClientException;
5+
36
ini_set("display_errors", "On");
47
ini_set("display_startup_errors", "On");
58
error_reporting(E_ALL);
69

7-
phpinfo();
10+
$client = new HttpClient();
11+
12+
$resp = $client->get("https://httpbin.org/ip");
13+
var_dump([
14+
"status" => $resp->status(),
15+
"headers" => $resp->headers(),
16+
"body" => $resp->body(),
17+
]);
18+
19+
try {
20+
$client->get("file:///");
21+
throw new AssertionError("no throw exception");
22+
} catch (HttpClientException $e) {
23+
}

0 commit comments

Comments
 (0)