fix(nc): enable Nextcloud Android app connectivity and uploads

- Add /remote.php/dav discovery endpoint for Android app server detection
- Add /index.php/204 connectivity check endpoint (returns 204 No Content)
- Redirect login flow to nc:// deep link for mobile credential delivery
- Support GET/HEAD on folders (NC clients use as existence checks)
- Recursive MKCOL to create missing parent directories
- Fix single-file PROPFIND returning empty multistatus response
- Strip instance suffix from preview fileId (e.g. "00000326ocnca")
- Add recommendations stub endpoint
This commit is contained in:
Jared Wolff
2026-03-05 20:42:30 -05:00
parent 3fc408d72d
commit d8eecbd9ca
6 changed files with 180 additions and 42 deletions
+28
View File
@@ -40,6 +40,11 @@ pub fn nextcloud_routes_with_state(state: Arc<AppState>) -> Router<Arc<AppState>
// Public routes — no auth required.
let public = Router::new()
.route("/status.php", get(status_handler::handle_status))
// NC connectivity check — app expects 204 to confirm server is reachable.
.route("/index.php/204", get(handle_connectivity_check))
// Bare /remote.php/dav — NC clients probe this to confirm WebDAV is available.
.route("/remote.php/dav", any(handle_dav_discovery))
.route("/remote.php/dav/", any(handle_dav_discovery))
.route(
"/index.php/login/v2",
post(login_v2_handler::handle_login_initiate),
@@ -96,6 +101,10 @@ pub fn nextcloud_routes_with_state(state: Arc<AppState>) -> Router<Arc<AppState>
"/ocs/v2.php/apps/notifications/api/v2/push",
post(ocs_handler::handle_notifications_push),
)
.route(
"/ocs/v2.php/apps/recommendations/api/v1/recommendations",
get(ocs_handler::handle_recommendations),
)
.route(
"/ocs/v2.php/apps/files_sharing/api/v1/sharees",
get(ocs_handler::handle_sharees_search),
@@ -254,3 +263,22 @@ async fn handle_dav_trashbin_root(
.await
.map_err(|e| e.into_response())
}
/// `GET /index.php/204` — NC app connectivity check. Returns 204 No Content.
async fn handle_connectivity_check() -> Response {
Response::builder()
.status(StatusCode::NO_CONTENT)
.body(Body::empty())
.unwrap()
}
/// Bare `/remote.php/dav` — NC clients (especially Android) probe this endpoint
/// during server discovery to confirm WebDAV is available.
async fn handle_dav_discovery() -> Response {
Response::builder()
.status(StatusCode::OK)
.header("DAV", "1, 3")
.header("Allow", "OPTIONS, GET, HEAD, PROPFIND")
.body(Body::empty())
.unwrap()
}