Skip to content

Commit 1604e90

Browse files
mayankkumar2Nick Vidal
authored andcommitted
fix: url parameters validation
1 parent 871acc7 commit 1604e90

File tree

3 files changed

+160
-80
lines changed

3 files changed

+160
-80
lines changed

Cargo.lock

Lines changed: 76 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ mini_http = {git = "https://github.com/haraldh/mini_http"}
99
httparse = "1"
1010
http = "0.1"
1111
rand = "0.8.5"
12+
url = "2.2.2"

src/main.rs

Lines changed: 83 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ mod game_state;
22

33
use game_state::GameState;
44
use mini_http;
5-
use mini_http::Server;
5+
use mini_http::{Request, Server};
66
use rand::Rng;
7+
use std::collections::HashMap;
78
use std::rc::Rc;
9+
use url::{ParseError, Url};
810

911
// All the web server and network code by Harald H.
1012
// https://github.com/haraldh
@@ -31,40 +33,49 @@ const NOT_FOUND: &str = r#"
3133
</body></html>
3234
"#;
3335

36+
fn get_url(req: &Request) -> Result<Url, ParseError> {
37+
let k = req.headers();
38+
if let Some(base) = k.get("host") {
39+
let base_url: String = base.to_str().unwrap_or("http://localhost:10030").into();
40+
let url = format!("{}{}", base_url, req.uri().to_string());
41+
Url::parse(&*url)
42+
} else {
43+
Err(ParseError::EmptyHost)
44+
}
45+
}
46+
3447
// Single-player mode
3548
//
3649
// Color scheme:
3750
// y (yellow): right letter, wrong position
3851
// g (green): letter at the right position
3952

