Skip to content
This repository was archived by the owner on Dec 15, 2025. It is now read-only.

Commit c86e96a

Browse files
committed
separated the http proxy and zinit itself. 2 separate binaries now
1 parent 962d83d commit c86e96a

File tree

7 files changed

+471
-181
lines changed

7 files changed

+471
-181
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,7 @@ path = "src/main.rs"
3737
[[bin]]
3838
name = "testapp"
3939
path = "src/bin/testapp.rs"
40+
[[bin]]
41+
name = "zinit-http"
42+
path = "src/bin/zinit-http.rs"
4043

README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,61 @@
1+
# Zinit - A Process Manager
2+
3+
Zinit is a process manager designed to manage services and their lifecycle. It provides both a Unix socket interface and an HTTP API for interacting with the process manager.
4+
5+
## Components
6+
7+
Zinit now consists of two separate binaries:
8+
9+
1. **zinit** - The core process manager that handles service lifecycle management
10+
2. **zinit-http** - An HTTP proxy that forwards JSON-RPC requests to the Zinit Unix socket
11+
12+
This separation allows for more flexibility and reduced resource usage when the HTTP API is not needed.
13+
14+
## Usage
15+
16+
### Process Manager (zinit)
17+
18+
```bash
19+
# Run zinit in init mode
20+
zinit init --config /etc/zinit/ --socket /var/run/zinit.sock
21+
22+
# List services
23+
zinit list
24+
25+
# Start a service
26+
zinit start <service-name>
27+
28+
# Stop a service
29+
zinit stop <service-name>
30+
```
31+
32+
### HTTP Proxy (zinit-http)
33+
34+
```bash
35+
# Start the HTTP proxy on the default port (8080)
36+
zinit-http --socket /var/run/zinit.sock
37+
38+
# Start the HTTP proxy on a custom port
39+
zinit-http --socket /var/run/zinit.sock --port 3000
40+
```
41+
42+
## JSON-RPC API
43+
44+
The HTTP proxy provides a JSON-RPC 2.0 API for interacting with Zinit. You can send JSON-RPC requests to the HTTP endpoint:
45+
46+
```bash
47+
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"service.list","params":{}}' http://localhost:8080/
48+
```
49+
50+
## Building from Source
51+
52+
```bash
53+
# Build both binaries
54+
cargo build --release
55+
56+
# The binaries will be available in target/release/
57+
```
58+
159
# Zinit [![Rust](https://github.com/threefoldtech/zinit/actions/workflows/rust.yml/badge.svg)](https://github.com/threefoldtech/zinit/actions/workflows/rust.yml)
260

361
A lightweight PID 1 replacement inspired by runit, written in Rust using Tokio for async I/O.

docker/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ FROM ubuntu:18.04
22

33
RUN mkdir -p /etc/zinit
44
ADD zinit /sbin/zinit
5+
ADD zinit-http /sbin/zinit-http
56

67
ENTRYPOINT ["/sbin/zinit", "init"]

src/app/api.rs

