mirror of
https://github.com/cupcakearmy/cryptgeon.git
synced 2024-12-22 08:16:28 +00:00
refactor to use axum
This commit is contained in:
parent
a45f6a3772
commit
c2b81bc04d
953
packages/backend/Cargo.lock
generated
953
packages/backend/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -10,16 +10,18 @@ name = "cryptgeon"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "4"
|
# Core
|
||||||
actix-files = "0.6"
|
axum = "0.7.5"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0.208", features = ["derive"] }
|
||||||
|
tokio = { version = "1.39.3", features = ["full"] }
|
||||||
|
tower = "0.5.0"
|
||||||
|
tower-http = { version = "0.5.2", features = ["full"] }
|
||||||
|
redis = { version = "0.25.2", features = ["tls-native-tls"] }
|
||||||
|
|
||||||
|
# Utility
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
ring = "0.16"
|
ring = "0.16"
|
||||||
bs62 = "0.1"
|
bs62 = "0.1"
|
||||||
byte-unit = "4"
|
byte-unit = "4"
|
||||||
dotenv = "0.15"
|
dotenv = "0.15"
|
||||||
mime = "0.3"
|
|
||||||
env_logger = "0.9"
|
|
||||||
log = "0.4"
|
|
||||||
redis = { version = "0.25.2", features = ["tls-native-tls"] }
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "cargo watch -x 'run --bin cryptgeon'",
|
"dev": "cargo watch -x 'run --bin cryptgeon'",
|
||||||
"build": "cargo build --release",
|
"build": "cargo build --release",
|
||||||
"test:server": "SIZE_LIMIT=10MiB LISTEN_ADDR=0.0.0.0:1234 cargo run",
|
"test:server": "SIZE_LIMIT=10MiB LISTEN_ADDR=0.0.0.0:3000 cargo run",
|
||||||
"test:prepare": "cargo build"
|
"test:prepare": "cargo build"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
use actix_web::web;
|
|
||||||
|
|
||||||
use crate::health;
|
|
||||||
use crate::note;
|
|
||||||
use crate::status;
|
|
||||||
|
|
||||||
pub fn init(cfg: &mut web::ServiceConfig) {
|
|
||||||
cfg.service(
|
|
||||||
web::scope("/api")
|
|
||||||
.service(note::init())
|
|
||||||
.service(status::init())
|
|
||||||
.service(health::init()),
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
use actix_files::{Files, NamedFile};
|
|
||||||
use actix_web::{web, Result};
|
|
||||||
|
|
||||||
use crate::config;
|
|
||||||
|
|
||||||
pub fn init(cfg: &mut web::ServiceConfig) {
|
|
||||||
cfg.service(
|
|
||||||
Files::new("/", config::FRONTEND_PATH.to_string())
|
|
||||||
.index_file("index.html")
|
|
||||||
.use_etag(true),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn index() -> Result<NamedFile> {
|
|
||||||
let index = format!("{}{}", config::FRONTEND_PATH.to_string(), "/index.html");
|
|
||||||
Ok(NamedFile::open(index)?)
|
|
||||||
}
|
|
@ -1,3 +1,10 @@
|
|||||||
mod routes;
|
use crate::store;
|
||||||
|
use axum::http::StatusCode;
|
||||||
|
|
||||||
pub use routes::*;
|
pub async fn report_health() -> (StatusCode,) {
|
||||||
|
if store::can_reach_redis() {
|
||||||
|
return (StatusCode::OK,);
|
||||||
|
} else {
|
||||||
|
return (StatusCode::SERVICE_UNAVAILABLE,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
use actix_web::{get, web, HttpResponse, Responder, Scope};
|
|
||||||
|
|
||||||
use crate::store;
|
|
||||||
|
|
||||||
#[get("/")]
|
|
||||||
async fn get_live() -> impl Responder {
|
|
||||||
if store::can_reach_redis() {
|
|
||||||
return HttpResponse::Ok();
|
|
||||||
} else {
|
|
||||||
return HttpResponse::ServiceUnavailable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init() -> Scope {
|
|
||||||
web::scope("/live").service(get_live)
|
|
||||||
}
|
|
@ -1,44 +1,70 @@
|
|||||||
use actix_web::{
|
use axum::{
|
||||||
middleware::{self, Logger},
|
extract::Request,
|
||||||
web::{self},
|
routing::{delete, get, post},
|
||||||
App, HttpServer,
|
Router, ServiceExt,
|
||||||
};
|
};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use log::error;
|
use tower::Layer;
|
||||||
|
use tower_http::{
|
||||||
|
compression::CompressionLayer,
|
||||||
|
limit::RequestBodyLimitLayer,
|
||||||
|
normalize_path::NormalizePathLayer,
|
||||||
|
services::{ServeDir, ServeFile},
|
||||||
|
};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
mod api;
|
|
||||||
mod client;
|
|
||||||
mod config;
|
mod config;
|
||||||
mod health;
|
mod health;
|
||||||
mod note;
|
mod note;
|
||||||
mod size;
|
|
||||||
mod status;
|
mod status;
|
||||||
mod store;
|
mod store;
|
||||||
|
|
||||||
#[actix_web::main]
|
#[tokio::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() {
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or(config::VERBOSITY.as_str()));
|
|
||||||
|
|
||||||
if !store::can_reach_redis() {
|
if !store::can_reach_redis() {
|
||||||
error!("cannot reach redis");
|
println!("cannot reach redis");
|
||||||
panic!("canont reach redis");
|
panic!("canont reach redis");
|
||||||
}
|
}
|
||||||
|
|
||||||
return HttpServer::new(|| {
|
let notes_routes = Router::new()
|
||||||
App::new()
|
.route("/", post(note::create))
|
||||||
.wrap(Logger::new("\"%r\" %s %b %T"))
|
.route("/:id", delete(note::delete))
|
||||||
.wrap(middleware::Compress::default())
|
.route("/:id", get(note::preview));
|
||||||
.wrap(middleware::DefaultHeaders::default())
|
let health_routes = Router::new().route("/live", get(health::report_health));
|
||||||
.configure(size::init)
|
let status_routes = Router::new().route("/status", get(status::get_status));
|
||||||
.configure(api::init)
|
let api_routes = Router::new()
|
||||||
.configure(client::init)
|
.nest("/notes", notes_routes)
|
||||||
.default_service(web::to(client::index))
|
.nest("/", health_routes)
|
||||||
})
|
.nest("/", status_routes);
|
||||||
.bind(config::LISTEN_ADDR.to_string())?
|
|
||||||
.run()
|
let index = format!("{}{}", config::FRONTEND_PATH.to_string(), "/index.html");
|
||||||
.await;
|
let serve_dir =
|
||||||
|
ServeDir::new(config::FRONTEND_PATH.to_string()).not_found_service(ServeFile::new(index));
|
||||||
|
let app = Router::new()
|
||||||
|
.nest("/api", api_routes)
|
||||||
|
.fallback_service(serve_dir)
|
||||||
|
.layer(
|
||||||
|
CompressionLayer::new()
|
||||||
|
.br(true)
|
||||||
|
.deflate(true)
|
||||||
|
.gzip(true)
|
||||||
|
.zstd(true),
|
||||||
|
)
|
||||||
|
.layer(RequestBodyLimitLayer::new(*config::LIMIT));
|
||||||
|
|
||||||
|
let app = NormalizePathLayer::trim_trailing_slash().layer(app);
|
||||||
|
|
||||||
|
let listener = tokio::net::TcpListener::bind(config::LISTEN_ADDR.to_string())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
println!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
println!("Config {}", *config::LIMIT);
|
||||||
|
axum::serve(listener, ServiceExt::<Request>::into_make_service(app))
|
||||||
|
// axum::serve(listener, app)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,12 @@ pub struct Note {
|
|||||||
pub expiration: Option<u32>,
|
pub expiration: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize)]
|
||||||
pub struct NoteInfo {
|
pub struct NoteInfo {
|
||||||
pub meta: String,
|
pub meta: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize)]
|
||||||
pub struct NotePublic {
|
pub struct NotePublic {
|
||||||
pub meta: String,
|
pub meta: String,
|
||||||
pub contents: String,
|
pub contents: String,
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
use actix_web::{delete, get, post, web, HttpResponse, Responder, Scope};
|
use axum::extract::Path;
|
||||||
|
use axum::http::StatusCode;
|
||||||
|
use axum::response::{IntoResponse, Response};
|
||||||
|
use axum::Json;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::note::{generate_id, Note, NoteInfo, NotePublic};
|
use crate::note::{generate_id, Note, NoteInfo};
|
||||||
use crate::store;
|
use crate::store;
|
||||||
|
|
||||||
|
use super::NotePublic;
|
||||||
|
|
||||||
pub fn now() -> u32 {
|
pub fn now() -> u32 {
|
||||||
SystemTime::now()
|
SystemTime::now()
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
@ -13,20 +18,18 @@ pub fn now() -> u32 {
|
|||||||
.as_secs() as u32
|
.as_secs() as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct NotePath {
|
pub struct OneNoteParams {
|
||||||
id: String,
|
id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/{id}")]
|
pub async fn preview(Path(OneNoteParams { id }): Path<OneNoteParams>) -> Response {
|
||||||
async fn one(path: web::Path<NotePath>) -> impl Responder {
|
let note = store::get(&id);
|
||||||
let p = path.into_inner();
|
|
||||||
let note = store::get(&p.id);
|
|
||||||
|
|
||||||
match note {
|
match note {
|
||||||
Ok(Some(n)) => HttpResponse::Ok().json(NoteInfo { meta: n.meta }),
|
Ok(Some(n)) => (StatusCode::OK, Json(NoteInfo { meta: n.meta })).into_response(),
|
||||||
Ok(None) => HttpResponse::NotFound().finish(),
|
Ok(None) => (StatusCode::NOT_FOUND).into_response(),
|
||||||
Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
|
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,13 +38,16 @@ struct CreateResponse {
|
|||||||
id: String,
|
id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/")]
|
pub async fn create(Json(mut n): Json<Note>) -> Response {
|
||||||
async fn create(note: web::Json<Note>) -> impl Responder {
|
// let mut n = note.into_inner();
|
||||||
let mut n = note.into_inner();
|
|
||||||
let id = generate_id();
|
let id = generate_id();
|
||||||
let bad_req = HttpResponse::BadRequest().finish();
|
// let bad_req = HttpResponse::BadRequest().finish();
|
||||||
if n.views == None && n.expiration == None {
|
if n.views == None && n.expiration == None {
|
||||||
return bad_req;
|
return (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
"At least views or expiration must be set",
|
||||||
|
)
|
||||||
|
.into_response();
|
||||||
}
|
}
|
||||||
if !*config::ALLOW_ADVANCED {
|
if !*config::ALLOW_ADVANCED {
|
||||||
n.views = Some(1);
|
n.views = Some(1);
|
||||||
@ -50,7 +56,7 @@ async fn create(note: web::Json<Note>) -> impl Responder {
|
|||||||
match n.views {
|
match n.views {
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
if v > *config::MAX_VIEWS || v < 1 {
|
if v > *config::MAX_VIEWS || v < 1 {
|
||||||
return bad_req;
|
return (StatusCode::BAD_REQUEST, "Invalid views").into_response();
|
||||||
}
|
}
|
||||||
n.expiration = None; // views overrides expiration
|
n.expiration = None; // views overrides expiration
|
||||||
}
|
}
|
||||||
@ -58,8 +64,8 @@ async fn create(note: web::Json<Note>) -> impl Responder {
|
|||||||
}
|
}
|
||||||
match n.expiration {
|
match n.expiration {
|
||||||
Some(e) => {
|
Some(e) => {
|
||||||
if e > *config::MAX_EXPIRATION {
|
if e > *config::MAX_EXPIRATION || e < 1 {
|
||||||
return bad_req;
|
return (StatusCode::BAD_REQUEST, "Invalid expiration").into_response();
|
||||||
}
|
}
|
||||||
let expiration = now() + (e * 60);
|
let expiration = now() + (e * 60);
|
||||||
n.expiration = Some(expiration);
|
n.expiration = Some(expiration);
|
||||||
@ -67,38 +73,40 @@ async fn create(note: web::Json<Note>) -> impl Responder {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
match store::set(&id.clone(), &n.clone()) {
|
match store::set(&id.clone(), &n.clone()) {
|
||||||
Ok(_) => return HttpResponse::Ok().json(CreateResponse { id: id }),
|
Ok(_) => (StatusCode::OK, Json(CreateResponse { id })).into_response(),
|
||||||
Err(e) => return HttpResponse::InternalServerError().body(e.to_string()),
|
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[delete("/{id}")]
|
pub async fn delete(Path(OneNoteParams { id }): Path<OneNoteParams>) -> Response {
|
||||||
async fn delete(path: web::Path<NotePath>) -> impl Responder {
|
let note = store::get(&id);
|
||||||
let p = path.into_inner();
|
|
||||||
let note = store::get(&p.id);
|
|
||||||
match note {
|
match note {
|
||||||
Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
|
// Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
|
||||||
Ok(None) => return HttpResponse::NotFound().finish(),
|
// Ok(None) => return HttpResponse::NotFound().finish(),
|
||||||
|
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
|
||||||
|
Ok(None) => (StatusCode::NOT_FOUND).into_response(),
|
||||||
Ok(Some(note)) => {
|
Ok(Some(note)) => {
|
||||||
let mut changed = note.clone();
|
let mut changed = note.clone();
|
||||||
if changed.views == None && changed.expiration == None {
|
if changed.views == None && changed.expiration == None {
|
||||||
return HttpResponse::BadRequest().finish();
|
return (StatusCode::BAD_REQUEST).into_response();
|
||||||
}
|
}
|
||||||
match changed.views {
|
match changed.views {
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
changed.views = Some(v - 1);
|
changed.views = Some(v - 1);
|
||||||
let id = p.id.clone();
|
let id = id.clone();
|
||||||
if v <= 1 {
|
if v <= 1 {
|
||||||
match store::del(&id) {
|
match store::del(&id) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return HttpResponse::InternalServerError().body(e.to_string())
|
return (StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
|
||||||
|
.into_response();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match store::set(&id, &changed.clone()) {
|
match store::set(&id, &changed.clone()) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return HttpResponse::InternalServerError().body(e.to_string())
|
return (StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
|
||||||
|
.into_response();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -111,33 +119,26 @@ async fn delete(path: web::Path<NotePath>) -> impl Responder {
|
|||||||
match changed.expiration {
|
match changed.expiration {
|
||||||
Some(e) => {
|
Some(e) => {
|
||||||
if e < n {
|
if e < n {
|
||||||
match store::del(&p.id.clone()) {
|
match store::del(&id.clone()) {
|
||||||
Ok(_) => return HttpResponse::BadRequest().finish(),
|
Ok(_) => return (StatusCode::BAD_REQUEST).into_response(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return HttpResponse::InternalServerError().body(e.to_string())
|
return (StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
|
||||||
|
.into_response()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
return HttpResponse::Ok().json(NotePublic {
|
|
||||||
contents: changed.contents,
|
return (
|
||||||
meta: changed.meta,
|
StatusCode::OK,
|
||||||
});
|
Json(NotePublic {
|
||||||
|
contents: changed.contents,
|
||||||
|
meta: changed.meta,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.into_response();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct Status {
|
|
||||||
version: String,
|
|
||||||
max_size: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init() -> Scope {
|
|
||||||
web::scope("/notes")
|
|
||||||
.service(one)
|
|
||||||
.service(create)
|
|
||||||
.service(delete)
|
|
||||||
}
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
use crate::config;
|
|
||||||
use actix_web::web;
|
|
||||||
use mime;
|
|
||||||
|
|
||||||
pub fn init(cfg: &mut web::ServiceConfig) {
|
|
||||||
let json = web::JsonConfig::default().limit(*config::LIMIT);
|
|
||||||
let plain = web::PayloadConfig::default()
|
|
||||||
.limit(*config::LIMIT)
|
|
||||||
.mimetype(mime::STAR_STAR);
|
|
||||||
// cfg.app_data(plain);
|
|
||||||
cfg.app_data(json).app_data(plain);
|
|
||||||
}
|
|
@ -1,5 +1,40 @@
|
|||||||
mod model;
|
use crate::config;
|
||||||
mod routes;
|
use axum::http::StatusCode;
|
||||||
|
use axum::Json;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
pub use model::*;
|
#[derive(Serialize)]
|
||||||
pub use routes::*;
|
pub struct Status {
|
||||||
|
// General
|
||||||
|
pub version: String,
|
||||||
|
// Config
|
||||||
|
pub max_size: u32,
|
||||||
|
pub max_views: u32,
|
||||||
|
pub max_expiration: u32,
|
||||||
|
pub allow_advanced: bool,
|
||||||
|
pub allow_files: bool,
|
||||||
|
pub theme_new_note_notice: bool,
|
||||||
|
// Theme
|
||||||
|
pub theme_image: String,
|
||||||
|
pub theme_text: String,
|
||||||
|
pub theme_page_title: String,
|
||||||
|
pub theme_favicon: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_status() -> (StatusCode, Json<Status>) {
|
||||||
|
let status = Status {
|
||||||
|
version: config::VERSION.to_string(),
|
||||||
|
max_size: *config::LIMIT as u32,
|
||||||
|
max_views: *config::MAX_VIEWS,
|
||||||
|
max_expiration: *config::MAX_EXPIRATION,
|
||||||
|
allow_advanced: *config::ALLOW_ADVANCED,
|
||||||
|
allow_files: *config::ALLOW_FILES,
|
||||||
|
theme_new_note_notice: *config::THEME_NEW_NOTE_NOTICE,
|
||||||
|
theme_image: config::THEME_IMAGE.to_string(),
|
||||||
|
theme_text: config::THEME_TEXT.to_string(),
|
||||||
|
theme_page_title: config::THEME_PAGE_TITLE.to_string(),
|
||||||
|
theme_favicon: config::THEME_FAVICON.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
(StatusCode::OK, Json(status))
|
||||||
|
}
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Status {
|
|
||||||
// General
|
|
||||||
pub version: String,
|
|
||||||
// Config
|
|
||||||
pub max_size: u32,
|
|
||||||
pub max_views: u32,
|
|
||||||
pub max_expiration: u32,
|
|
||||||
pub allow_advanced: bool,
|
|
||||||
pub allow_files: bool,
|
|
||||||
pub theme_new_note_notice: bool,
|
|
||||||
// Theme
|
|
||||||
pub theme_image: String,
|
|
||||||
pub theme_text: String,
|
|
||||||
pub theme_page_title: String,
|
|
||||||
pub theme_favicon: String,
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
use actix_web::{get, web, HttpResponse, Responder, Scope};
|
|
||||||
|
|
||||||
use crate::config;
|
|
||||||
use crate::status::Status;
|
|
||||||
|
|
||||||
#[get("/")]
|
|
||||||
async fn get_status() -> impl Responder {
|
|
||||||
return HttpResponse::Ok().json(Status {
|
|
||||||
version: config::VERSION.to_string(),
|
|
||||||
max_size: *config::LIMIT as u32,
|
|
||||||
max_views: *config::MAX_VIEWS,
|
|
||||||
max_expiration: *config::MAX_EXPIRATION,
|
|
||||||
allow_advanced: *config::ALLOW_ADVANCED,
|
|
||||||
allow_files: *config::ALLOW_FILES,
|
|
||||||
theme_new_note_notice: *config::THEME_NEW_NOTE_NOTICE,
|
|
||||||
theme_image: config::THEME_IMAGE.to_string(),
|
|
||||||
theme_text: config::THEME_TEXT.to_string(),
|
|
||||||
theme_page_title: config::THEME_PAGE_TITLE.to_string(),
|
|
||||||
theme_favicon: config::THEME_FAVICON.to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init() -> Scope {
|
|
||||||
web::scope("/status").service(get_status)
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user