1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use crate::{
    config::CONFIG,
    controller::{
        admin::{admin, admin_gallery, admin_post, admin_view},
        feed::{feed, feed_add, feed_add_post, feed_read, feed_star, feed_subscribe, feed_update},
        inn::{
            comment_delete, comment_downvote, comment_hide, comment_post, comment_upvote,
            edit_post, edit_post_post, inn, inn_feed, inn_join, inn_list, mod_feed_post, mod_inn,
            mod_inn_post, post, post_delete, post_downvote, post_hide, post_lock, post_pin,
            post_upvote, preview, tag,
        },
        message::{inbox, key, key_post, message, message_post},
        meta_handler::{encoding_js, encryption_js, handler_404, home, robots, style},
        notification::notification,
        solo::{solo, solo_delete, solo_like, solo_list, solo_post},
        tantivy::search,
        upload::{gallery, image_delete, upload, upload_pic_post, upload_post},
        user::{
            remove_session, reset, reset_post, role_post, signin, signin_post, signout, signup,
            signup_post, user, user_follow, user_list, user_password_post, user_recovery_code,
            user_setting, user_setting_post,
        },
    },
};
use axum::{
    error_handling::HandleErrorLayer, extract::DefaultBodyLimit, handler::Handler,
    http::StatusCode, routing::get, BoxError, Router,
};
use std::time::Duration;
use tower::{timeout::TimeoutLayer, ServiceBuilder};
use tower_http::{
    compression::CompressionLayer,
    services::ServeDir,
    trace::{DefaultMakeSpan, TraceLayer},
};
use tracing::Level;

const UPLOAD_LIMIT: usize = 20 * 1024 * 1024;

pub async fn router() -> Router {
    let middleware_stack = ServiceBuilder::new()
        .layer(HandleErrorLayer::new(|_: BoxError| async {
            StatusCode::REQUEST_TIMEOUT
        }))
        .layer(TimeoutLayer::new(Duration::from_secs(10)))
        .layer(CompressionLayer::new())
        .layer(
            TraceLayer::new_for_http().make_span_with(DefaultMakeSpan::new().level(Level::INFO)),
        );

    let router_db = Router::new()
        .route("/", get(home))
        .route("/signup", get(signup).post(signup_post))
        .route("/signin", get(signin).post(signin_post))
        .route("/signout", get(signout))
        .route("/user/:u", get(user))
        .route("/user/:u/follow", get(user_follow))
        .route("/user/setting", get(user_setting).post(user_setting_post))
        .route("/user/avatar", get(user_setting).post(upload_pic_post))
        .route("/user/password", get(user_setting).post(user_password_post))
        .route("/user/recovery", get(user_setting).post(user_recovery_code))
        .route("/user/reset", get(reset).post(reset_post))
        .route("/user/list", get(user_list))
        .route("/user/remove/:session_id", get(remove_session))
        .route("/role/:id/:uid", get(user_list).post(role_post))
        .route("/notification", get(notification))
        .route("/admin", get(admin).post(admin_post))
        .route("/admin/view", get(admin_view))
        .route("/admin/gallery", get(admin_gallery))
        .route("/image/delete/:uid/:img_id", get(image_delete))
        .route("/mod/:iid", get(mod_inn).post(mod_inn_post))
        .route("/mod/feed/:iid", get(mod_inn).post(mod_feed_post))
        .route(
            "/mod/inn_icon",
            get(mod_inn).post(upload_pic_post.layer(DefaultBodyLimit::max(UPLOAD_LIMIT))),
        )
        .route("/mod/:iid/:pid/lock", get(post_lock))
        .route("/mod/:iid/:pid/hide", get(post_hide))
        .route("/mod/:iid/:pid/pin", get(post_pin))
        .route("/inn/list", get(inn_list))
        .route("/inn/tag/:tag", get(tag))
        .route("/inn/:i", get(inn))
        .route("/inn/:i/join", get(inn_join))
        .route("/inn/:i/atom.xml", get(inn_feed))
        .route("/post/:iid/:pid", get(post).post(comment_post))
        .route("/post/:iid/:pid/:cid/delete", get(comment_delete))
        .route("/post/:iid/:pid/:cid/hide", get(comment_hide))
        .route("/post/edit/:pid", get(edit_post).post(edit_post_post))
        .route("/post/:iid/:pid/upvote", get(post_upvote))
        .route("/post/:iid/:pid/downvote", get(post_downvote))
        .route("/post/:iid/:pid/delete", get(post_delete))
        .route("/post/:iid/:pid/:cid/upvote", get(comment_upvote))
        .route("/post/:iid/:pid/:cid/downvote", get(comment_downvote))
        .route("/preview", get(post).post(preview))
        .route("/solo/user/:u", get(solo_list).post(solo_post))
        .route("/solo/:sid/like", get(solo_like))
        .route("/solo/:sid/delete", get(solo_delete))
        .route("/solo/:sid", get(solo))
        .route(
            "/upload",
            get(upload).post(upload_post.layer(DefaultBodyLimit::max(UPLOAD_LIMIT))),
        )
        .route("/gallery/:uid", get(gallery))
        .route("/feed/:uid", get(feed))
        .route("/feed/add", get(feed_add).post(feed_add_post))
        .route("/feed/update", get(feed_update))
        .route("/feed/star/:item_id", get(feed_star))
        .route("/feed/subscribe/:uid/:item_id", get(feed_subscribe))
        .route("/feed/read/:item_id", get(feed_read))
        .route("/search", get(search))
        .route("/message/:uid", get(message).post(message_post))
        .route("/key", get(key).post(key_post))
        .route("/inbox/:mid", get(inbox));

    let router_static = Router::new()
        .route("/static/style.css", get(style))
        .route("/robots.txt", get(robots))
        .route("/static/js/encryption-helper.js", get(encryption_js))
        .route("/static/js/encoding-helper.js", get(encoding_js))
        .nest_service("/static/avatars", ServeDir::new(&CONFIG.avatars_path))
        .nest_service("/static/inn_icons", ServeDir::new(&CONFIG.inn_icons_path))
        .nest_service("/static/upload", ServeDir::new(&CONFIG.upload_path));

    let app = router_static.merge(router_db);
    app.layer(middleware_stack).fallback(handler_404)
}