documentation
This commit is contained in:
parent
b7cd187c0e
commit
3e51e91630
105
src/lib.rs
105
src/lib.rs
@ -18,6 +18,7 @@ use std::{
|
|||||||
sync::{mpsc, Mutex},
|
sync::{mpsc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Http headers
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Headers {
|
pub struct Headers {
|
||||||
entries: Vec<(String, String)>,
|
entries: Vec<(String, String)>,
|
||||||
@ -51,18 +52,9 @@ impl Headers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_value(self, value: impl ToString) -> bool {
|
pub fn contains(self, header: impl ToString) -> bool {
|
||||||
for (_, v) in self.entries {
|
|
||||||
if v == value.to_string() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn contains_key(self, key: impl ToString) -> bool {
|
|
||||||
for (k, _) in self.entries {
|
for (k, _) in self.entries {
|
||||||
if k.to_lowercase() == key.to_string().to_lowercase() {
|
if k.to_lowercase() == header.to_string().to_lowercase() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,6 +116,7 @@ impl Display for Headers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Http request
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct HttpRequest {
|
pub struct HttpRequest {
|
||||||
pub page: String,
|
pub page: String,
|
||||||
@ -140,6 +133,7 @@ impl Display for HttpRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Http response
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct HttpResponse {
|
pub struct HttpResponse {
|
||||||
pub headers: Headers,
|
pub headers: Headers,
|
||||||
@ -241,17 +235,19 @@ fn split(text: String, delimiter: &str, times: usize) -> Vec<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl HttpRequest {
|
impl HttpRequest {
|
||||||
|
/// Create new http request
|
||||||
pub fn new(page: &str, method: &str, params: Value, headers: Headers, data: Vec<u8>) -> Self {
|
pub fn new(page: &str, method: &str, params: Value, headers: Headers, data: Vec<u8>) -> Self {
|
||||||
HttpRequest {
|
HttpRequest {
|
||||||
page: page.to_string(),
|
page: page.to_string(),
|
||||||
method: method.to_string(),
|
method: method.to_string(),
|
||||||
addr: String::new(),
|
addr: String::new(),
|
||||||
params: params,
|
params,
|
||||||
headers: headers,
|
headers,
|
||||||
data: data,
|
data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read http request from stream
|
||||||
pub fn read(data: &mut impl Read, addr: &SocketAddr) -> Result<HttpRequest, HttpError> {
|
pub fn read(data: &mut impl Read, addr: &SocketAddr) -> Result<HttpRequest, HttpError> {
|
||||||
let octets = match addr.ip() {
|
let octets = match addr.ip() {
|
||||||
IpAddr::V4(ip) => ip.octets(),
|
IpAddr::V4(ip) => ip.octets(),
|
||||||
@ -406,15 +402,16 @@ impl HttpRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(HttpRequest {
|
Ok(HttpRequest {
|
||||||
page: page,
|
page,
|
||||||
method: method,
|
method,
|
||||||
addr: ip_str.to_string(),
|
addr: ip_str.to_string(),
|
||||||
params: Value::Object(params),
|
params: Value::Object(params),
|
||||||
headers: headers,
|
headers,
|
||||||
data: reqdata.clone(),
|
data: reqdata.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read http request with http_rrs support
|
||||||
pub fn read_with_rrs(data: &mut impl Read) -> Result<HttpRequest, HttpError> {
|
pub fn read_with_rrs(data: &mut impl Read) -> Result<HttpRequest, HttpError> {
|
||||||
let addr = match read_line_lf(data) {
|
let addr = match read_line_lf(data) {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
@ -428,6 +425,7 @@ impl HttpRequest {
|
|||||||
HttpRequest::read(data, &addr)
|
HttpRequest::read(data, &addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set params to query in url
|
||||||
pub fn params_to_page(&mut self) {
|
pub fn params_to_page(&mut self) {
|
||||||
let mut query = String::new();
|
let mut query = String::new();
|
||||||
|
|
||||||
@ -450,6 +448,14 @@ impl HttpRequest {
|
|||||||
self.page += query.as_str();
|
self.page += query.as_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set params to json data
|
||||||
|
pub fn params_to_json(&mut self) {
|
||||||
|
self.data = Vec::from(self.params.to_string().as_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write http request to stream
|
||||||
|
///
|
||||||
|
/// [`params`](Self::params) is not written to the stream, you need to use [`params_to_json`](Self::params_to_json) or [`params_to_page`](Self::params_to_page)
|
||||||
pub fn write(self, data: &mut impl Write) -> Result<(), HttpError> {
|
pub fn write(self, data: &mut impl Write) -> Result<(), HttpError> {
|
||||||
let mut head: String = String::new();
|
let mut head: String = String::new();
|
||||||
head.push_str(&self.method);
|
head.push_str(&self.method);
|
||||||
@ -484,26 +490,30 @@ impl HttpRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl HttpResponse {
|
impl HttpResponse {
|
||||||
|
/// Create new http response with empty headers and data and a 200 OK status code
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::from_bytes(Headers::new(), "200 OK", Vec::new())
|
Self::from_bytes(Headers::new(), "200 OK", Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create new http response from headers, bytes data, and status code
|
||||||
pub fn from_bytes(headers: Headers, status_code: impl ToString, data: Vec<u8>) -> Self {
|
pub fn from_bytes(headers: Headers, status_code: impl ToString, data: Vec<u8>) -> Self {
|
||||||
HttpResponse {
|
HttpResponse {
|
||||||
headers: headers,
|
headers,
|
||||||
data: data,
|
data,
|
||||||
status_code: status_code.to_string(),
|
status_code: status_code.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create new http response from headers, string data, and status code
|
||||||
pub fn from_string(headers: Headers, status_code: impl ToString, data: impl ToString) -> Self {
|
pub fn from_string(headers: Headers, status_code: impl ToString, data: impl ToString) -> Self {
|
||||||
HttpResponse {
|
HttpResponse {
|
||||||
headers: headers,
|
headers,
|
||||||
data: data.to_string().into_bytes(),
|
data: data.to_string().into_bytes(),
|
||||||
status_code: status_code.to_string(),
|
status_code: status_code.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get data in UTF-8
|
||||||
pub fn get_text(self) -> String {
|
pub fn get_text(self) -> String {
|
||||||
match String::from_utf8(self.data) {
|
match String::from_utf8(self.data) {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
@ -511,6 +521,7 @@ impl HttpResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get json [`Value`](Value) from data
|
||||||
pub fn get_json(self) -> Value {
|
pub fn get_json(self) -> Value {
|
||||||
match serde_json::from_str(self.get_text().as_str()) {
|
match serde_json::from_str(self.get_text().as_str()) {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
@ -518,6 +529,7 @@ impl HttpResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read http response from stream
|
||||||
pub fn read(data: &mut impl Read) -> Result<HttpResponse, HttpError> {
|
pub fn read(data: &mut impl Read) -> Result<HttpResponse, HttpError> {
|
||||||
let status = match read_line_crlf(data) {
|
let status = match read_line_crlf(data) {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
@ -591,13 +603,10 @@ impl HttpResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(HttpResponse {
|
Ok(HttpResponse::from_bytes(headers, status_code, reqdata))
|
||||||
headers: headers,
|
|
||||||
status_code: status_code.to_string(),
|
|
||||||
data: reqdata,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write http response to stream
|
||||||
pub fn write(self, data: &mut impl Write) -> Result<(), &str> {
|
pub fn write(self, data: &mut impl Write) -> Result<(), &str> {
|
||||||
let mut head: String = String::new();
|
let mut head: String = String::new();
|
||||||
head.push_str("HTTP/1.1 ");
|
head.push_str("HTTP/1.1 ");
|
||||||
@ -627,6 +636,7 @@ impl HttpResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Async http server trait
|
||||||
pub trait HttpServer {
|
pub trait HttpServer {
|
||||||
fn on_start(&mut self, host: &str) -> impl Future<Output = ()> + Send;
|
fn on_start(&mut self, host: &str) -> impl Future<Output = ()> + Send;
|
||||||
fn on_close(&mut self) -> impl Future<Output = ()> + Send;
|
fn on_close(&mut self) -> impl Future<Output = ()> + Send;
|
||||||
@ -636,6 +646,7 @@ pub trait HttpServer {
|
|||||||
) -> impl Future<Output = Option<HttpResponse>> + Send;
|
) -> impl Future<Output = Option<HttpResponse>> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Http server start builder
|
||||||
pub struct HttpServerStarter<T: HttpServer + Send + 'static> {
|
pub struct HttpServerStarter<T: HttpServer + Send + 'static> {
|
||||||
http_server: T,
|
http_server: T,
|
||||||
support_http_rrs: bool,
|
support_http_rrs: bool,
|
||||||
@ -644,6 +655,7 @@ pub struct HttpServerStarter<T: HttpServer + Send + 'static> {
|
|||||||
threads: usize,
|
threads: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Running http server
|
||||||
pub struct RunningHttpServer {
|
pub struct RunningHttpServer {
|
||||||
thread: thread::JoinHandle<()>,
|
thread: thread::JoinHandle<()>,
|
||||||
running: Arc<AtomicBool>,
|
running: Arc<AtomicBool>,
|
||||||
@ -654,6 +666,7 @@ impl RunningHttpServer {
|
|||||||
RunningHttpServer { thread, running }
|
RunningHttpServer { thread, running }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stop http server
|
||||||
pub fn close(self) {
|
pub fn close(self) {
|
||||||
self.running.store(false, Ordering::Release);
|
self.running.store(false, Ordering::Release);
|
||||||
self.thread.join().unwrap();
|
self.thread.join().unwrap();
|
||||||
@ -661,6 +674,7 @@ impl RunningHttpServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: HttpServer + Send + 'static> HttpServerStarter<T> {
|
impl<T: HttpServer + Send + 'static> HttpServerStarter<T> {
|
||||||
|
/// Create new HttpServerStarter
|
||||||
pub fn new(http_server: T, host: &str) -> Self {
|
pub fn new(http_server: T, host: &str) -> Self {
|
||||||
HttpServerStarter {
|
HttpServerStarter {
|
||||||
http_server,
|
http_server,
|
||||||
@ -671,31 +685,68 @@ impl<T: HttpServer + Send + 'static> HttpServerStarter<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set http server
|
||||||
pub fn http_server(mut self, http_server: T) -> Self {
|
pub fn http_server(mut self, http_server: T) -> Self {
|
||||||
self.http_server = http_server;
|
self.http_server = http_server;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set if http_rrs is supported
|
||||||
pub fn support_http_rrs(mut self, support_http_rrs: bool) -> Self {
|
pub fn support_http_rrs(mut self, support_http_rrs: bool) -> Self {
|
||||||
self.support_http_rrs = support_http_rrs;
|
self.support_http_rrs = support_http_rrs;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set timeout for read & write
|
||||||
pub fn timeout(mut self, timeout: Option<Duration>) -> Self {
|
pub fn timeout(mut self, timeout: Option<Duration>) -> Self {
|
||||||
self.timeout = timeout;
|
self.timeout = timeout;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set host
|
||||||
pub fn host(mut self, host: String) -> Self {
|
pub fn host(mut self, host: String) -> Self {
|
||||||
self.host = host;
|
self.host = host;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set threads in threadpool and return builder
|
||||||
|
///
|
||||||
|
/// 0 threads means that a new thread is created for each connection
|
||||||
|
/// 1 thread means that all connections are processed in the main thread
|
||||||
pub fn threads(mut self, threads: usize) -> Self {
|
pub fn threads(mut self, threads: usize) -> Self {
|
||||||
self.threads = threads;
|
self.threads = threads;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get http server
|
||||||
|
pub fn get_http_server(self) -> T {
|
||||||
|
self.http_server
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get if http_rrs is supported
|
||||||
|
pub fn get_support_http_rrs(&self) -> bool {
|
||||||
|
self.support_http_rrs
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get timeout for read & write
|
||||||
|
pub fn get_timeout(&self) -> Option<Duration> {
|
||||||
|
self.timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get host
|
||||||
|
pub fn get_host(&self) -> &str {
|
||||||
|
&self.host
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get threads in threadpool
|
||||||
|
///
|
||||||
|
/// 0 threads means that a new thread is created for each connection
|
||||||
|
/// 1 thread means that all connections are processed in the main thread
|
||||||
|
pub fn get_threads(&self) -> usize {
|
||||||
|
self.threads
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start http server forever with options
|
||||||
pub fn start_forever(self) -> Result<(), Box<dyn Error>> {
|
pub fn start_forever(self) -> Result<(), Box<dyn Error>> {
|
||||||
let handler = if self.support_http_rrs {
|
let handler = if self.support_http_rrs {
|
||||||
move |server, sock| {
|
move |server, sock| {
|
||||||
@ -725,6 +776,7 @@ impl<T: HttpServer + Send + 'static> HttpServerStarter<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Start http server with options in new thread
|
||||||
pub fn start(self) -> RunningHttpServer {
|
pub fn start(self) -> RunningHttpServer {
|
||||||
let handler = if self.support_http_rrs {
|
let handler = if self.support_http_rrs {
|
||||||
move |server, sock| {
|
move |server, sock| {
|
||||||
@ -999,6 +1051,9 @@ impl Worker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Start [`HttpServer`](HttpServer) on some host
|
||||||
|
///
|
||||||
|
/// Use [`HttpServerStarter`](HttpServerStarter) to set more options
|
||||||
pub fn start_server<S: HttpServer + Send + 'static>(server: S, host: &str) {
|
pub fn start_server<S: HttpServer + Send + 'static>(server: S, host: &str) {
|
||||||
start_server_new_thread(
|
start_server_new_thread(
|
||||||
server,
|
server,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use ezhttp::{Headers, HttpRequest, HttpResponse, HttpServer, HttpServerStarter};
|
use ezhttp::{Headers, HttpRequest, HttpResponse, HttpServer, HttpServerStarter};
|
||||||
use std::{collections::HashMap, time::Duration};
|
use std::time::Duration;
|
||||||
|
|
||||||
struct EzSite {
|
struct EzSite {
|
||||||
index_page: String,
|
index_page: String,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user