Run rustfmt
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
use super::StatusClass::*;
|
|
||||||
use super::StatusClass;
|
use super::StatusClass;
|
||||||
|
use super::StatusClass::*;
|
||||||
|
|
||||||
pub static HTTP_STATUSES: [(u16, StatusClass, &str, &str); 41] = [
|
pub static HTTP_STATUSES: [(u16, StatusClass, &str, &str); 41] = [
|
||||||
(100, Informational, "Continue",
|
(100, Informational, "Continue",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use json;
|
|
||||||
use chrono;
|
|
||||||
use crate::usimp;
|
|
||||||
use super::Method;
|
use super::Method;
|
||||||
|
use crate::usimp;
|
||||||
|
use chrono;
|
||||||
|
use json;
|
||||||
|
|
||||||
pub struct HttpStream {
|
pub struct HttpStream {
|
||||||
stream: super::Stream,
|
stream: super::Stream,
|
||||||
@ -30,7 +30,13 @@ pub fn connection_handler(client: super::Stream) {
|
|||||||
fn request_handler(client: &mut super::HttpStream) {
|
fn request_handler(client: &mut super::HttpStream) {
|
||||||
let mut res = super::Response::new();
|
let mut res = super::Response::new();
|
||||||
res.add_header("Server", "Locutus");
|
res.add_header("Server", "Locutus");
|
||||||
res.add_header("Date", chrono::Utc::now().format("%a, %d %b %Y %H:%M:%S GMT").to_string().as_str());
|
res.add_header(
|
||||||
|
"Date",
|
||||||
|
chrono::Utc::now()
|
||||||
|
.format("%a, %d %b %Y %H:%M:%S GMT")
|
||||||
|
.to_string()
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
|
|
||||||
let req = super::parser::parse_request(&mut client.stream).unwrap();
|
let req = super::parser::parse_request(&mut client.stream).unwrap();
|
||||||
println!("{} {}", req.method, req.uri);
|
println!("{} {}", req.method, req.uri);
|
||||||
@ -53,14 +59,12 @@ fn request_handler(client: &mut super::HttpStream) {
|
|||||||
let parts: Vec<&str> = req.uri.split('/').collect();
|
let parts: Vec<&str> = req.uri.split('/').collect();
|
||||||
match parts[2..] {
|
match parts[2..] {
|
||||||
["entity", entity] => res.status(501),
|
["entity", entity] => res.status(501),
|
||||||
[func] => {
|
[func] => match usimp::is_valid(func) {
|
||||||
match usimp::is_valid(func) {
|
|
||||||
true => match req.method {
|
true => match req.method {
|
||||||
Method::POST => res.status(200),
|
Method::POST => res.status(200),
|
||||||
_ => res.status(405),
|
_ => res.status(405),
|
||||||
},
|
},
|
||||||
false => res.status(400),
|
false => res.status(400),
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_ => res.status(400),
|
_ => res.status(400),
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
mod consts;
|
mod consts;
|
||||||
mod parser;
|
|
||||||
mod handler;
|
mod handler;
|
||||||
|
mod parser;
|
||||||
|
|
||||||
use std::net::TcpStream;
|
|
||||||
use openssl::ssl::SslStream;
|
use openssl::ssl::SslStream;
|
||||||
use std::io::{Write, Read};
|
|
||||||
use std::fmt::Formatter;
|
use std::fmt::Formatter;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::net::TcpStream;
|
||||||
|
|
||||||
pub use handler::*;
|
pub use handler::*;
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ impl StatusClass {
|
|||||||
300..=399 => StatusClass::Redirection,
|
300..=399 => StatusClass::Redirection,
|
||||||
400..=499 => StatusClass::ClientError,
|
400..=499 => StatusClass::ClientError,
|
||||||
500..=599 => StatusClass::ServerError,
|
500..=599 => StatusClass::ServerError,
|
||||||
_ => panic!("invalid status code")
|
_ => panic!("invalid status code"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,7 +106,7 @@ impl Status {
|
|||||||
code: status_code,
|
code: status_code,
|
||||||
message: msg.to_string(),
|
message: msg.to_string(),
|
||||||
class: class.clone(),
|
class: class.clone(),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic!("invalid status code");
|
panic!("invalid status code");
|
||||||
@ -124,7 +124,6 @@ impl Status {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct HeaderField {
|
pub struct HeaderField {
|
||||||
name: String,
|
name: String,
|
||||||
value: String,
|
value: String,
|
||||||
@ -140,13 +139,13 @@ pub struct Request {
|
|||||||
version: String,
|
version: String,
|
||||||
method: Method,
|
method: Method,
|
||||||
uri: String,
|
uri: String,
|
||||||
header_fields: Vec<HeaderField>
|
header_fields: Vec<HeaderField>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
version: String,
|
version: String,
|
||||||
status: Status,
|
status: Status,
|
||||||
header_fields: Vec<HeaderField>
|
header_fields: Vec<HeaderField>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
@ -170,7 +169,10 @@ impl Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn send(&self, stream: &mut Stream) -> Result<(), std::io::Error> {
|
fn send(&self, stream: &mut Stream) -> Result<(), std::io::Error> {
|
||||||
let mut header = format!("HTTP/{} {:03} {}\r\n", self.version, self.status.code, self.status.message);
|
let mut header = format!(
|
||||||
|
"HTTP/{} {:03} {}\r\n",
|
||||||
|
self.version, self.status.code, self.status.message
|
||||||
|
);
|
||||||
for header_field in &self.header_fields {
|
for header_field in &self.header_fields {
|
||||||
header.push_str(format!("{}: {}\r\n", header_field.name, header_field.value).as_str());
|
header.push_str(format!("{}: {}\r\n", header_field.name, header_field.value).as_str());
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ pub fn parse_request(stream: &mut http::Stream) -> Result<http::Request, String>
|
|||||||
let mut parser = Parser::new_request_parser(&buf[..size]);
|
let mut parser = Parser::new_request_parser(&buf[..size]);
|
||||||
let header_size = parser.parse().unwrap();
|
let header_size = parser.parse().unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mut header_fields = Vec::new();
|
let mut header_fields = Vec::new();
|
||||||
for (name, value) in parser.headers {
|
for (name, value) in parser.headers {
|
||||||
header_fields.push(http::HeaderField {
|
header_fields.push(http::HeaderField {
|
||||||
@ -126,8 +124,13 @@ impl Parser<'_> {
|
|||||||
self.next(*char);
|
self.next(*char);
|
||||||
match self.state {
|
match self.state {
|
||||||
State::Finish => return Ok(self.header_size),
|
State::Finish => return Ok(self.header_size),
|
||||||
State::Error => return Err(format!("invalid character at position {}", self.header_size - 1)),
|
State::Error => {
|
||||||
_ => {},
|
return Err(format!(
|
||||||
|
"invalid character at position {}",
|
||||||
|
self.header_size - 1
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(String::from("input too short"));
|
return Err(String::from("input too short"));
|
||||||
@ -135,36 +138,30 @@ impl Parser<'_> {
|
|||||||
|
|
||||||
fn next(&mut self, char: u8) {
|
fn next(&mut self, char: u8) {
|
||||||
self.header_size += 1;
|
self.header_size += 1;
|
||||||
let get_str = || {
|
let get_str =
|
||||||
std::str::from_utf8(&self.buf[self.str_start..self.header_size - 1]).unwrap()
|
|| std::str::from_utf8(&self.buf[self.str_start..self.header_size - 1]).unwrap();
|
||||||
};
|
|
||||||
self.state = match &self.state {
|
self.state = match &self.state {
|
||||||
State::Error => State::Error,
|
State::Error => State::Error,
|
||||||
State::Finish => State::Error,
|
State::Finish => State::Error,
|
||||||
State::Method => {
|
State::Method => match char {
|
||||||
match char {
|
|
||||||
0x41..=0x5A => State::Method,
|
0x41..=0x5A => State::Method,
|
||||||
0x20 => {
|
0x20 => {
|
||||||
self.method = Some(get_str());
|
self.method = Some(get_str());
|
||||||
self.str_start = self.header_size;
|
self.str_start = self.header_size;
|
||||||
State::Uri
|
State::Uri
|
||||||
},
|
|
||||||
_ => State::Error,
|
|
||||||
}
|
}
|
||||||
|
_ => State::Error,
|
||||||
},
|
},
|
||||||
State::Uri => {
|
State::Uri => match char {
|
||||||
match char {
|
|
||||||
0x21..=0x7E => State::Uri,
|
0x21..=0x7E => State::Uri,
|
||||||
0x20 => {
|
0x20 => {
|
||||||
self.uri = Some(get_str());
|
self.uri = Some(get_str());
|
||||||
self.str_start = self.header_size;
|
self.str_start = self.header_size;
|
||||||
State::Http(&State::HeaderName)
|
State::Http(&State::HeaderName)
|
||||||
},
|
|
||||||
_ => State::Error,
|
|
||||||
}
|
}
|
||||||
|
_ => State::Error,
|
||||||
},
|
},
|
||||||
State::Http(next) => {
|
State::Http(next) => match char {
|
||||||
match char {
|
|
||||||
0x48 | 0x54 | 0x50 => State::Http(next),
|
0x48 | 0x54 | 0x50 => State::Http(next),
|
||||||
0x2F => {
|
0x2F => {
|
||||||
let http = get_str();
|
let http = get_str();
|
||||||
@ -174,95 +171,87 @@ impl Parser<'_> {
|
|||||||
} else {
|
} else {
|
||||||
State::HttpVersion(next)
|
State::HttpVersion(next)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
_ => State::Error,
|
|
||||||
}
|
}
|
||||||
|
_ => State::Error,
|
||||||
},
|
},
|
||||||
State::HttpVersion(next) => {
|
State::HttpVersion(next) => match char {
|
||||||
match char {
|
|
||||||
0x30..=0x39 | 0x2E => State::HttpVersion(next),
|
0x30..=0x39 | 0x2E => State::HttpVersion(next),
|
||||||
0x0D => {
|
0x0D => match next {
|
||||||
match next {
|
|
||||||
State::HeaderName => {
|
State::HeaderName => {
|
||||||
self.http_version = Some(get_str());
|
self.http_version = Some(get_str());
|
||||||
State::CRLF(next)
|
State::CRLF(next)
|
||||||
},
|
|
||||||
_ => State::Error,
|
|
||||||
}
|
}
|
||||||
|
_ => State::Error,
|
||||||
},
|
},
|
||||||
0x20 => {
|
0x20 => match next {
|
||||||
match next {
|
|
||||||
State::StatusCode => {
|
State::StatusCode => {
|
||||||
self.http_version = Some(get_str());
|
self.http_version = Some(get_str());
|
||||||
self.str_start = self.header_size;
|
self.str_start = self.header_size;
|
||||||
State::StatusCode
|
State::StatusCode
|
||||||
},
|
|
||||||
_ => State::Error,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => State::Error,
|
_ => State::Error,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
State::StatusCode => {
|
_ => State::Error,
|
||||||
match char {
|
},
|
||||||
|
State::StatusCode => match char {
|
||||||
0x30..=0x39 => State::StatusCode,
|
0x30..=0x39 => State::StatusCode,
|
||||||
0x20 => {
|
0x20 => {
|
||||||
self.status_code = Some(get_str());
|
self.status_code = Some(get_str());
|
||||||
self.str_start = self.header_size;
|
self.str_start = self.header_size;
|
||||||
State::StatusMessage
|
State::StatusMessage
|
||||||
},
|
|
||||||
_ => State::Error,
|
|
||||||
}
|
}
|
||||||
|
_ => State::Error,
|
||||||
},
|
},
|
||||||
State::StatusMessage => {
|
State::StatusMessage => match char {
|
||||||
match char {
|
|
||||||
0x20..=0x7E => State::StatusMessage,
|
0x20..=0x7E => State::StatusMessage,
|
||||||
0x0D => {
|
0x0D => {
|
||||||
self.status_message = Some(get_str());
|
self.status_message = Some(get_str());
|
||||||
State::CRLF(&State::HeaderName)
|
State::CRLF(&State::HeaderName)
|
||||||
},
|
|
||||||
_ => State::Error,
|
|
||||||
}
|
}
|
||||||
|
_ => State::Error,
|
||||||
},
|
},
|
||||||
State::HeaderName => {
|
State::HeaderName => match char {
|
||||||
match char {
|
|
||||||
0x0D => {
|
0x0D => {
|
||||||
if self.header_size == self.str_start + 1 {
|
if self.header_size == self.str_start + 1 {
|
||||||
State::CRLF(&State::Finish)
|
State::CRLF(&State::Finish)
|
||||||
} else {
|
} else {
|
||||||
State::Error
|
State::Error
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
0x3A => {
|
0x3A => {
|
||||||
let header_name = get_str();
|
let header_name = get_str();
|
||||||
self.headers.push((header_name, ""));
|
self.headers.push((header_name, ""));
|
||||||
self.str_start = self.header_size;
|
self.str_start = self.header_size;
|
||||||
State::HeaderValue
|
State::HeaderValue
|
||||||
},
|
|
||||||
0x00..=0x1F | 0x7F | 0x80..=0xFF |
|
|
||||||
0x20 | 0x28 | 0x29 | 0x2C | 0x2F |
|
|
||||||
0x3A..=0x40 | 0x5B..=0x5D | 0x7B | 0x7D => State::Error,
|
|
||||||
_ => State::HeaderName,
|
|
||||||
}
|
}
|
||||||
|
0x00..=0x1F
|
||||||
|
| 0x7F
|
||||||
|
| 0x80..=0xFF
|
||||||
|
| 0x20
|
||||||
|
| 0x28
|
||||||
|
| 0x29
|
||||||
|
| 0x2C
|
||||||
|
| 0x2F
|
||||||
|
| 0x3A..=0x40
|
||||||
|
| 0x5B..=0x5D
|
||||||
|
| 0x7B
|
||||||
|
| 0x7D => State::Error,
|
||||||
|
_ => State::HeaderName,
|
||||||
},
|
},
|
||||||
State::HeaderValue => {
|
State::HeaderValue => match char {
|
||||||
match char {
|
|
||||||
0x20..=0x7E | 0x09 => State::HeaderValue,
|
0x20..=0x7E | 0x09 => State::HeaderValue,
|
||||||
0x0D => {
|
0x0D => {
|
||||||
self.headers.last_mut().unwrap().1 = get_str().trim();
|
self.headers.last_mut().unwrap().1 = get_str().trim();
|
||||||
State::CRLF(&State::HeaderName)
|
State::CRLF(&State::HeaderName)
|
||||||
},
|
}
|
||||||
_ => State::Error,
|
_ => State::Error,
|
||||||
}
|
},
|
||||||
}
|
State::CRLF(next) => match char {
|
||||||
State::CRLF(next) => {
|
|
||||||
match char {
|
|
||||||
0x0A => {
|
0x0A => {
|
||||||
self.str_start = self.header_size;
|
self.str_start = self.header_size;
|
||||||
*next.clone()
|
*next.clone()
|
||||||
},
|
|
||||||
_ => State::Error,
|
|
||||||
}
|
}
|
||||||
|
_ => State::Error,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -312,7 +301,10 @@ mod tests {
|
|||||||
assert_eq!(3, parser.headers.len());
|
assert_eq!(3, parser.headers.len());
|
||||||
assert_eq!(("Host", "www.example.com"), parser.headers[0]);
|
assert_eq!(("Host", "www.example.com"), parser.headers[0]);
|
||||||
assert_eq!(("Content-Length", "13"), parser.headers[1]);
|
assert_eq!(("Content-Length", "13"), parser.headers[1]);
|
||||||
assert_eq!(("User-Agent", "Mozilla/5.0 (X11; Linux x86_64)"), parser.headers[2]);
|
assert_eq!(
|
||||||
|
("User-Agent", "Mozilla/5.0 (X11; Linux x86_64)"),
|
||||||
|
parser.headers[2]
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!("username=test", &request[size..]);
|
assert_eq!("username=test", &request[size..]);
|
||||||
}
|
}
|
||||||
@ -357,7 +349,10 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(2, parser.headers.len());
|
assert_eq!(2, parser.headers.len());
|
||||||
assert_eq!(("Content-Length", "12"), parser.headers[0]);
|
assert_eq!(("Content-Length", "12"), parser.headers[0]);
|
||||||
assert_eq!(("Content-Type", "text/plain; charset=us-ascii"), parser.headers[1]);
|
assert_eq!(
|
||||||
|
("Content-Type", "text/plain; charset=us-ascii"),
|
||||||
|
parser.headers[1]
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!("Hello world!", &response[size..]);
|
assert_eq!("Hello world!", &response[size..]);
|
||||||
}
|
}
|
||||||
|
17
src/main.rs
17
src/main.rs
@ -2,12 +2,12 @@ mod http;
|
|||||||
mod udp;
|
mod udp;
|
||||||
mod usimp;
|
mod usimp;
|
||||||
|
|
||||||
use std::thread;
|
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod, SslStream};
|
||||||
use threadpool::ThreadPool;
|
|
||||||
use std::net::{TcpListener, UdpSocket};
|
use std::net::{TcpListener, UdpSocket};
|
||||||
use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use std::thread;
|
||||||
|
use threadpool::ThreadPool;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut threads = Vec::new();
|
let mut threads = Vec::new();
|
||||||
@ -32,8 +32,15 @@ fn main() {
|
|||||||
let mut ssl_socket = TcpListener::bind("[::]:8443").unwrap();
|
let mut ssl_socket = TcpListener::bind("[::]:8443").unwrap();
|
||||||
|
|
||||||
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
|
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
|
||||||
acceptor.set_certificate_chain_file("/home/lorenz/Certificates/chakotay.pem").unwrap();
|
acceptor
|
||||||
acceptor.set_private_key_file("/home/lorenz/Certificates/priv/chakotay.key", SslFiletype::PEM).unwrap();
|
.set_certificate_chain_file("/home/lorenz/Certificates/chakotay.pem")
|
||||||
|
.unwrap();
|
||||||
|
acceptor
|
||||||
|
.set_private_key_file(
|
||||||
|
"/home/lorenz/Certificates/priv/chakotay.key",
|
||||||
|
SslFiletype::PEM,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
acceptor.check_private_key().unwrap();
|
acceptor.check_private_key().unwrap();
|
||||||
let acceptor = Arc::new(acceptor.build());
|
let acceptor = Arc::new(acceptor.build());
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::net::{UdpSocket, SocketAddr};
|
use std::net::{SocketAddr, UdpSocket};
|
||||||
|
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
socket: UdpSocket,
|
socket: UdpSocket,
|
||||||
@ -8,7 +8,12 @@ pub struct Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
pub fn new(socket: &UdpSocket, address: SocketAddr, size: usize, buf: &[u8; 65_536]) -> Request {
|
pub fn new(
|
||||||
|
socket: &UdpSocket,
|
||||||
|
address: SocketAddr,
|
||||||
|
size: usize,
|
||||||
|
buf: &[u8; 65_536],
|
||||||
|
) -> Request {
|
||||||
Request {
|
Request {
|
||||||
socket: socket.try_clone().unwrap(),
|
socket: socket.try_clone().unwrap(),
|
||||||
address,
|
address,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
pub fn is_valid(evt: &str) -> bool {
|
pub fn is_valid(evt: &str) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user