fix(drive): answer a runtime unsupported PROPPATCH the way an absent one is
A backend with setProps that rejects unsupported for this path got 501 while a backend without setProps got 403, for the same inability. 403 is the answer kept: WebDAV allows it for a property the server will not store, where 501 says PROPPATCH itself is unimplemented, which is not what the server means. Refs #179 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { Context } from "@webnet/http/server"
|
||||
import type { AsyncVFS } from "@webnet/vfs"
|
||||
import { isUnsupported } from "@webnet/vfs/fallback"
|
||||
import { vfsPathToHref } from "../../common/utils.js"
|
||||
import { parse, parseProppatchBody, buildMultistatusXml, makePropKey } from "../xml.js"
|
||||
import { el, text } from "@webnet/xml"
|
||||
@@ -9,17 +10,25 @@ import type { DAVServerOptions } from "../types.js"
|
||||
const d = (localName: string) => el(DAV_NS, localName)
|
||||
const dt = (localName: string, value: string) => text(DAV_NS, localName, value)
|
||||
|
||||
/**
|
||||
* WebDAV lets a server answer 403 for a property it will not store, and a filesystem with no
|
||||
* property storage is that case for every property. 501 would say PROPPATCH itself is
|
||||
* unimplemented, which is not what the server means, and clients read it as a broken server rather
|
||||
* than a limited one. A backend that has `setProps` but rejects `unsupported` for this path is the
|
||||
* same answer rather than a different one, so both arrive here.
|
||||
*/
|
||||
function cannotStoreProps(ctx: Context): void {
|
||||
ctx.res.setStatus(403, "Forbidden")
|
||||
ctx.res.body = null
|
||||
}
|
||||
|
||||
export async function handleProppatch(
|
||||
ctx: Context,
|
||||
vfs: AsyncVFS,
|
||||
vfsPath: string,
|
||||
opts: DAVServerOptions,
|
||||
): Promise<void> {
|
||||
if (!vfs.setProps) {
|
||||
ctx.res.setStatus(403, "Forbidden")
|
||||
ctx.res.body = null
|
||||
return
|
||||
}
|
||||
if (!vfs.setProps) return cannotStoreProps(ctx)
|
||||
|
||||
const bodyText = await ctx.req.text()
|
||||
const xml = parse(bodyText)
|
||||
@@ -35,7 +44,12 @@ export async function handleProppatch(
|
||||
delete props[makePropKey(ns, localName)]
|
||||
}
|
||||
|
||||
await vfs.setProps(vfsPath, props)
|
||||
try {
|
||||
await vfs.setProps(vfsPath, props)
|
||||
} catch (e) {
|
||||
if (!isUnsupported(e)) throw e
|
||||
return cannotStoreProps(ctx)
|
||||
}
|
||||
|
||||
const href = vfsPathToHref(vfsPath, opts.prefix, ctx.req.url)
|
||||
const allPropEls = [
|
||||
|
||||
Reference in New Issue
Block a user