Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dapr = { path = "../dapr" }
dapr-macros = { path = "../dapr-macros" }
env_logger = "0.11"
log = "0.4"
reqwest = { version = "0.12", default-features = false }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
tokio = { workspace = true, features = ["full"] }
Expand Down Expand Up @@ -74,8 +75,17 @@ path = "src/invoke/grpc-proxying/client.rs"
name = "invoke-grpc-proxying-server"
path = "src/invoke/grpc-proxying/server.rs"

[[example]]
name = "invoke-http-client"
path = "src/invoke/http/client.rs"

[[example]]
name = "invoke-http-server"
path = "src/invoke/http/server.rs"

[[example]]
name = "jobs"

path = "src/jobs/jobs.rs"

[[example]]
Expand Down
15 changes: 15 additions & 0 deletions examples/src/invoke/http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Invoke HTTP Example

This example demonstrates how to use the Dapr HTTP proxying feature to proxy HTTP requests sent via the Rust SDK (using `reqwest`) through Dapr to reach another application.

1. Build the examples:
```bash
cargo build --examples
```

2. Run with Dapr in the example/invoke/http directory:
```bash
dapr run -f .
```

If everything worked, you should see the `invoke-http-client` successfully sending an HTTP request via the Dapr sidecar to the `invoke-http-server`, with `"Hello, test! (from HTTP server)"` printed to the stdout.
53 changes: 53 additions & 0 deletions examples/src/invoke/http/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tokio::time::sleep(Duration::from_secs(5)).await;

let address = "https://127.0.0.1".to_string();

let client_result = dapr::Client::<dapr::client::TonicClient>::connect(address).await;

let value = "test";
let method_to_call = format!("hello/{}", value);

match client_result {
Ok(mut _client) => {
let http_client = reqwest::Client::builder()
.timeout(Duration::from_secs(2))
.build()
.unwrap();

let target_app_id = "invoke-http-server";
let dapr_http_port: u16 = std::env::var("DAPR_HTTP_PORT")
.unwrap_or_else(|_| "3500".to_string())
.parse()?;

let url = format!("http://127.0.0.1:{}/{}", dapr_http_port, method_to_call);
let req = http_client.post(url).header("dapr-app-id", target_app_id);

let response_result = req.send().await;
match response_result {
Ok(response) => {
let body_result = response.text().await;
match body_result {
Ok(body) => {
println!("Response: {:?}", body);
}
Err(e) => {
eprintln!("Error 1: {}", e);
}
}
}
Err(e) => {
eprintln!("Error 2: {}", e);
}
}
}
Err(e) => {
eprintln!("Dapr client error: {}", e);
}
}

Ok(())
}
15 changes: 15 additions & 0 deletions examples/src/invoke/http/dapr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: 1
common:
daprdLogDestination: console
apps:
- appID: invoke-http-server
appDirPath: ./
appProtocol: http
appPort: 8080
logLevel: debug
command: ["cargo", "run", "--example", "invoke-http-server"]
- appID: invoke-http-client
appDirPath: ./
appProtocol: http
logLevel: debug
command: ["cargo", "run", "--example", "invoke-http-client"]
43 changes: 43 additions & 0 deletions examples/src/invoke/http/server.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "127.0.0.1:8080";
let listener = TcpListener::bind(&addr).await?;
println!("Server running on {}", addr);

loop {
let (mut stream, _) = listener.accept().await?;

tokio::spawn(async move {
let mut buf = [0; 1024];
if let Ok(n) = stream.read(&mut buf).await {
if n > 0 {
let request_str = String::from_utf8_lossy(&buf[..n]);

if let Some(line) = request_str.lines().next() {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 2 {
let path = parts[1];

if let Some(value) = path.strip_prefix("/hello/") {
let body = format!("Hello, {}! (from HTTP server)", value);
let response = format!(
"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: {}\r\n\r\n{}",
body.len(),
body
);
let _ = stream.write_all(response.as_bytes()).await;
return;
}
}
}

let response = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
let _ = stream.write_all(response.as_bytes()).await;
}
}
});
}
}