forked from M-Labs/ionpak-thermostat
implement support for HTTP GET arguments
This commit is contained in:
parent
e8174f0773
commit
1a06b524d2
@ -1,6 +1,6 @@
|
||||
use core::fmt;
|
||||
|
||||
const MAX_PATH: usize = 128;
|
||||
const MAX_QUERY: usize = 128;
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Eq)]
|
||||
enum State {
|
||||
@ -8,7 +8,7 @@ enum State {
|
||||
WaitE,
|
||||
WaitT,
|
||||
WaitSpace,
|
||||
GetPath,
|
||||
GetQuery,
|
||||
WaitCR1,
|
||||
WaitLF1,
|
||||
WaitCR2,
|
||||
@ -18,22 +18,22 @@ enum State {
|
||||
|
||||
pub struct Request {
|
||||
state: State,
|
||||
path_idx: usize,
|
||||
path: [u8; MAX_PATH]
|
||||
query_idx: usize,
|
||||
query: [u8; MAX_QUERY]
|
||||
}
|
||||
|
||||
impl Request {
|
||||
pub fn new() -> Request {
|
||||
Request {
|
||||
state: State::WaitG,
|
||||
path_idx: 0,
|
||||
path: [0; MAX_PATH]
|
||||
query_idx: 0,
|
||||
query: [0; MAX_QUERY]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.state = State::WaitG;
|
||||
self.path_idx = 0;
|
||||
self.query_idx = 0;
|
||||
}
|
||||
|
||||
pub fn input_char(&mut self, c: u8) -> Result<bool, &'static str> {
|
||||
@ -61,26 +61,26 @@ impl Request {
|
||||
}
|
||||
State::WaitSpace => {
|
||||
if c == b' ' {
|
||||
self.state = State::GetPath;
|
||||
self.state = State::GetQuery;
|
||||
} else {
|
||||
return Err("invalid character in method")
|
||||
}
|
||||
}
|
||||
State::GetPath => {
|
||||
State::GetQuery => {
|
||||
if c == b'\r' || c == b'\n' {
|
||||
return Err("GET ended prematurely")
|
||||
} else if c == b' ' {
|
||||
if self.path_idx == 0 {
|
||||
return Err("path is empty")
|
||||
if self.query_idx == 0 {
|
||||
return Err("query is empty")
|
||||
} else {
|
||||
self.state = State::WaitCR1;
|
||||
}
|
||||
} else {
|
||||
if self.path_idx >= self.path.len() {
|
||||
return Err("path is too long")
|
||||
if self.query_idx >= self.query.len() {
|
||||
return Err("query is too long")
|
||||
} else {
|
||||
self.path[self.path_idx] = c;
|
||||
self.path_idx += 1;
|
||||
self.query[self.query_idx] = c;
|
||||
self.query_idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -127,14 +127,42 @@ impl Request {
|
||||
result
|
||||
}
|
||||
|
||||
pub fn get_path<'a>(&'a self) -> Result<&'a [u8], &'static str> {
|
||||
pub fn get_query<'a>(&'a self) -> Result<&'a [u8], &'static str> {
|
||||
if self.state != State::Finished {
|
||||
return Err("request is not finished")
|
||||
}
|
||||
Ok(&self.path[..self.path_idx])
|
||||
Ok(&self.query[..self.query_idx])
|
||||
}
|
||||
|
||||
pub fn get_path<'a>(&'a self) -> Result<&'a [u8], &'static str> {
|
||||
let query = self.get_query()?;
|
||||
Ok(query.split(|b| *b == '?' as u8).next().unwrap())
|
||||
}
|
||||
|
||||
// FIXME: this yields some empty strings
|
||||
pub fn iter_args<'a>(&'a self) -> Result<impl Iterator<Item=(&'a [u8], &'a [u8])>, &'static str> {
|
||||
let query = self.get_query()?;
|
||||
let mut qs = query.split(|b| *b == '?' as u8);
|
||||
qs.next();
|
||||
let args = qs.next().unwrap_or(b"");
|
||||
let args_it = args.split(|b| *b == '&' as u8);
|
||||
Ok(args_it.map(|arg| {
|
||||
let mut eqs = arg.split(|b| *b == '=' as u8);
|
||||
(eqs.next().unwrap(), eqs.next().unwrap_or(b""))
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn get_arg<'a>(&'a self, name: &[u8]) -> Result<&'a [u8], &'static str> {
|
||||
for (current_name, current_value) in self.iter_args()? {
|
||||
if current_name == name {
|
||||
return Ok(current_value)
|
||||
}
|
||||
}
|
||||
Err("argument not found")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn write_reply_header(output: &mut fmt::Write, status: u16, content_type: &str, gzip: bool) -> fmt::Result {
|
||||
let status_text = match status {
|
||||
200 => "OK",
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(used, const_fn, core_float, asm, lang_items)]
|
||||
#![feature(used, const_fn, core_float, asm, lang_items, conservative_impl_trait)]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m;
|
||||
|
Loading…
Reference in New Issue
Block a user