40-
fn check_single(query: Option<&str>, state: Rc<GameState>) -> Vec<u8> {
53+
fn check_single(req: &Request, state: Rc<GameState>) -> Vec<u8> {
4154
let mut response = vec![b'c'; 5];
55+
let url = get_url(&req);
4256

4357
// Get guess parameter
44-
if query.is_some() {
45-
let the_params = query.unwrap();
46-
let the_params_parts = the_params.split_once("&").unwrap();
47-
let the_guess = the_params_parts.0;
48-
let the_guess_parts = the_guess.split_once("=").unwrap();
49-
let guess = the_guess_parts.1;
50-
//println!("The guess: {}", guess);
51-
52-
let guess_size: usize = guess.len() as usize;
53-
if guess_size == 5 {
54-
for letter_index in 0..guess_size {
55-
if guess.as_bytes()[letter_index] == state.word.as_bytes()[letter_index] {
56-
response[letter_index] = b'g';
57-
} else {
58-
for letter_byte in state.word.as_bytes() {
59-
if guess.as_bytes()[letter_index].eq(letter_byte)
60-
&& response[letter_index] == b'c'
61-
{
62-
response[letter_index] = b'y';
58+
if let Ok(url) = url {
59+
let query: HashMap<String, String> = url.query_pairs().into_owned().collect();
60+
if let Some(guess) = query.get("guess") {
61+
let guess_size: usize = guess.len();
62+
if guess_size == 5 {
63+
for letter_index in 0..guess_size {
64+
if guess.as_bytes()[letter_index] == state.word.as_bytes()[letter_index] {
65+
response[letter_index] = b'g';
66+
} else {
67+
for letter_byte in state.word.as_bytes() {
68+
if guess.as_bytes()[letter_index].eq(letter_byte)
69+
&& response[letter_index] == b'c'
70+
{
71+
response[letter_index] = b'y';
72+
}
6373
}
6474
}
6575
}
6676
}
6777
}
78+
//println!("The guess: {}", guess);
6879
}
6980

7081
return response;
@@ -77,72 +88,64 @@ fn check_single(query: Option<&str>, state: Rc<GameState>) -> Vec<u8> {
7788
// p (purple): word match
7889
// r (red): word was already a match
7990

80-
fn check_multi(query: Option<&str>, state: Rc<GameState>) -> Vec<u8> {
91+
fn check_multi(req: &Request, state: Rc<GameState>) -> Vec<u8> {
8192
let mut response = vec![b'c'; 5];
82-
93+
let url = get_url(&req);
8394
// Get guess and player parameters
84-
if query.is_some() {
85-
let the_params = query.unwrap();
86-
let the_params_parts = the_params.split_once("&").unwrap();
87-
let the_guess = the_params_parts.0;
88-
let the_player = the_params_parts.1;
89-
let the_guess_parts = the_guess.split_once("=").unwrap();
90-
let guess = the_guess_parts.1;
91-
//println!("The guess: {}", guess);
92-
let the_player_parts = the_player.split_once("=").unwrap();
93-
let player = the_player_parts.1;
94-
//println!("The player: {}", player);
95-
96-
// Wrong word size
97-
let word_size: usize = guess.len() as usize;
98-
if word_size != 5 {
99-
return response;
100-
}
101-
102-
// Check if this word was already a match
103-
let matches_index = state.matches.borrow().iter().position(|x| x == guess);
104-
if matches_index.is_some() {
105-
response = vec![b'r'; 5];
106-
return response;
107-
}
108-
109-
// Check letters
110-
for letter_index in 0..word_size {
111-
let letter_char = guess.as_bytes()[letter_index] as char;
112-
let found_char = state.letters.borrow()[letter_index]
113-
.chars()
114-
.any(|ch| ch == letter_char);
115-
if found_char {
116-
response[letter_index] = b'b';
117-
} else {
118-
state.letters.borrow_mut()[letter_index].push_str(&letter_char.to_string());
95+
if let Ok(url) = url {
96+
let query: HashMap<String, String> = url.query_pairs().into_owned().collect();
97+
if let (Some(guess), Some(player)) = (query.get("guess"), query.get("player")) {
98+
// Wrong word size
99+
let word_size: usize = guess.len() as usize;
100+
if word_size != 5 {
101+
return response;
119102
}
120-
}
121103

122-
// Check if this word is a new match
123-
let guesses_index = state.guesses.borrow().iter().position(|x| x == guess);
124-
if guesses_index.is_some() {
125-
// Check if it matches a previous guess from the player
126-
let winner = &state.players.borrow()[guesses_index.unwrap()];
127-
if winner == player {
104+
// Check if this word was already a match
105+
let matches_index = state.matches.borrow().iter().position(|x| x == guess);
106+
if matches_index.is_some() {
128107
response = vec![b'r'; 5];
129108
return response;
130109
}
131110

132-
// Push word to matches
133-
state.matches.borrow_mut().push(guess.to_string());
134-
response = vec![b'p'; 5];
135-
//println!("New match: {}", guess.to_string());
111+
// Check letters
112+
for letter_index in 0..word_size {
113+
let letter_char = guess.as_bytes()[letter_index] as char;
114+
let found_char = state.letters.borrow()[letter_index]
115+
.chars()
116+
.any(|ch| ch == letter_char);
117+
if found_char {
118+
response[letter_index] = b'b';
119+
} else {
120+
state.letters.borrow_mut()[letter_index].push_str(&letter_char.to_string());
121+
}
122+
}
123+
124+
// Check if this word is a new match
125+
let guesses_index = state.guesses.borrow().iter().position(|x| x == guess);
126+
if guesses_index.is_some() {
127+
// Check if it matches a previous guess from the player
128+
let winner = &state.players.borrow()[guesses_index.unwrap()];
129+
if winner == player {
130+
response = vec![b'r'; 5];
131+
return response;
132+
}
136133

137-
// Push winners
138-
state.winners.borrow_mut().push(player.to_string());
139-
state.winners.borrow_mut().push(winner.to_string());
140-
//println!("Winners: {}, {}", player.to_string(), winner.to_string());
141-
} else {
142-
// Push new word to guesses
143-
state.guesses.borrow_mut().push(guess.to_string());
144-
state.players.borrow_mut().push(player.to_string());
145-
//println!("New word: {}", guess.to_string());
134+
// Push word to matches
135+
state.matches.borrow_mut().push(guess.to_string());
136+
response = vec![b'p'; 5];
137+
//println!("New match: {}", guess.to_string());
138+
139+
// Push winners
140+
state.winners.borrow_mut().push(player.to_string());
141+
state.winners.borrow_mut().push(winner.to_string());
142+
//println!("Winners: {}, {}", player.to_string(), winner.to_string());
143+
} else {
144+
// Push new word to guesses
145+
state.guesses.borrow_mut().push(guess.to_string());
146+
state.players.borrow_mut().push(player.to_string());
147+
//println!("New word: {}", guess.to_string());
148+
}
146149
}
147150
}
148151

@@ -230,12 +233,12 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
230233
"/single" => mini_http::Response::builder()
231234
.status(200)
232235
.header("Content-Type", "text/plain")
233-
.body(check_single(req.uri().query(), state.clone()))
236+
.body(check_single(&req, state.clone()))
234237
.unwrap(),
235238
"/multi" => mini_http::Response::builder()
236239
.status(200)
237240
.header("Content-Type", "text/plain")
238-
.body(check_multi(req.uri().query(), state.clone()))
241+
.body(check_multi(&req, state.clone()))
239242
.unwrap(),
240243
"/winners" => mini_http::Response::builder()
241244
.status(200)

0 commit comments

Comments
 (0)