webdav: Support empty multistatus responses and simplify error handling.

Currently, the package-internal multistatus writer does not allow to
write empty XML multistatus elements. This conflicts with RFC 4918
(see [1]), and prevents to reuse the writer to implement REPORTs and
other WebDAV extensions. This CL adds support to write empty multi-
status responses. Based on this, it simplifies the error handling of
PROPFIND and PROPPATCH request handling.

[1] http://webdav.org/specs/rfc4918.html#ELEMENT_multistatus

Change-Id: I6ae56ec261ad3a0763b6c197ad1e9c2e30d988a6
Reviewed-on: https://go-review.googlesource.com/9186
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/webdav/webdav.go b/webdav/webdav.go
index 51052fd..897acb2 100644
--- a/webdav/webdav.go
+++ b/webdav/webdav.go
@@ -500,18 +500,15 @@
 		return mw.write(makePropstatResponse(path, pstats))
 	}
 
-	err = walkFS(h.FileSystem, depth, r.URL.Path, fi, walkFn)
-	if mw.enc == nil {
-		if err == nil {
-			err = errEmptyMultistatus
-		}
-		// Not a single response has been written.
-		return http.StatusInternalServerError, err
+	walkErr := walkFS(h.FileSystem, depth, r.URL.Path, fi, walkFn)
+	closeErr := mw.close()
+	if walkErr != nil {
+		return http.StatusInternalServerError, walkErr
 	}
-	if err != nil {
-		return 0, err
+	if closeErr != nil {
+		return http.StatusInternalServerError, closeErr
 	}
-	return 0, mw.close()
+	return 0, nil
 }
 
 func (h *Handler) handleProppatch(w http.ResponseWriter, r *http.Request) (status int, err error) {
@@ -541,7 +538,10 @@
 	if writeErr != nil {
 		return http.StatusInternalServerError, writeErr
 	}
-	return 0, closeErr
+	if closeErr != nil {
+		return http.StatusInternalServerError, closeErr
+	}
+	return 0, nil
 }
 
 // davHeaderNames maps the names of DAV properties to their corresponding
@@ -638,7 +638,6 @@
 var (
 	errDestinationEqualsSource = errors.New("webdav: destination equals source")
 	errDirectoryNotEmpty       = errors.New("webdav: directory not empty")
-	errEmptyMultistatus        = errors.New("webdav: empty multistatus response")
 	errInvalidDepth            = errors.New("webdav: invalid depth")
 	errInvalidDestination      = errors.New("webdav: invalid destination")
 	errInvalidIfHeader         = errors.New("webdav: invalid If header")