github.com/cs3org/reva/v2@v2.27.7/internal/http/services/owncloud/ocdav/webdav.go (about)

     1  // Copyright 2018-2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package ocdav
    20  
    21  import (
    22  	"fmt"
    23  	"net/http"
    24  	"path"
    25  
    26  	"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/errors"
    27  	"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind"
    28  	"github.com/cs3org/reva/v2/pkg/appctx"
    29  )
    30  
    31  // Common Webdav methods.
    32  //
    33  // Unless otherwise noted, these are defined in RFC 4918 section 9.
    34  const (
    35  	MethodPropfind  = "PROPFIND"
    36  	MethodLock      = "LOCK"
    37  	MethodUnlock    = "UNLOCK"
    38  	MethodProppatch = "PROPPATCH"
    39  	MethodMkcol     = "MKCOL"
    40  	MethodMove      = "MOVE"
    41  	MethodCopy      = "COPY"
    42  	MethodReport    = "REPORT"
    43  )
    44  
    45  // WebDavHandler implements a dav endpoint
    46  type WebDavHandler struct {
    47  	namespace         string
    48  	useLoggedInUserNS bool
    49  }
    50  
    51  func (h *WebDavHandler) init(ns string, useLoggedInUserNS bool) error {
    52  	h.namespace = path.Join("/", ns)
    53  	h.useLoggedInUserNS = useLoggedInUserNS
    54  	return nil
    55  }
    56  
    57  // Handler handles requests
    58  func (h *WebDavHandler) Handler(s *svc) http.Handler {
    59  	config := s.Config()
    60  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    61  		ns, newPath, err := s.ApplyLayout(r.Context(), h.namespace, h.useLoggedInUserNS, r.URL.Path)
    62  		if err != nil {
    63  			w.WriteHeader(http.StatusNotFound)
    64  			b, err := errors.Marshal(http.StatusNotFound, fmt.Sprintf("could not get storage for %s", r.URL.Path), "", "")
    65  			errors.HandleWebdavError(appctx.GetLogger(r.Context()), w, b, err)
    66  			return
    67  		}
    68  		r.URL.Path = newPath
    69  
    70  		// TODO initialize status with http.StatusBadRequest
    71  		// TODO initialize err with errors.ErrUnsupportedMethod
    72  		var status int // status 0 means the handler already sent the response
    73  		switch r.Method {
    74  		case MethodPropfind:
    75  			p := propfind.NewHandler(config.PublicURL, s.gatewaySelector, config)
    76  			p.HandlePathPropfind(w, r, ns)
    77  		case MethodLock:
    78  			status, err = s.handleLock(w, r, ns)
    79  		case MethodUnlock:
    80  			status, err = s.handleUnlock(w, r, ns)
    81  		case MethodProppatch:
    82  			status, err = s.handlePathProppatch(w, r, ns)
    83  		case MethodMkcol:
    84  			status, err = s.handlePathMkcol(w, r, ns)
    85  		case MethodMove:
    86  			s.handlePathMove(w, r, ns)
    87  		case MethodCopy:
    88  			s.handlePathCopy(w, r, ns)
    89  		case MethodReport:
    90  			s.handleReport(w, r, ns)
    91  		case http.MethodGet:
    92  			s.handlePathGet(w, r, ns)
    93  		case http.MethodPut:
    94  			s.handlePathPut(w, r, ns)
    95  		case http.MethodPost:
    96  			s.handlePathTusPost(w, r, ns)
    97  		case http.MethodOptions:
    98  			s.handleOptions(w, r)
    99  		case http.MethodHead:
   100  			s.handlePathHead(w, r, ns)
   101  		case http.MethodDelete:
   102  			status, err = s.handlePathDelete(w, r, ns)
   103  		default:
   104  			w.WriteHeader(http.StatusNotFound)
   105  		}
   106  
   107  		if status != 0 { // 0 means the handler already sent the response
   108  			w.WriteHeader(status)
   109  			if status != http.StatusNoContent {
   110  				var b []byte
   111  				if b, err = errors.Marshal(status, err.Error(), "", ""); err == nil {
   112  					_, err = w.Write(b)
   113  				}
   114  			}
   115  		}
   116  		if err != nil {
   117  			appctx.GetLogger(r.Context()).Error().Err(err).Msg(err.Error())
   118  		}
   119  	})
   120  }