12483: Fix multiple WriteHeader(). Skip updates on readonly methods.
authorTom Clegg <tclegg@veritasgenetics.com>
Wed, 22 Nov 2017 17:32:38 +0000 (12:32 -0500)
committerTom Clegg <tclegg@veritasgenetics.com>
Wed, 22 Nov 2017 17:45:00 +0000 (12:45 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

services/keep-web/handler.go

index a30d40d217132127a3b62b0eaf0bfbbd6216b9fc..576ecdb86f73cb3732e0bf088d953590c69f9f8f 100644 (file)
@@ -6,7 +6,6 @@ package main
 
 import (
        "encoding/json"
 
 import (
        "encoding/json"
-       "errors"
        "fmt"
        "html"
        "html/template"
        "fmt"
        "html"
        "html/template"
@@ -101,19 +100,17 @@ func (h *handler) serveStatus(w http.ResponseWriter, r *http.Request) {
 // sends an HTTP header indicating success, updateOnSuccess first
 // calls the provided update func. If the update func fails, a 500
 // response is sent, and the status code and body sent by the handler
 // sends an HTTP header indicating success, updateOnSuccess first
 // calls the provided update func. If the update func fails, a 500
 // response is sent, and the status code and body sent by the handler
-// are ignored (all response writes return errors).
+// are ignored (all response writes return the update error).
 type updateOnSuccess struct {
        httpserver.ResponseWriter
        update     func() error
        sentHeader bool
 type updateOnSuccess struct {
        httpserver.ResponseWriter
        update     func() error
        sentHeader bool
-       dropBody   bool
+       err        error
 }
 
 }
 
-var errUpdateFailed = errors.New("update failed")
-
 func (uos *updateOnSuccess) Write(p []byte) (int, error) {
 func (uos *updateOnSuccess) Write(p []byte) (int, error) {
-       if uos.dropBody {
-               return 0, errUpdateFailed
+       if uos.err != nil {
+               return 0, uos.err
        }
        if !uos.sentHeader {
                uos.WriteHeader(http.StatusOK)
        }
        if !uos.sentHeader {
                uos.WriteHeader(http.StatusOK)
@@ -123,19 +120,25 @@ func (uos *updateOnSuccess) Write(p []byte) (int, error) {
 
 func (uos *updateOnSuccess) WriteHeader(code int) {
        if !uos.sentHeader {
 
 func (uos *updateOnSuccess) WriteHeader(code int) {
        if !uos.sentHeader {
+               uos.sentHeader = true
                if code >= 200 && code < 400 {
                if code >= 200 && code < 400 {
-                       if err := uos.update(); err != nil {
-                               http.Error(uos.ResponseWriter, err.Error(), http.StatusInternalServerError)
-                               uos.dropBody = true
+                       if uos.err = uos.update(); uos.err != nil {
+                               http.Error(uos.ResponseWriter, uos.err.Error(), http.StatusInternalServerError)
                                return
                        }
                }
                                return
                        }
                }
-               uos.sentHeader = true
        }
        uos.ResponseWriter.WriteHeader(code)
 }
 
 var (
        }
        uos.ResponseWriter.WriteHeader(code)
 }
 
 var (
+       writeMethod = map[string]bool{
+               "DELETE": true,
+               "MKCOL":  true,
+               "MOVE":   true,
+               "PUT":    true,
+               "RMCOL":  true,
+       }
        webdavMethod = map[string]bool{
                "DELETE":   true,
                "MKCOL":    true,
        webdavMethod = map[string]bool{
                "DELETE":   true,
                "MKCOL":    true,
@@ -407,7 +410,7 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                return
        }
        if webdavMethod[r.Method] {
                return
        }
        if webdavMethod[r.Method] {
-               writing := !arvadosclient.PDHMatch(targetID)
+               writing := !arvadosclient.PDHMatch(targetID) && writeMethod[r.Method]
                if writing {
                        // Save the collection only if/when all
                        // webdav->filesystem operations succeed --
                if writing {
                        // Save the collection only if/when all
                        // webdav->filesystem operations succeed --