Skip to content

Commit 4a619e4

Browse files
committed
add model, controllers and handler
1 parent 6cb30a3 commit 4a619e4

File tree

1 file changed

+185
-1
lines changed

1 file changed

+185
-1
lines changed

src/main.rs

+185-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,187 @@
1+
use postgres::{Client, NoTls};
2+
use postgres::Error as PostgresError;
3+
use std::net::{TcpListener, TcpStream};
4+
use std::io::{Read, Write};
5+
use std::env;
6+
7+
#[macro_use]
8+
extern crate serde_derive;
9+
10+
// model
11+
#[derive(Serialize, Deserialize)]
12+
struct User {
13+
id: Option<i32>,
14+
name: String,
15+
email: String,
16+
}
17+
18+
const DB_URL: &str = !env("DATABASE_URL");
19+
const RESPONSE_OK: &str = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
20+
const RESPONSE_NOT_FOUND: &str = "HTTP/1.1 404 NOT FOUND\r\n\r\n";
21+
const RESPONSE_INTERNAL_SERVER_ERROR: &str = "HTTP/1.1 500 INTERNAL SERVER ERROR\r\n\r\n";
22+
123
fn main() {
2-
println!("Hello, world!");
24+
if let Err(e) = set_database() {
25+
println!("Error: {}", e);
26+
return;
27+
}
28+
29+
let listener = TcpListener::bind(format!("0.0.0.0:8080")).unwrap();
30+
println!("Server started at port 8080");
31+
32+
for stream in listener.incoming() {
33+
match stream {
34+
Ok(stream) => {
35+
handle_client(stream);
36+
}
37+
Err(e) => {
38+
println!("Error: {}", e);
39+
}
40+
}
41+
}
42+
}
43+
44+
fn handle_client(mut stream: TcpStream) {
45+
let mut buffer = [0; 1024];
46+
let mut request = String::new();
47+
48+
match stream.read(&mut buffer) {
49+
Ok(size) => {
50+
request.push_str(String::from_utf8_lossy(&buffer[..size]).as_ref());
51+
52+
let (status_line, content) = match &*request {
53+
r if request_with("POST /users") => handle_post_request(r),
54+
r if request_with("GET /users") => handle_get_request(r),
55+
r if request_with("GET /users") => handle_get_all_request(r),
56+
r if request_with("PUT /users") => handle_put_request(r),
57+
r if request_with("DELETE /users") => handle_delete_request(r),
58+
_ => (NOT_FOUND, "Not found".to_string()),
59+
};
60+
61+
stream.write_all(format!("{}{}", status_line, content).as_bytes()).unwrap();
62+
}
63+
Err(e) => {
64+
println!("Error: {}", e);
65+
}
66+
}
67+
}
68+
69+
// controllers
70+
71+
fn handle_post_request(request: &str) -> (String, String) {
72+
match (get_user_request_body(&request), Client::connect(DB_URL, NoTls)) {
73+
(Ok(user), Ok(mut client)) => {
74+
client.execute("INSERT INTO users(name, email) VALUES ($1, $2)",
75+
&[&user.name, &user.email]
76+
).unwrap();
77+
78+
(RESPONSE_OK.to_string(), "User created".to_string())
79+
}
80+
_ => (RESPONSE_INTERNAL_SERVER_ERROR.to_string(), "Error".to_string()),
81+
}
82+
}
83+
84+
fn handle_get_request(request: &str) -> (String, String) {
85+
match (get_id(&request).parse::<i32>(), Client::connect(DB_URL, NoTls)) {
86+
(Ok(id), Ok(mut client)) =>
87+
match client.query_one("SELECT * FROM users WHERE id = $1", &[&id]) {
88+
Ok(row) => {
89+
let user = User {
90+
id: row.get(0),
91+
name: row.get(1),
92+
email: row.get(2),
93+
};
94+
95+
(RESPONSE_OK.to_string(), serde_json::to_string(&user).unwrap())
96+
}
97+
_ => (RESPONSE_NOT_FOUND.to_string(), "User not found".to_string()),
98+
}
99+
100+
_ => (RESPONSE_INTERNAL_SERVER_ERROR.to_string(), "Internal error".to_string()),
101+
}
102+
}
103+
104+
fn handle_get_all_request(_request: &str) -> (String, String) {
105+
match Client::connect(DB_URL, NoTls) {
106+
Ok(mut client) => {
107+
let mut users = Vec::new();
108+
109+
for row in client.query("SELECT id, name, email FROM users", &[]).unwrap() {
110+
users.push(User {
111+
id: row.get(0),
112+
name: row.get(1),
113+
email: row.get(2),
114+
});
115+
}
116+
117+
(RESPONSE_OK.to_string(), serde_json::to_string(&users).unwrap())
118+
}
119+
_ => (RESPONSE_INTERNAL_SERVER_ERROR.to_string(), "Internal error".to_string()),
120+
}
121+
}
122+
123+
fn handle_put_request(request: &str) -> (String, String) {
124+
match
125+
(
126+
get_id(&request).parse::<i32>(),
127+
get_user_request_body(&request),
128+
Client::connect(DB_URL, NoTls),
129+
)
130+
{
131+
(Ok(id), Ok(user), Ok(mut client)) => {
132+
client
133+
.execute(
134+
"UPDATE users SET name = $1, email = $2 WHERE id = $3",
135+
&[&user.name, &user.email, &id]
136+
)
137+
.unwrap();
138+
139+
(RESPONSE_OK.to_string(), "User updated".to_string())
140+
}
141+
_ => (RESPONSE_INTERNAL_SERVER_ERROR.to_string(), "Internal error".to_string()),
142+
}
143+
}
144+
145+
fn handle_delete_request(request: &str) -> (String, String) {
146+
match (get_id(&request).parse::<i32>(), Client::connect(DB_URL, NoTls)) {
147+
(Ok(id), Ok(mut client)) => {
148+
let rows_affected = client.execute("DELETE FROM users WHERE id = $1", &[&id]).unwrap();
149+
150+
if rows_affected == 0 { //if rows affected is 0, user not found
151+
return (RESPONSE_NOT_FOUND.to_string(), "User not found".to_string());
152+
}
153+
154+
(RESPONSE_OK.to_string(), "User deleted".to_string())
155+
}
156+
_ => (RESPONSE_INTERNAL_SERVER_ERROR.to_string(), "Internal error".to_string()),
157+
}
158+
}
159+
160+
// Utility functions
161+
162+
fn set_database() -> Result<(), PostgresError> {
163+
let mut client = Client::connect(DB_URL, NoTls)?;
164+
client.batch_execute(
165+
"
166+
CREATE TABLE IF NOT EXISTS users (
167+
id SERIAL PRIMARY KEY,
168+
name VARCHAR NOT NULL,
169+
email VARCHAR NOT NULL
170+
)
171+
"
172+
)?;
173+
Ok(())
174+
}
175+
176+
fn get_id(request: &str) -> &str {
177+
request.split("/")
178+
.nth(2)
179+
.unwrap_or_default()
180+
.split_whitespace()
181+
.next()
182+
.unwrap_or_default()
183+
}
184+
185+
fn get_user_request_body(request: &str) -> Result<User, serde_json::Error> {
186+
serde_json::from_str(request.split("\r\n\r\n").last().unwrap_or_default())
3187
}

0 commit comments

Comments
 (0)