Lines changed: 5 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -96,185 +96,22 @@ pub struct Status {
9696
pub struct Api {
9797
zinit: ZInit,
9898
socket: PathBuf,
99-
http_port: Option<u16>,
99+
// http_port removed as it's now in a separate binary
100100
}
101101

102102
impl Api {
103-
pub fn new<P: AsRef<Path>>(zinit: ZInit, socket: P, http_port: Option<u16>) -> Api {
103+
pub fn new<P: AsRef<Path>>(zinit: ZInit, socket: P, _http_port: Option<u16>) -> Api {
104+
// _http_port parameter kept for backward compatibility but not used
104105
Api {
105106
zinit,
106107
socket: socket.as_ref().to_path_buf(),
107-
http_port,
108108
}
109109
}
110110

111-
// Serve HTTP proxy for JSON-RPC API
112-
async fn serve_http(port: u16, zinit: ZInit) -> Result<()> {
113-
// Handle JSON-RPC requests
114-
async fn handle_json_rpc(
115-
body: Bytes,
116-
zinit: ZInit,
117-
) -> Result<Response, (StatusCode, String)> {
118-
// Process the JSON-RPC request
119-
let request: JsonRpcRequest = serde_json::from_slice(&body).map_err(|e| {
120-
(
121-
StatusCode::BAD_REQUEST,
122-
format!("Invalid JSON-RPC request: {}", e),
123-
)
124-
})?;
125-
126-
// We can't use Api::process_jsonrpc directly from an inner function
127-
// So we'll manually create a JsonRpcResponse
128-
let id = request.id.unwrap_or(Value::Null);
129-
let method = request.method.clone();
130-
let params = request.params.clone();
131-
132-
// Serialize the request parameters for the Unix socket
133-
let response_bytes = match method.as_str() {
134-
"rpc.discover" => {
135-
// For discover, we can directly return the OpenRPC spec
136-
let spec: Value = match serde_json::from_str(OPENRPC_SPEC) {
137-
Ok(value) => value,
138-
Err(err) => {
139-
return Err((
140-
StatusCode::INTERNAL_SERVER_ERROR,
141-
format!("Failed to parse OpenRPC spec: {}", err),
142-
));
143-
}
144-
};
145-
146-
let response = JsonRpcResponse {
147-
jsonrpc: "2.0".to_string(),
148-
id,
149-
result: Some(spec),
150-
error: None,
151-
};
152-
153-
serde_json::to_vec(&response).map_err(|e| {
154-
(
155-
StatusCode::INTERNAL_SERVER_ERROR,
156-
format!("Failed to serialize response: {}", e),
157-
)
158-
})?
159-
}
160-
_ => {
161-
// For other methods, create a new JSON-RPC request to send to the Unix socket
162-
let unix_request = JsonRpcRequest {
163-
jsonrpc: "2.0".to_string(),
164-
id: Some(id.clone()),
165-
method,
166-
params,
167-
};
168-
169-
// Serialize the request
170-
let request_bytes = serde_json::to_vec(&unix_request).map_err(|e| {
171-
(
172-
StatusCode::INTERNAL_SERVER_ERROR,
173-
format!("Failed to serialize request: {}", e),
174-
)
175-
})?;
176-
177-
// Create a Unix socket connection
178-
let mut socket =
179-
UnixStream::connect("/var/run/zinit.sock")
180-
.await
181-
.map_err(|e| {
182-
(
183-
StatusCode::INTERNAL_SERVER_ERROR,
184-
format!("Failed to connect to Zinit socket: {}", e),
185-
)
186-
})?;
187-
188-
// Send the request
189-
socket.write_all(&request_bytes).await.map_err(|e| {
190-
(
191-
StatusCode::INTERNAL_SERVER_ERROR,
192-
format!("Failed to write to Zinit socket: {}", e),
193-
)
194-
})?;
195-
196-
socket.write_all(b"\n").await.map_err(|e| {
197-
(
198-
StatusCode::INTERNAL_SERVER_ERROR,
199-
format!("Failed to write newline to Zinit socket: {}", e),
200-
)
201-
})?;
202-
203-
// Read the response
204-
let mut response_data = Vec::new();
205-
socket.read_to_end(&mut response_data).await.map_err(|e| {
206-
(
207-
StatusCode::INTERNAL_SERVER_ERROR,
208-
format!("Failed to read from Zinit socket: {}", e),
209-
)
210-
})?;
211-
212-
response_data
213-
}
214-
};
215-
216-
// Create response with CORS headers
217-
let mut headers = HeaderMap::new();
218-
headers.insert("Content-Type", "application/json".parse().unwrap());
219-
headers.insert("Access-Control-Allow-Origin", "*".parse().unwrap());
220-
headers.insert(
221-
"Access-Control-Allow-Methods",
222-
"POST, OPTIONS".parse().unwrap(),
223-
);
224-
headers.insert(
225-
"Access-Control-Allow-Headers",
226-
"Content-Type".parse().unwrap(),
227-
);
228-
229-
// Return the response
230-
Ok((headers, Bytes::from(response_bytes)).into_response())
231-
}
232-
233-
// Handle OPTIONS requests for CORS
234-
async fn handle_cors() -> Response {
235-
// Create response with CORS headers
236-
let mut headers = HeaderMap::new();
237-
headers.insert("Access-Control-Allow-Origin", "*".parse().unwrap());
238-
headers.insert(
239-
"Access-Control-Allow-Methods",
240-
"POST, OPTIONS".parse().unwrap(),
241-
);
242-
headers.insert(
243-
"Access-Control-Allow-Headers",
244-
"Content-Type".parse().unwrap(),
245-
);
246-
247-
(headers, "").into_response()
248-
}
249-
250-
// Build the router
251-
let app = Router::new()
252-
.route(
253-
"/",
254-
post(move |body: Bytes| handle_json_rpc(body, zinit.clone())),
255-
)
256-
.route("/", options(handle_cors));
257-
258-
// Run the server
259-
let addr = SocketAddr::from(([0, 0, 0, 0], port));
260-
info!("Zinit HTTP proxy listening on http://{}", addr);
261-
262-
let listener = TcpListener::bind(addr).await?;
263-
axum::serve(listener, app).await?;
264-
265-
Ok(())
266-
}
111+
// HTTP proxy functionality has been moved to a separate binary (zinit-http)
267112

268113
pub async fn serve(&self) -> Result<()> {
269-
// Start HTTP proxy server if http_port is provided
270-
if let Some(port) = self.http_port {
271-
let zinit_clone = self.zinit.clone();
272-
tokio::spawn(async move {
273-
if let Err(e) = Self::serve_http(port, zinit_clone).await {
274-
error!("HTTP proxy server error: {}", e);
275-
}
276-
});
277-
}
114+
// HTTP proxy functionality has been moved to a separate binary (zinit-http)
278115

279116
// Start Unix socket server
280117
let listener = UnixListener::bind(&self.socket).context("failed to listen for socket")?;

src/app/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ pub async fn init(
4747
socket: &str,
4848
container: bool,
4949
debug: bool,
50-
http_port: Option<u16>,
5150
) -> Result<()> {
5251
//std::fs::create_dir_all(config)?;
5352
if let Err(err) = logger(if debug {
@@ -87,7 +86,7 @@ pub async fn init(
8786
error!("failed to monitor service {}: {}", k, err);
8887
};
8988
}
90-
let a = api::Api::new(init, socket, http_port);
89+
let a = api::Api::new(init, socket, None); // HTTP proxy is now a separate binary
9190
a.serve().await?;
9291
Ok(())
9392
}

0 commit comments

Comments
 (0)