this repo has no description
1pub mod api;
2pub mod auth;
3pub mod cache;
4pub mod circuit_breaker;
5pub mod config;
6pub mod crawlers;
7pub mod image;
8pub mod metrics;
9pub mod notifications;
10pub mod oauth;
11pub mod plc;
12pub mod rate_limit;
13pub mod repo;
14pub mod state;
15pub mod storage;
16pub mod sync;
17pub mod util;
18pub mod validation;
19
20use axum::{
21 Router,
22 middleware,
23 routing::{any, get, post},
24};
25use state::AppState;
26use tower_http::services::{ServeDir, ServeFile};
27
28pub fn app(state: AppState) -> Router {
29 let router = Router::new()
30 .route("/metrics", get(metrics::metrics_handler))
31 .route("/health", get(api::server::health))
32 .route("/xrpc/_health", get(api::server::health))
33 .route("/robots.txt", get(api::server::robots_txt))
34 .route(
35 "/xrpc/com.atproto.server.describeServer",
36 get(api::server::describe_server),
37 )
38 .route(
39 "/xrpc/com.atproto.server.createAccount",
40 post(api::identity::create_account),
41 )
42 .route(
43 "/xrpc/com.atproto.server.createSession",
44 post(api::server::create_session),
45 )
46 .route(
47 "/xrpc/com.atproto.server.getSession",
48 get(api::server::get_session),
49 )
50 .route(
51 "/xrpc/com.atproto.server.deleteSession",
52 post(api::server::delete_session),
53 )
54 .route(
55 "/xrpc/com.atproto.server.refreshSession",
56 post(api::server::refresh_session),
57 )
58 .route(
59 "/xrpc/com.atproto.server.confirmSignup",
60 post(api::server::confirm_signup),
61 )
62 .route(
63 "/xrpc/com.atproto.server.resendVerification",
64 post(api::server::resend_verification),
65 )
66 .route(
67 "/xrpc/com.atproto.server.getServiceAuth",
68 get(api::server::get_service_auth),
69 )
70 .route(
71 "/xrpc/com.atproto.identity.resolveHandle",
72 get(api::identity::resolve_handle),
73 )
74 .route(
75 "/xrpc/com.atproto.repo.createRecord",
76 post(api::repo::create_record),
77 )
78 .route(
79 "/xrpc/com.atproto.repo.putRecord",
80 post(api::repo::put_record),
81 )
82 .route(
83 "/xrpc/com.atproto.repo.getRecord",
84 get(api::repo::get_record),
85 )
86 .route(
87 "/xrpc/com.atproto.repo.deleteRecord",
88 post(api::repo::delete_record),
89 )
90 .route(
91 "/xrpc/com.atproto.repo.listRecords",
92 get(api::repo::list_records),
93 )
94 .route(
95 "/xrpc/com.atproto.repo.describeRepo",
96 get(api::repo::describe_repo),
97 )
98 .route(
99 "/xrpc/com.atproto.repo.uploadBlob",
100 post(api::repo::upload_blob),
101 )
102 .route(
103 "/xrpc/com.atproto.repo.applyWrites",
104 post(api::repo::apply_writes),
105 )
106 .route(
107 "/xrpc/com.atproto.sync.getLatestCommit",
108 get(sync::get_latest_commit),
109 )
110 .route(
111 "/xrpc/com.atproto.sync.listRepos",
112 get(sync::list_repos),
113 )
114 .route(
115 "/xrpc/com.atproto.sync.getBlob",
116 get(sync::get_blob),
117 )
118 .route(
119 "/xrpc/com.atproto.sync.listBlobs",
120 get(sync::list_blobs),
121 )
122 .route(
123 "/xrpc/com.atproto.sync.getRepoStatus",
124 get(sync::get_repo_status),
125 )
126 .route(
127 "/xrpc/com.atproto.server.checkAccountStatus",
128 get(api::server::check_account_status),
129 )
130 .route(
131 "/xrpc/com.atproto.identity.getRecommendedDidCredentials",
132 get(api::identity::get_recommended_did_credentials),
133 )
134 .route(
135 "/xrpc/com.atproto.repo.listMissingBlobs",
136 get(api::repo::list_missing_blobs),
137 )
138 .route(
139 "/xrpc/com.atproto.sync.notifyOfUpdate",
140 post(sync::notify_of_update),
141 )
142 .route(
143 "/xrpc/com.atproto.sync.requestCrawl",
144 post(sync::request_crawl),
145 )
146 .route(
147 "/xrpc/com.atproto.sync.getBlocks",
148 get(sync::get_blocks),
149 )
150 .route(
151 "/xrpc/com.atproto.sync.getRepo",
152 get(sync::get_repo),
153 )
154 .route(
155 "/xrpc/com.atproto.sync.getRecord",
156 get(sync::get_record),
157 )
158 .route(
159 "/xrpc/com.atproto.sync.subscribeRepos",
160 get(sync::subscribe_repos),
161 )
162 .route(
163 "/xrpc/com.atproto.sync.getHead",
164 get(sync::get_head),
165 )
166 .route(
167 "/xrpc/com.atproto.sync.getCheckout",
168 get(sync::get_checkout),
169 )
170 .route(
171 "/xrpc/com.atproto.moderation.createReport",
172 post(api::moderation::create_report),
173 )
174 .route(
175 "/xrpc/com.atproto.admin.getAccountInfo",
176 get(api::admin::get_account_info),
177 )
178 .route(
179 "/xrpc/com.atproto.admin.getAccountInfos",
180 get(api::admin::get_account_infos),
181 )
182 .route(
183 "/xrpc/com.atproto.server.activateAccount",
184 post(api::server::activate_account),
185 )
186 .route(
187 "/xrpc/com.atproto.server.deactivateAccount",
188 post(api::server::deactivate_account),
189 )
190 .route(
191 "/xrpc/com.atproto.server.requestAccountDelete",
192 post(api::server::request_account_delete),
193 )
194 .route(
195 "/xrpc/com.atproto.server.deleteAccount",
196 post(api::server::delete_account),
197 )
198 .route(
199 "/xrpc/com.atproto.server.requestPasswordReset",
200 post(api::server::request_password_reset),
201 )
202 .route(
203 "/xrpc/com.atproto.server.resetPassword",
204 post(api::server::reset_password),
205 )
206 .route(
207 "/xrpc/com.atproto.server.requestEmailUpdate",
208 post(api::server::request_email_update),
209 )
210 .route(
211 "/xrpc/com.atproto.server.confirmEmail",
212 post(api::server::confirm_email),
213 )
214 .route(
215 "/xrpc/com.atproto.server.updateEmail",
216 post(api::server::update_email),
217 )
218 .route(
219 "/xrpc/com.atproto.server.reserveSigningKey",
220 post(api::server::reserve_signing_key),
221 )
222 .route(
223 "/xrpc/com.atproto.identity.updateHandle",
224 post(api::identity::update_handle),
225 )
226 .route(
227 "/xrpc/com.atproto.identity.requestPlcOperationSignature",
228 post(api::identity::request_plc_operation_signature),
229 )
230 .route(
231 "/xrpc/com.atproto.identity.signPlcOperation",
232 post(api::identity::sign_plc_operation),
233 )
234 .route(
235 "/xrpc/com.atproto.identity.submitPlcOperation",
236 post(api::identity::submit_plc_operation),
237 )
238 .route(
239 "/xrpc/com.atproto.repo.importRepo",
240 post(api::repo::import_repo),
241 )
242 .route(
243 "/xrpc/com.atproto.admin.deleteAccount",
244 post(api::admin::delete_account),
245 )
246 .route(
247 "/xrpc/com.atproto.admin.updateAccountEmail",
248 post(api::admin::update_account_email),
249 )
250 .route(
251 "/xrpc/com.atproto.admin.updateAccountHandle",
252 post(api::admin::update_account_handle),
253 )
254 .route(
255 "/xrpc/com.atproto.admin.updateAccountPassword",
256 post(api::admin::update_account_password),
257 )
258 .route(
259 "/xrpc/com.atproto.server.listAppPasswords",
260 get(api::server::list_app_passwords),
261 )
262 .route(
263 "/xrpc/com.atproto.server.createAppPassword",
264 post(api::server::create_app_password),
265 )
266 .route(
267 "/xrpc/com.atproto.server.revokeAppPassword",
268 post(api::server::revoke_app_password),
269 )
270 .route(
271 "/xrpc/com.atproto.server.createInviteCode",
272 post(api::server::create_invite_code),
273 )
274 .route(
275 "/xrpc/com.atproto.server.createInviteCodes",
276 post(api::server::create_invite_codes),
277 )
278 .route(
279 "/xrpc/com.atproto.server.getAccountInviteCodes",
280 get(api::server::get_account_invite_codes),
281 )
282 .route(
283 "/xrpc/com.atproto.admin.getInviteCodes",
284 get(api::admin::get_invite_codes),
285 )
286 .route(
287 "/xrpc/com.atproto.admin.disableAccountInvites",
288 post(api::admin::disable_account_invites),
289 )
290 .route(
291 "/xrpc/com.atproto.admin.enableAccountInvites",
292 post(api::admin::enable_account_invites),
293 )
294 .route(
295 "/xrpc/com.atproto.admin.disableInviteCodes",
296 post(api::admin::disable_invite_codes),
297 )
298 .route(
299 "/xrpc/com.atproto.admin.getSubjectStatus",
300 get(api::admin::get_subject_status),
301 )
302 .route(
303 "/xrpc/com.atproto.admin.updateSubjectStatus",
304 post(api::admin::update_subject_status),
305 )
306 .route(
307 "/xrpc/com.atproto.admin.sendEmail",
308 post(api::admin::send_email),
309 )
310 .route(
311 "/xrpc/app.bsky.actor.getPreferences",
312 get(api::actor::get_preferences),
313 )
314 .route(
315 "/xrpc/app.bsky.actor.putPreferences",
316 post(api::actor::put_preferences),
317 )
318 .route(
319 "/xrpc/app.bsky.actor.getProfile",
320 get(api::actor::get_profile),
321 )
322 .route(
323 "/xrpc/app.bsky.actor.getProfiles",
324 get(api::actor::get_profiles),
325 )
326 .route(
327 "/xrpc/app.bsky.feed.getTimeline",
328 get(api::feed::get_timeline),
329 )
330 .route(
331 "/xrpc/app.bsky.feed.getAuthorFeed",
332 get(api::feed::get_author_feed),
333 )
334 .route(
335 "/xrpc/app.bsky.feed.getActorLikes",
336 get(api::feed::get_actor_likes),
337 )
338 .route(
339 "/xrpc/app.bsky.feed.getPostThread",
340 get(api::feed::get_post_thread),
341 )
342 .route(
343 "/xrpc/app.bsky.feed.getFeed",
344 get(api::feed::get_feed),
345 )
346 .route(
347 "/xrpc/app.bsky.notification.registerPush",
348 post(api::notification::register_push),
349 )
350 .route("/.well-known/did.json", get(api::identity::well_known_did))
351 .route("/u/{handle}/did.json", get(api::identity::user_did_doc))
352 // OAuth 2.1 endpoints
353 .route(
354 "/.well-known/oauth-protected-resource",
355 get(oauth::endpoints::oauth_protected_resource),
356 )
357 .route(
358 "/.well-known/oauth-authorization-server",
359 get(oauth::endpoints::oauth_authorization_server),
360 )
361 .route("/oauth/jwks", get(oauth::endpoints::oauth_jwks))
362 .route(
363 "/oauth/par",
364 post(oauth::endpoints::pushed_authorization_request),
365 )
366 .route("/oauth/authorize", get(oauth::endpoints::authorize_get))
367 .route("/oauth/authorize", post(oauth::endpoints::authorize_post))
368 .route("/oauth/authorize/select", post(oauth::endpoints::authorize_select))
369 .route("/oauth/authorize/2fa", get(oauth::endpoints::authorize_2fa_get))
370 .route("/oauth/authorize/2fa", post(oauth::endpoints::authorize_2fa_post))
371 .route("/oauth/authorize/deny", post(oauth::endpoints::authorize_deny))
372 .route("/oauth/token", post(oauth::endpoints::token_endpoint))
373 .route("/oauth/revoke", post(oauth::endpoints::revoke_token))
374 .route("/oauth/introspect", post(oauth::endpoints::introspect_token))
375 .route(
376 "/xrpc/com.atproto.temp.checkSignupQueue",
377 get(api::temp::check_signup_queue),
378 )
379 .route(
380 "/xrpc/com.bspds.account.getNotificationPrefs",
381 get(api::notification_prefs::get_notification_prefs),
382 )
383 .route(
384 "/xrpc/com.bspds.account.updateNotificationPrefs",
385 post(api::notification_prefs::update_notification_prefs),
386 )
387 .route("/xrpc/{*method}", any(api::proxy::proxy_handler))
388 .layer(middleware::from_fn(metrics::metrics_middleware))
389 .with_state(state);
390
391 let frontend_dir = std::env::var("FRONTEND_DIR")
392 .unwrap_or_else(|_| "./frontend/dist".to_string());
393
394 if std::path::Path::new(&frontend_dir).join("index.html").exists() {
395 let index_path = format!("{}/index.html", frontend_dir);
396 let serve_dir = ServeDir::new(&frontend_dir)
397 .not_found_service(ServeFile::new(index_path));
398 router.fallback_service(serve_dir)
399 } else {
400 router
401 }
402}