Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • codecraft/webserver
  • sorcaMriete/webserver
  • opnonmicgo/webserver
  • loposuezo/webserver
  • diufeYmike/webserver
  • contbuspecmi/webserver
  • mogamuboun/webserver
  • glabalwelre/webserver
8 results
Show changes
Showing
with 5803 additions and 4 deletions
This diff is collapsed.
mod map;
mod mime_enum;
pub use map::MIME_MAP;
pub use mime_enum::Mime;
pub use mime_enum::ParseMimeError;
pub mod mime;
pub mod url_utils;
pub mod urlencoded;
pub mod vec_utils;
use std::error;
use crate::utils::urlencoded::UrlEncodeData;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Uri {
pub(super) parts: Vec<UrlEncodeData>,
pub raw: String,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct RawUri {
pub(super) raw_string: String,
pub(super) infinte_end: bool,
pub(super) parts: Vec<RawUriElement>,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum RawUriElement {
Variable,
Name(UrlEncodeData),
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum UriError {
InvalidUriEncoding,
}
#[derive(Debug)]
pub struct ParseUriError {
pub error: UriError,
}
impl std::fmt::Display for ParseUriError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
impl error::Error for ParseUriError {}
mod datatypes;
mod uri;
pub use datatypes::ParseUriError;
pub use datatypes::RawUri;
pub use datatypes::RawUriElement;
pub use datatypes::Uri;
pub use datatypes::UriError;
use std::str::FromStr;
use crate::{
setup::MountPoint,
utils::{
url_utils::datatypes::RawUriElement,
urlencoded::{EnCodable, UrlEncodeData},
vec_utils::remove_n,
},
};
use super::datatypes::{ParseUriError, RawUri, Uri};
impl MountPoint {
pub fn compare_with_uri(&self, uri: &mut Uri) -> bool {
if !uri.raw.starts_with(&self.mountpoint.raw) {
return false;
}
let to_remove_after_finish = self.mountpoint.parts.len();
remove_n(uri.mut_parts(), to_remove_after_finish);
true
}
}
impl Uri {
pub fn new(parts: Vec<&str>) -> Self {
Self {
raw: "/".to_owned()
+ &parts
.iter()
.map(|part| part.encode())
.collect::<Vec<String>>()
.join("/"),
parts: parts.into_iter().map(UrlEncodeData::from_raw).collect(),
}
}
pub fn parts(&self) -> &[UrlEncodeData] {
self.parts.as_slice()
}
pub fn mut_parts(&mut self) -> &mut Vec<UrlEncodeData> {
self.parts.as_mut()
}
pub fn compare(&self, uri: &Uri) -> bool {
let mut uri_iter = uri.parts.iter();
for part in self.parts.iter() {
let Some(part_uri) = uri_iter.next() else {
return false;
};
if part != part_uri {
return false;
}
}
true
}
pub(crate) fn to_pretty_print_string(&self) -> String {
if self.parts.is_empty() {
"/".to_string()
} else {
let url = self
.parts
.iter()
.map(|part| part.encoded())
.collect::<Vec<_>>();
"/".to_string() + &url.join("/")
}
}
}
impl RawUri {
pub fn new(parts: Vec<&str>) -> Self {
let mut result = Self {
infinte_end: false,
parts: Vec::with_capacity(parts.len()),
raw_string: parts.join("/"),
};
for part in parts {
if part.starts_with('<') && part.ends_with("..>") {
result.infinte_end = true;
break;
}
if part.starts_with('<') && part.ends_with('>') {
result.parts.push(RawUriElement::Variable);
continue;
}
result
.parts
.push(RawUriElement::Name(UrlEncodeData::from_raw(part)))
}
result
}
pub fn compare_uri(&self, uri: &Uri) -> bool {
let mut iter_comp = uri.parts.iter();
if uri.parts().len() != self.parts.len() && !self.infinte_end {
return false;
}
for element in self.parts.iter() {
let Some(compare_element) = iter_comp.next() else {
return false;
};
if *element == RawUriElement::Variable {
continue;
}
if let RawUriElement::Name(name) = element {
if name.encoded() != compare_element.encoded() {
return false;
}
} else {
return false;
}
}
if uri.parts.len() > self.parts.len() && self.infinte_end {
return true;
}
true
}
pub(crate) fn to_pretty_print_string(&self, is_after: &Uri) -> String {
let is_after = is_after.to_pretty_print_string();
if is_after == "/" {
format!("\x1b[34;4m/\x1b[24m{}\x1b[0m", self)
} else {
format!("\x1b[34;4m{is_after}/\x1b[24m{self}\x1b[0m")
}
}
}
impl std::fmt::Display for RawUri {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.raw_string)
}
}
impl std::fmt::Display for Uri {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.parts.is_empty() {
write!(f, "/")
} else {
let url = self
.parts
.iter()
.map(|part| part.encoded())
.collect::<Vec<_>>();
write!(f, "{}", url.join("/"))
}
}
}
impl FromStr for Uri {
type Err = ParseUriError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let split = s.split('/');
let mut result = Vec::new();
for sub in split {
if sub.is_empty() {
continue;
}
result.push(if let Ok(coded) = UrlEncodeData::from_encoded(sub) {
coded
} else {
UrlEncodeData::from_raw(sub)
});
}
Ok(Self {
parts: result,
raw: s.to_string(),
})
}
}
impl FromStr for RawUri {
type Err = ParseUriError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts = s.split('/').collect::<Vec<&str>>();
let mut result = Self {
infinte_end: false,
parts: Vec::new(),
raw_string: s.to_string(),
};
for part in parts {
if part.is_empty() {
continue;
}
if part.starts_with('<') && part.ends_with("..>") {
result.infinte_end = true;
break;
}
if part.starts_with('<') && part.ends_with('>') {
result.parts.push(RawUriElement::Variable);
continue;
}
result
.parts
.push(RawUriElement::Name(UrlEncodeData::from_raw(part)))
}
Ok(result)
}
}
impl TryFrom<&str> for Uri {
type Error = ParseUriError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::from_str(value)
}
}
impl TryFrom<&str> for RawUri {
type Error = ParseUriError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::from_str(value)
}
}
#[cfg(test)]
mod test {
use crate::utils::{
url_utils::{
datatypes::{RawUri, RawUriElement},
Uri,
},
urlencoded::UrlEncodeData,
};
#[test]
fn uri_to_string() {
assert_eq!("a/%20", Uri::new(vec!["a", " "]).to_string());
}
#[test]
fn uri_from_string() {
assert_eq!(Uri::new(vec!["a", " "]), "/a/%20".parse().unwrap())
}
#[test]
fn raw_uri_from_string() {
assert_eq!(
RawUri {
raw_string: "/<name>/a/<f..>".to_owned(),
infinte_end: true,
parts: vec![
RawUriElement::Variable,
RawUriElement::Name(UrlEncodeData::from_raw("a")),
]
},
"/<name>/a/<f..>".parse().unwrap()
);
}
#[test]
fn raw_uri_to_string() {
assert_eq!(
"/<name>/a/<f..>",
RawUri {
raw_string: "/<name>/a/<f..>".to_owned(),
infinte_end: true,
parts: vec![
RawUriElement::Variable,
RawUriElement::Name(UrlEncodeData::from_raw("a")),
]
}
.to_string()
)
}
}
use crate::utils::urlencoded::endecode::EnCodable;
use super::endecode::DeCodable;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
/// A way to store UrlEncoded data
pub struct UrlEncodeData {
/// Encoded string
pub(crate) encoded: String,
/// raw data, unencoded
pub(crate) raw: Vec<u8>,
/// raw string if it exists
pub(crate) raw_string: Option<String>,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum UrlEncodeError {
NonHexAfterPercent,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ParseUrlEncodeError {
pub inner: UrlEncodeError,
}
impl std::fmt::Display for ParseUrlEncodeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
impl std::error::Error for ParseUrlEncodeError {}
impl UrlEncodeData {
/// Generates a [UrlEncodeData] from any raw data that can be a slice of [u8]
pub fn from_raw<T: AsRef<[u8]>>(raw: T) -> Self {
Self {
raw: raw.as_ref().to_owned(),
encoded: raw.encode(),
raw_string: String::from_utf8(raw.as_ref().into()).ok(),
}
}
/// Generates a [UrlEncodeData] from a correctly encoded string
///
/// # Errors
///
/// errors if the encoded data is wrongly encoded -> %<invalid_character>
pub fn from_encoded(encoded: &str) -> super::UriParseResult<Self> {
Ok(Self {
encoded: encoded.to_owned(),
raw: encoded.decode()?,
raw_string: String::from_utf8(encoded.decode()?).ok(),
})
}
/// Gets a reference to the encoded data
pub fn encoded(&self) -> &str {
self.encoded.as_ref()
}
/// Get a reference to the raw [u8] slice
pub fn raw(&self) -> &[u8] {
self.raw.as_ref()
}
/// Gets an Optional string slice to the raw data
pub fn raw_string(&self) -> Option<&str> {
self.raw_string.as_deref()
}
}
impl std::fmt::Display for UrlEncodeData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.encoded)
}
}
use super::{datatypes::ParseUrlEncodeError, UriParseResult};
/// Base of the HexaDecimal Number system
static BASE16_HEXA_DECIMAL: u8 = 0x10;
/// Highest possible Value per digit
static BASE16_HEXA_DECIMAL_POSSIBLE_VALUE_PER_DIGIT: u8 = 0xF;
/// Bits of a hexa decimal number
static BASE16_HEXA_DECIMAL_DIGIT_BITS: u8 = 4;
pub trait EnCodable {
/// Encodes the give data into a Percent Encoded [String]
fn encode(&self) -> String;
}
pub trait DeCodable {
/// Decodes the given data into a [`Vec<u8>`]
///
/// # Errors
/// Errors if the encoding isn't right
fn decode(&self) -> UriParseResult<Vec<u8>>;
}
impl<T: AsRef<[u8]>> EnCodable for T {
fn encode(&self) -> String {
self.as_ref().encode()
}
}
impl EnCodable for [u8] {
fn encode(self: &[u8]) -> String {
let mut result = String::with_capacity(self.len());
let result_vec = unsafe { result.as_mut_vec() };
self.iter().for_each(|byte| {
if !matches!(byte, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' | b'-' | b'_' | b'.' | b'~')
{
result_vec.push(b'%');
result_vec.push(hex_to_digit(byte >> BASE16_HEXA_DECIMAL_DIGIT_BITS));
result_vec.push(hex_to_digit(
byte & BASE16_HEXA_DECIMAL_POSSIBLE_VALUE_PER_DIGIT,
));
} else {
result_vec.push(*byte)
}
});
result
}
}
impl DeCodable for &str {
fn decode(&self) -> UriParseResult<Vec<u8>> {
let mut first = true;
let mut result = Vec::with_capacity(self.len());
for i in self.split('%') {
if first {
first = false;
result.extend_from_slice(i.as_bytes());
continue;
}
let Ok(char) = u8::from_str_radix(i[0..=1].as_ref(), BASE16_HEXA_DECIMAL.into()) else {
return Err(ParseUrlEncodeError { inner: super::datatypes::UrlEncodeError::NonHexAfterPercent });
};
result.push(char);
result.extend_from_slice(i[2..].as_bytes());
}
Ok(result)
}
}
/// converts a [u8] digit into the ascii code of its counterpart. The digit shouldn't be bigger
/// than [BASE16_HEXA_DECIMAL_POSSIBLE_VALUE_PER_DIGIT]
fn hex_to_digit(digit: u8) -> u8 {
match digit {
0..=9 => b'0' + digit,
10..=255 => b'A' + digit - 10,
}
}
#[cfg(test)]
mod test {
use crate::utils::urlencoded::endecode::DeCodable;
use crate::utils::urlencoded::endecode::EnCodable;
#[test]
fn urlencoded_test() {
assert_eq!(
"Darius%20is%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire",
b"Darius is the biggest genius/Genie/Human extraordin\xC3\xA4ire".encode()
);
}
#[test]
fn urldecoded_test() {
assert_eq!(
"Darius is the biggest genius/Genie/Human extraordinäire",
String::from_utf8(
"Darius%20is%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire"
.decode()
.unwrap()
)
.unwrap()
);
assert_eq!(
Err(crate::utils::urlencoded::datatypes::ParseUrlEncodeError {
inner: crate::utils::urlencoded::datatypes::UrlEncodeError::NonHexAfterPercent
}),
"Darius%2iis%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire".decode()
);
assert_eq!(
"hi?asdf=sadf%%&jkl=s",
String::from_utf8("hi?asdf=sadf%25%25&jkl=s".decode().unwrap()).unwrap()
)
}
}
mod datatypes;
mod endecode;
use std::result;
type UriParseResult<T> = result::Result<T, datatypes::ParseUrlEncodeError>;
pub use datatypes::UrlEncodeData;
pub use endecode::{DeCodable, EnCodable};
pub(crate) fn remove_n<T>(vec: &mut Vec<T>, n: usize) {
if n > vec.len() {
return;
}
for i in 0..n {
vec.remove(i);
}
}
use std::{collections::HashMap, path::PathBuf};
use http::handling::{
file_handlers::NamedFile,
methods::Method,
request::{Request, ParseFormError},
response::{Outcome, Response, Status},
routes::{Data, Route},
};
fn hashmap_to_string(map: &HashMap<&str, Result<&str, ParseFormError>>) -> String {
let mut result = String::new();
for (key, value) in map {
result.push_str(key);
result.push('=');
result.push_str(value.as_ref().unwrap());
result.push(';');
}
result.pop(); // Remove the trailing semicolon if desired
result
}
fn handle_static_hi(request: Request<>, data: Data) -> Outcome<Response, Status, Data> {
let keys = if let Ok(keys) = request.get_get_form_keys(&["asdf", "jkl"]) {
keys
} else {
return Outcome::Forward(data);
};
let response = hashmap_to_string(&keys);
Outcome::Success(Response {
headers: vec![],
cookies: None,
status: Some(Status::Ok),
body: Box::new(response),
})
// Outcome::Forward(data)
}
fn handler(request: Request<>, _data: Data) -> Outcome<Response, Status, Data> {
let response = fileserver(request.uri.raw_string().unwrap().strip_prefix("static/").unwrap());
let response = match response {
Ok(dat) => Response {
headers: vec![],
cookies: None,
status: Some(Status::Ok),
body: Box::new(dat),
},
Err(_) => return Outcome::Failure(Status::NotFound),
};
Outcome::Success(response)
}
fn fileserver(path: &str) -> Result<NamedFile, Status> {
NamedFile::open(PathBuf::from("static/".to_string() + path))
}
fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Data> {
if data.is_empty() {
return Outcome::Forward(data);
}
let dat = if let Ok(val) = request.get_post_data(&["message"], &data) {
post_hi(String::from_utf8_lossy(val.get("message").unwrap().as_ref().unwrap()).to_string())
} else {
return Outcome::Failure(Status::BadRequest);
};
Outcome::Success(Response {
headers: vec![],
cookies: None,
status: Some(Status::Ok),
body: Box::new(dat),
})
}
fn post_hi(msg: String) -> String {
msg
}
#[tokio::main]
async fn main() {
let fileserver = Route {
format: None,
handler,
name: Some("file_server"),
uri: "static/<path..>",
method: Method::Get,
rank: 1,
};
let post_test = Route {
format: None,
handler: post_hi_handler,
name: Some("post_test"),
uri: "post",
method: Method::Post,
rank: 0,
};
let static_hi = Route {
format: None,
handler: handle_static_hi,
name: Some("Handle_Static_hi"),
uri: "static/hi",
method: Method::Get,
rank: 0,
};
http::build("127.0.0.1:8080", "127.0.0.1:8443")
.await
.mount("/", vec![fileserver, post_test, static_hi])
.mount("/post/", vec![post_test])
.launch()
.await;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>404</title>
</head>
<body>
<h1>404</h1>
<p>Hi from Rust</p>
<form action="/post/post" method="post" enctype="multipart/form-data">
<label for="message">Enter your message:</label>
<input type="text" id="message" name="message" />
<button type="submit">Send</button>
</form>
<form action="/static/hi" method="get">
<label for="jump">Enter asdf</label>
<input type="text" id="jump" name="asdf" />
<label for="jkl">Enter jkl;</label>
<input type="text" id="jkl" name="jkl" />
<button type="submit">Send</button>
</form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>411</title>
</head>
<h1>411</h1>
</html>
This diff is collapsed.
[package] [package]
name = "site" name = "site"
version = "0.1.0" version = "1.0.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
http = { path = "../core/http", features = ["secure"]}
tokio = { version = "1.28.2", features = ["full"] }
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
fill="#000000"
height="800px"
width="800px"
version="1.1"
id="Capa_1"
viewBox="0 0 511 511"
xml:space="preserve"
sodipodi:docname="favicon.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs290" /><sodipodi:namedview
id="namedview288"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="1.51125"
inkscape:cx="390.73615"
inkscape:cy="400"
inkscape:window-width="5120"
inkscape:window-height="1387"
inkscape:window-x="0"
inkscape:window-y="28"
inkscape:window-maximized="1"
inkscape:current-layer="Capa_1" />
<g
id="g285"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1">
<path
d="M487.5,128.106H479v-24.5c0-2.905-1.678-5.549-4.307-6.786C405.088,64.066,325.408,63.6,255.5,95.371 C185.592,63.6,105.912,64.067,36.307,96.82C33.678,98.057,32,100.701,32,103.606v24.5h-8.5c-12.958,0-23.5,10.542-23.5,23.5v264 c0,12.958,10.542,23.5,23.5,23.5h464c12.958,0,23.5-10.542,23.5-23.5v-264C511,138.648,500.458,128.106,487.5,128.106z M263,239.583c0-0.009,0-0.019,0-0.028V108.416c64.137-28.707,136.861-28.707,201,0v27.161c0,0.01-0.001,0.02-0.001,0.029 s0.001,0.02,0.001,0.029v244.438c-32.237-13.461-66.371-20.193-100.5-20.193c-34.129,0-68.264,6.732-100.5,20.193V239.583z M215,96.391c11.187,3.204,22.217,7.198,33,12.025v117.177l-12.34-8.227c-2.52-1.68-5.801-1.68-8.32,0L215,225.593V96.391z M47,135.626c0-0.007,0.001-0.013,0.001-0.02S47,135.594,47,135.587v-27.171c48.563-21.736,102.046-26.999,153-15.82v32.856 c-26.767-5.505-54.078-6.777-81.328-3.75c-4.117,0.457-7.083,4.165-6.626,8.282c0.458,4.116,4.162,7.085,8.282,6.626 c26.708-2.967,53.479-1.562,79.671,4.165v48.686c-15.912-3.265-32.14-5.067-48.377-5.323c-4.145-0.078-7.552,3.239-7.618,7.38 c-0.065,4.142,3.239,7.552,7.38,7.618c16.331,0.258,32.654,2.164,48.614,5.647v16.66c-43.389-8.909-88.39-6.644-130.748,6.665 c-3.952,1.241-6.148,5.451-4.907,9.403c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347 c40.908-12.852,84.428-14.773,126.252-5.638v2.825c0,2.766,1.522,5.308,3.961,6.612c2.438,1.306,5.398,1.162,7.699-0.372 l19.84-13.227l16.5,11v136.454c-32.237-13.461-66.371-20.193-100.5-20.193c-34.129,0-68.264,6.732-100.5,20.193V135.626z M224,424.106H23.5c-4.687,0-8.5-3.813-8.5-8.5v-264c0-4.687,3.813-8.5,8.5-8.5H32v248.5v8c0,4.142,3.358,7.5,7.5,7.5H224V424.106z M57.29,392.106c58.099-22.934,122.32-22.935,180.42,0H57.29z M272,424.106h-33v-17h33V424.106z M453.71,392.106H273.29 C331.389,369.172,395.61,369.172,453.71,392.106z M496,415.606c0,4.687-3.813,8.5-8.5,8.5H287v-17h184.5c4.142,0,7.5-3.358,7.5-7.5 v-8v-248.5h8.5c4.687,0,8.5,3.813,8.5,8.5V415.606z"
id="path243"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M309.96,317.749c-8.302,1.74-16.615,3.911-24.708,6.454c-3.952,1.242-6.148,5.452-4.907,9.403 c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c7.628-2.396,15.464-4.443,23.288-6.083 c4.054-0.85,6.652-4.825,5.802-8.879C317.989,319.497,314.011,316.9,309.96,317.749z"
id="path245"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M439.502,338.859c3.189,0,6.147-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403 c-32.073-10.076-65.329-13.842-98.844-11.188c-4.129,0.326-7.211,3.938-6.885,8.068s3.935,7.213,8.068,6.885 c31.59-2.499,62.935,1.048,93.165,10.546C438,338.748,438.757,338.859,439.502,338.859z"
id="path247"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M287.498,306.767c0.745,0,1.502-0.112,2.25-0.347c48.249-15.159,99.256-15.159,147.504,0 c3.952,1.24,8.162-0.956,9.403-4.907c1.241-3.952-0.956-8.162-4.907-9.403c-51.191-16.083-105.306-16.083-156.496,0 c-3.952,1.241-6.149,5.451-4.907,9.403C281.352,304.716,284.309,306.767,287.498,306.767z"
id="path249"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M287.498,274.859c0.745,0,1.502-0.112,2.25-0.347c27.681-8.697,56.409-12.412,85.399-11.037 c4.147,0.192,7.651-2.999,7.847-7.137c0.196-4.138-2.999-7.65-7.137-7.847c-30.753-1.456-61.236,2.483-90.605,11.71 c-3.952,1.242-6.149,5.452-4.907,9.403C281.352,272.81,284.309,274.859,287.498,274.859z"
id="path251"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M441.748,260.202c-10.76-3.38-21.846-6.086-32.952-8.043c-4.08-0.719-7.968,2.006-8.688,6.085 c-0.719,4.079,2.005,7.969,6.085,8.688c10.467,1.844,20.917,4.395,31.058,7.581c0.749,0.235,1.505,0.347,2.25,0.347 c3.189,0,6.147-2.051,7.153-5.254C447.896,265.653,445.7,261.443,441.748,260.202z"
id="path253"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M287.498,242.767c0.745,0,1.502-0.112,2.25-0.347c48.249-15.159,99.256-15.159,147.504,0 c3.952,1.24,8.162-0.956,9.403-4.907c1.241-3.952-0.956-8.162-4.907-9.403c-51.191-16.083-105.306-16.083-156.496,0 c-3.952,1.241-6.149,5.451-4.907,9.403C281.352,240.716,284.309,242.767,287.498,242.767z"
id="path255"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M334.678,185.702c-16.732,1.858-33.362,5.36-49.426,10.407c-3.952,1.241-6.148,5.451-4.907,9.403 c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c15.141-4.757,30.815-8.057,46.585-9.809 c4.117-0.457,7.083-4.165,6.626-8.282S338.79,185.244,334.678,185.702z"
id="path257"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M367.386,199.137c23.725,0.375,47.231,4.17,69.866,11.283c0.748,0.234,1.505,0.347,2.25,0.347 c3.189,0,6.146-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403c-24.015-7.545-48.955-11.572-74.125-11.97 c-4.125-0.078-7.552,3.239-7.618,7.38S363.244,199.072,367.386,199.137z"
id="path259"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M390.671,168.704c4.116,0.46,7.825-2.509,8.282-6.626c0.458-4.117-2.509-7.825-6.626-8.282 c-36.252-4.027-72.278-0.526-107.075,10.406c-3.952,1.242-6.148,5.452-4.907,9.403c1.007,3.204,3.964,5.254,7.153,5.254 c0.745,0,1.502-0.112,2.25-0.347C322.545,168.208,356.5,164.909,390.671,168.704z"
id="path261"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M441.748,164.202c-5.418-1.702-10.96-3.246-16.472-4.588c-4.03-0.98-8.082,1.488-9.062,5.512 c-0.98,4.024,1.488,8.082,5.512,9.062c5.196,1.265,10.419,2.72,15.526,4.324c0.748,0.235,1.505,0.347,2.25,0.347 c3.189,0,6.147-2.051,7.153-5.254C447.896,169.653,445.7,165.443,441.748,164.202z"
id="path263"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M287.498,146.767c0.745,0,1.502-0.112,2.25-0.347c5.103-1.604,10.325-3.058,15.521-4.324 c4.024-0.98,6.492-5.037,5.512-9.062s-5.038-6.492-9.062-5.512c-5.513,1.342-11.053,2.886-16.468,4.587 c-3.951,1.242-6.148,5.452-4.907,9.403C281.352,144.716,284.309,146.767,287.498,146.767z"
id="path265"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M336.329,136.611c34.172-3.796,68.126-0.496,100.923,9.809c0.748,0.234,1.505,0.347,2.25,0.347 c3.189,0,6.146-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403c-34.797-10.933-70.824-14.435-107.076-10.406 c-4.117,0.457-7.083,4.165-6.626,8.282C328.504,134.102,332.21,137.07,336.329,136.611z"
id="path267"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M93.96,317.749c-8.302,1.74-16.615,3.911-24.708,6.454c-3.952,1.242-6.148,5.452-4.907,9.403 c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c7.628-2.396,15.464-4.443,23.288-6.083 c4.054-0.85,6.652-4.825,5.802-8.879S98.011,316.9,93.96,317.749z"
id="path269"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M223.502,338.859c3.189,0,6.147-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403 c-32.073-10.076-65.331-13.842-98.844-11.188c-4.129,0.326-7.211,3.938-6.885,8.068s3.934,7.213,8.068,6.885 c31.591-2.499,62.935,1.048,93.165,10.546C222,338.748,222.757,338.859,223.502,338.859z"
id="path271"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M71.498,306.767c0.745,0,1.502-0.112,2.25-0.347c48.249-15.159,99.256-15.159,147.504,0 c3.952,1.24,8.162-0.956,9.403-4.907c1.241-3.952-0.956-8.162-4.907-9.403c-51.191-16.083-105.307-16.083-156.496,0 c-3.952,1.241-6.149,5.451-4.907,9.403C65.352,304.716,68.309,306.767,71.498,306.767z"
id="path273"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M71.498,274.859c0.745,0,1.502-0.112,2.25-0.347c27.681-8.697,56.411-12.412,85.399-11.037 c4.158,0.192,7.65-2.999,7.847-7.137c0.196-4.138-2.999-7.65-7.137-7.847c-30.756-1.456-61.236,2.483-90.605,11.71 c-3.952,1.242-6.149,5.452-4.907,9.403C65.352,272.81,68.309,274.859,71.498,274.859z"
id="path275"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M190.194,266.932c10.467,1.844,20.917,4.395,31.058,7.581c0.749,0.235,1.505,0.347,2.25,0.347 c3.189,0,6.147-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403c-10.76-3.38-21.846-6.086-32.952-8.043 c-4.079-0.719-7.969,2.006-8.688,6.085C183.39,262.323,186.114,266.213,190.194,266.932z"
id="path277"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M118.678,185.702c-16.732,1.858-33.362,5.36-49.426,10.407c-3.952,1.241-6.148,5.451-4.907,9.403 c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c15.141-4.757,30.815-8.057,46.585-9.809 c4.117-0.457,7.083-4.165,6.626-8.282C126.503,188.212,122.788,185.244,118.678,185.702z"
id="path279"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M64.345,173.605c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347 c32.797-10.305,66.752-13.604,100.923-9.809c4.116,0.46,7.825-2.509,8.282-6.626c0.458-4.117-2.509-7.825-6.626-8.282 c-36.253-4.027-72.278-0.526-107.075,10.406C65.3,165.444,63.104,169.654,64.345,173.605z"
id="path281"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
<path
d="M71.498,146.767c0.745,0,1.502-0.112,2.25-0.347c5.103-1.604,10.325-3.058,15.521-4.324 c4.024-0.98,6.492-5.037,5.512-9.062s-5.038-6.492-9.062-5.512c-5.513,1.342-11.053,2.886-16.468,4.587 c-3.951,1.242-6.148,5.452-4.907,9.403C65.352,144.716,68.309,146.767,71.498,146.767z"
id="path283"
style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
</g>
</svg>
fn main() { use http::handling::{
println!("Hello, world!"); file_handlers::NamedFile,
methods::Method,
request::Request,
response::{Outcome, Response, Status},
routes::{Data, Route},
};
fn static_files_handler(request: Request, _data: Data) -> Outcome<Response, Status, Data> {
let response = static_files(&request.uri.to_string());
let response = match response {
Ok(dat) => Response {
headers: vec![],
cookies: None,
status: Some(Status::Ok),
body: Box::new(dat),
},
Err(_) => return Outcome::Failure(Status::NotFound),
};
Outcome::Success(response)
}
fn static_files(path: &str) -> Result<NamedFile, Status> {
NamedFile::open(("static/".to_string() + path).into())
}
fn index_handler(_request: Request, _data: Data) -> Outcome<Response, Status, Data> {
Outcome::Success(Response {
headers: vec![],
cookies: None,
status: None,
body: Box::new(index()),
})
}
fn index() -> NamedFile {
NamedFile::open("../templates/index.html".into()).unwrap()
}
fn favicon_handler(_request: Request, _data: Data) -> Outcome<Response, Status, Data> {
let response = Response {
headers: vec![],
cookies: None,
status: None,
body: Box::new(NamedFile::open("/assets/favicon.svg".into()).unwrap()),
};
Outcome::Success(response)
}
#[tokio::main]
async fn main() {
let index_route = Route {
format: None,
handler: index_handler,
name: Some("index"),
uri: "".try_into().unwrap(),
method: Method::Get,
rank: 0,
};
let static_route = Route {
format: None,
handler: static_files_handler,
name: Some("static files"),
uri: "<file..>".try_into().unwrap(),
method: Method::Get,
rank: 0,
};
let favicon = Route {
format: None,
handler: favicon_handler,
name: Some("favicon"),
uri: "favicon.ico".try_into().unwrap(),
method: Method::Get,
rank: 0,
};
// http::build("127.0.0.1:8000")
http::build("127.0.0.1:8443", "127.0.0.1:8080")
.await
.mount("/static".try_into().unwrap(), vec![static_route])
.mount("/".try_into().unwrap(), vec![index_route, favicon])
.launch()
.await;
} }
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 511 511" xml:space="preserve">
<g>
<path d="M487.5,128.106H479v-24.5c0-2.905-1.678-5.549-4.307-6.786C405.088,64.066,325.408,63.6,255.5,95.371
C185.592,63.6,105.912,64.067,36.307,96.82C33.678,98.057,32,100.701,32,103.606v24.5h-8.5c-12.958,0-23.5,10.542-23.5,23.5v264
c0,12.958,10.542,23.5,23.5,23.5h464c12.958,0,23.5-10.542,23.5-23.5v-264C511,138.648,500.458,128.106,487.5,128.106z
M263,239.583c0-0.009,0-0.019,0-0.028V108.416c64.137-28.707,136.861-28.707,201,0v27.161c0,0.01-0.001,0.02-0.001,0.029
s0.001,0.02,0.001,0.029v244.438c-32.237-13.461-66.371-20.193-100.5-20.193c-34.129,0-68.264,6.732-100.5,20.193V239.583z
M215,96.391c11.187,3.204,22.217,7.198,33,12.025v117.177l-12.34-8.227c-2.52-1.68-5.801-1.68-8.32,0L215,225.593V96.391z
M47,135.626c0-0.007,0.001-0.013,0.001-0.02S47,135.594,47,135.587v-27.171c48.563-21.736,102.046-26.999,153-15.82v32.856
c-26.767-5.505-54.078-6.777-81.328-3.75c-4.117,0.457-7.083,4.165-6.626,8.282c0.458,4.116,4.162,7.085,8.282,6.626
c26.708-2.967,53.479-1.562,79.671,4.165v48.686c-15.912-3.265-32.14-5.067-48.377-5.323c-4.145-0.078-7.552,3.239-7.618,7.38
c-0.065,4.142,3.239,7.552,7.38,7.618c16.331,0.258,32.654,2.164,48.614,5.647v16.66c-43.389-8.909-88.39-6.644-130.748,6.665
c-3.952,1.241-6.148,5.451-4.907,9.403c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347
c40.908-12.852,84.428-14.773,126.252-5.638v2.825c0,2.766,1.522,5.308,3.961,6.612c2.438,1.306,5.398,1.162,7.699-0.372
l19.84-13.227l16.5,11v136.454c-32.237-13.461-66.371-20.193-100.5-20.193c-34.129,0-68.264,6.732-100.5,20.193V135.626z
M224,424.106H23.5c-4.687,0-8.5-3.813-8.5-8.5v-264c0-4.687,3.813-8.5,8.5-8.5H32v248.5v8c0,4.142,3.358,7.5,7.5,7.5H224V424.106z
M57.29,392.106c58.099-22.934,122.32-22.935,180.42,0H57.29z M272,424.106h-33v-17h33V424.106z M453.71,392.106H273.29
C331.389,369.172,395.61,369.172,453.71,392.106z M496,415.606c0,4.687-3.813,8.5-8.5,8.5H287v-17h184.5c4.142,0,7.5-3.358,7.5-7.5
v-8v-248.5h8.5c4.687,0,8.5,3.813,8.5,8.5V415.606z"/>
<path d="M309.96,317.749c-8.302,1.74-16.615,3.911-24.708,6.454c-3.952,1.242-6.148,5.452-4.907,9.403
c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c7.628-2.396,15.464-4.443,23.288-6.083
c4.054-0.85,6.652-4.825,5.802-8.879C317.989,319.497,314.011,316.9,309.96,317.749z"/>
<path d="M439.502,338.859c3.189,0,6.147-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403
c-32.073-10.076-65.329-13.842-98.844-11.188c-4.129,0.326-7.211,3.938-6.885,8.068s3.935,7.213,8.068,6.885
c31.59-2.499,62.935,1.048,93.165,10.546C438,338.748,438.757,338.859,439.502,338.859z"/>
<path d="M287.498,306.767c0.745,0,1.502-0.112,2.25-0.347c48.249-15.159,99.256-15.159,147.504,0
c3.952,1.24,8.162-0.956,9.403-4.907c1.241-3.952-0.956-8.162-4.907-9.403c-51.191-16.083-105.306-16.083-156.496,0
c-3.952,1.241-6.149,5.451-4.907,9.403C281.352,304.716,284.309,306.767,287.498,306.767z"/>
<path d="M287.498,274.859c0.745,0,1.502-0.112,2.25-0.347c27.681-8.697,56.409-12.412,85.399-11.037
c4.147,0.192,7.651-2.999,7.847-7.137c0.196-4.138-2.999-7.65-7.137-7.847c-30.753-1.456-61.236,2.483-90.605,11.71
c-3.952,1.242-6.149,5.452-4.907,9.403C281.352,272.81,284.309,274.859,287.498,274.859z"/>
<path d="M441.748,260.202c-10.76-3.38-21.846-6.086-32.952-8.043c-4.08-0.719-7.968,2.006-8.688,6.085
c-0.719,4.079,2.005,7.969,6.085,8.688c10.467,1.844,20.917,4.395,31.058,7.581c0.749,0.235,1.505,0.347,2.25,0.347
c3.189,0,6.147-2.051,7.153-5.254C447.896,265.653,445.7,261.443,441.748,260.202z"/>
<path d="M287.498,242.767c0.745,0,1.502-0.112,2.25-0.347c48.249-15.159,99.256-15.159,147.504,0
c3.952,1.24,8.162-0.956,9.403-4.907c1.241-3.952-0.956-8.162-4.907-9.403c-51.191-16.083-105.306-16.083-156.496,0
c-3.952,1.241-6.149,5.451-4.907,9.403C281.352,240.716,284.309,242.767,287.498,242.767z"/>
<path d="M334.678,185.702c-16.732,1.858-33.362,5.36-49.426,10.407c-3.952,1.241-6.148,5.451-4.907,9.403
c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c15.141-4.757,30.815-8.057,46.585-9.809
c4.117-0.457,7.083-4.165,6.626-8.282S338.79,185.244,334.678,185.702z"/>
<path d="M367.386,199.137c23.725,0.375,47.231,4.17,69.866,11.283c0.748,0.234,1.505,0.347,2.25,0.347
c3.189,0,6.146-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403c-24.015-7.545-48.955-11.572-74.125-11.97
c-4.125-0.078-7.552,3.239-7.618,7.38S363.244,199.072,367.386,199.137z"/>
<path d="M390.671,168.704c4.116,0.46,7.825-2.509,8.282-6.626c0.458-4.117-2.509-7.825-6.626-8.282
c-36.252-4.027-72.278-0.526-107.075,10.406c-3.952,1.242-6.148,5.452-4.907,9.403c1.007,3.204,3.964,5.254,7.153,5.254
c0.745,0,1.502-0.112,2.25-0.347C322.545,168.208,356.5,164.909,390.671,168.704z"/>
<path d="M441.748,164.202c-5.418-1.702-10.96-3.246-16.472-4.588c-4.03-0.98-8.082,1.488-9.062,5.512
c-0.98,4.024,1.488,8.082,5.512,9.062c5.196,1.265,10.419,2.72,15.526,4.324c0.748,0.235,1.505,0.347,2.25,0.347
c3.189,0,6.147-2.051,7.153-5.254C447.896,169.653,445.7,165.443,441.748,164.202z"/>
<path d="M287.498,146.767c0.745,0,1.502-0.112,2.25-0.347c5.103-1.604,10.325-3.058,15.521-4.324
c4.024-0.98,6.492-5.037,5.512-9.062s-5.038-6.492-9.062-5.512c-5.513,1.342-11.053,2.886-16.468,4.587
c-3.951,1.242-6.148,5.452-4.907,9.403C281.352,144.716,284.309,146.767,287.498,146.767z"/>
<path d="M336.329,136.611c34.172-3.796,68.126-0.496,100.923,9.809c0.748,0.234,1.505,0.347,2.25,0.347
c3.189,0,6.146-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403c-34.797-10.933-70.824-14.435-107.076-10.406
c-4.117,0.457-7.083,4.165-6.626,8.282C328.504,134.102,332.21,137.07,336.329,136.611z"/>
<path d="M93.96,317.749c-8.302,1.74-16.615,3.911-24.708,6.454c-3.952,1.242-6.148,5.452-4.907,9.403
c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c7.628-2.396,15.464-4.443,23.288-6.083
c4.054-0.85,6.652-4.825,5.802-8.879S98.011,316.9,93.96,317.749z"/>
<path d="M223.502,338.859c3.189,0,6.147-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403
c-32.073-10.076-65.331-13.842-98.844-11.188c-4.129,0.326-7.211,3.938-6.885,8.068s3.934,7.213,8.068,6.885
c31.591-2.499,62.935,1.048,93.165,10.546C222,338.748,222.757,338.859,223.502,338.859z"/>
<path d="M71.498,306.767c0.745,0,1.502-0.112,2.25-0.347c48.249-15.159,99.256-15.159,147.504,0
c3.952,1.24,8.162-0.956,9.403-4.907c1.241-3.952-0.956-8.162-4.907-9.403c-51.191-16.083-105.307-16.083-156.496,0
c-3.952,1.241-6.149,5.451-4.907,9.403C65.352,304.716,68.309,306.767,71.498,306.767z"/>
<path d="M71.498,274.859c0.745,0,1.502-0.112,2.25-0.347c27.681-8.697,56.411-12.412,85.399-11.037
c4.158,0.192,7.65-2.999,7.847-7.137c0.196-4.138-2.999-7.65-7.137-7.847c-30.756-1.456-61.236,2.483-90.605,11.71
c-3.952,1.242-6.149,5.452-4.907,9.403C65.352,272.81,68.309,274.859,71.498,274.859z"/>
<path d="M190.194,266.932c10.467,1.844,20.917,4.395,31.058,7.581c0.749,0.235,1.505,0.347,2.25,0.347
c3.189,0,6.147-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403c-10.76-3.38-21.846-6.086-32.952-8.043
c-4.079-0.719-7.969,2.006-8.688,6.085C183.39,262.323,186.114,266.213,190.194,266.932z"/>
<path d="M118.678,185.702c-16.732,1.858-33.362,5.36-49.426,10.407c-3.952,1.241-6.148,5.451-4.907,9.403
c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c15.141-4.757,30.815-8.057,46.585-9.809
c4.117-0.457,7.083-4.165,6.626-8.282C126.503,188.212,122.788,185.244,118.678,185.702z"/>
<path d="M64.345,173.605c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347
c32.797-10.305,66.752-13.604,100.923-9.809c4.116,0.46,7.825-2.509,8.282-6.626c0.458-4.117-2.509-7.825-6.626-8.282
c-36.253-4.027-72.278-0.526-107.075,10.406C65.3,165.444,63.104,169.654,64.345,173.605z"/>
<path d="M71.498,146.767c0.745,0,1.502-0.112,2.25-0.347c5.103-1.604,10.325-3.058,15.521-4.324
c4.024-0.98,6.492-5.037,5.512-9.062s-5.038-6.492-9.062-5.512c-5.513,1.342-11.053,2.886-16.468,4.587
c-3.951,1.242-6.148,5.452-4.907,9.403C65.352,144.716,68.309,146.767,71.498,146.767z"/>
</g>
</svg>
\ No newline at end of file
body {
background-color: #212121;
color: #ffffff;
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
Oxygen,
Ubuntu,
Cantarell,
"Open Sans",
"Helvetica Neue",
sans-serif;
}