Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
owncloud/ocs: Move to go-chi/chi based URL routing
Browse files Browse the repository at this point in the history
This should help with code readability and make it easier to figure out
which code is executed for which URL.

Closes #1986
rhafer committed Aug 20, 2021
1 parent 18b230c commit 57c47a8
Showing 17 changed files with 179 additions and 495 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ require (
github.com/cs3org/go-cs3apis v0.0.0-20210802070913-970eec344e59
github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59
github.com/gdexlab/go-render v1.0.1
github.com/go-chi/chi/v5 v5.0.3 // indirect
github.com/go-ldap/ldap/v3 v3.3.0
github.com/go-openapi/errors v0.20.0 // indirect
github.com/go-openapi/strfmt v0.19.5 // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -138,6 +138,8 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4=
github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
72 changes: 0 additions & 72 deletions internal/http/services/owncloud/ocs/handlers/apps/apps.go

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -29,7 +29,6 @@ import (
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/response"
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/pkg/rhttp/router"
"github.com/cs3org/reva/pkg/storage/utils/templates"
)

@@ -40,24 +39,13 @@ type Handler struct {
}

// Init initializes this and any contained handlers
func (h *Handler) Init(c *config.Config) error {
func (h *Handler) Init(c *config.Config) {
h.gatewayAddr = c.GatewaySvc
h.additionalInfoAttribute = c.AdditionalInfoAttribute
return nil
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log := appctx.GetLogger(r.Context())

var head string
head, r.URL.Path = router.ShiftPath(r.URL.Path)

log.Debug().Str("head", head).Str("tail", r.URL.Path).Msg("http routing")

h.findSharees(w, r)
}

func (h *Handler) findSharees(w http.ResponseWriter, r *http.Request) {
// FindSharees implements the /apps/files_sharing/api/v1/sharees endpoint
func (h *Handler) FindSharees(w http.ResponseWriter, r *http.Request) {
log := appctx.GetLogger(r.Context())
term := r.URL.Query().Get("search")

@@ -71,7 +59,6 @@ func (h *Handler) findSharees(w http.ResponseWriter, r *http.Request) {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting gateway grpc client", err)
return
}

usersRes, err := gwc.FindUsers(r.Context(), &userpb.FindUsersRequest{Filter: term})
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error searching users", err)
Original file line number Diff line number Diff line change
@@ -28,9 +28,22 @@ import (
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/response"
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/go-chi/chi/v5"
"github.com/pkg/errors"
)

// AcceptReceivedShare handles Post Requests on /apps/files_sharing/api/v1/shares/{shareid}
func (h *Handler) AcceptReceivedShare(w http.ResponseWriter, r *http.Request) {
shareID := chi.URLParam(r, "shareid")
h.updateReceivedShare(w, r, shareID, false)
}

// RejectReceivedShare handles DELETE Requests on /apps/files_sharing/api/v1/shares/{shareid}
func (h *Handler) RejectReceivedShare(w http.ResponseWriter, r *http.Request) {
shareID := chi.URLParam(r, "shareid")
h.updateReceivedShare(w, r, shareID, false)
}

func (h *Handler) updateReceivedShare(w http.ResponseWriter, r *http.Request, shareID string, rejectShare bool) {
ctx := r.Context()
logger := appctx.GetLogger(ctx)
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ import (
ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/go-chi/chi/v5"

"github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions"
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/response"
@@ -119,11 +120,13 @@ func (h *Handler) createFederatedCloudShare(w http.ResponseWriter, r *http.Reque
response.WriteOCSSuccess(w, r, "OCM Share created")
}

func (h *Handler) getFederatedShare(w http.ResponseWriter, r *http.Request, shareID string) {
// GetFederatedShare handles GET requests on /apps/files_sharing/api/v1/shares/remote_shares/{shareid}
func (h *Handler) GetFederatedShare(w http.ResponseWriter, r *http.Request) {

// TODO: Implement response with HAL schemating
ctx := r.Context()

shareID := chi.URLParam(r, "shareid")
gatewayClient, err := pool.GetGatewayServiceClient(h.gatewayAddr)
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err)
@@ -153,7 +156,8 @@ func (h *Handler) getFederatedShare(w http.ResponseWriter, r *http.Request, shar
response.WriteOCSSuccess(w, r, share)
}

func (h *Handler) listFederatedShares(w http.ResponseWriter, r *http.Request) {
// ListFederatedShares handles GET requests on /apps/files_sharing/api/v1/shares/remote_shares
func (h *Handler) ListFederatedShares(w http.ResponseWriter, r *http.Request) {

// TODO Implement pagination.
// TODO Implement response with HAL schemating
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@ import (
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/go-chi/chi/v5"
"github.com/rs/zerolog/log"

"github.com/ReneKroon/ttlcache/v2"
@@ -49,7 +50,6 @@ import (
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/response"
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/pkg/rhttp/router"
"github.com/cs3org/reva/pkg/share/cache"
"github.com/cs3org/reva/pkg/share/cache/registry"
"github.com/cs3org/reva/pkg/utils"
@@ -83,7 +83,7 @@ func getCacheWarmupManager(c *config.Config) (cache.Warmup, error) {
}

// Init initializes this and any contained handlers
func (h *Handler) Init(c *config.Config) error {
func (h *Handler) Init(c *config.Config) {
h.gatewayAddr = c.GatewaySvc
h.publicURL = c.Config.Host
h.sharePrefix = c.SharePrefix
@@ -102,8 +102,6 @@ func (h *Handler) Init(c *config.Config) error {
go h.startCacheWarmup(cwm)
}
}

return nil
}

func (h *Handler) startCacheWarmup(c cache.Warmup) {
@@ -117,89 +115,8 @@ func (h *Handler) startCacheWarmup(c cache.Warmup) {
}
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log := appctx.GetLogger(r.Context())

var head string
head, r.URL.Path = router.ShiftPath(r.URL.Path)

log.Debug().Str("head", head).Str("tail", r.URL.Path).Msg("http routing")

switch head {
case "":
switch r.Method {
case "OPTIONS":
w.WriteHeader(http.StatusOK)
case "GET":
if h.isListSharesWithMe(w, r) {
h.listSharesWithMe(w, r)
} else {
h.listSharesWithOthers(w, r)
}
case "POST":
h.createShare(w, r)
default:
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "Only GET, POST and PUT are allowed", nil)
}

case "pending":
var shareID string
shareID, r.URL.Path = router.ShiftPath(r.URL.Path)

log.Debug().Str("share_id", shareID).Str("tail", r.URL.Path).Msg("http routing")

switch r.Method {
case "POST":
h.updateReceivedShare(w, r, shareID, false)
case "DELETE":
h.updateReceivedShare(w, r, shareID, true)
default:
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "Only POST and DELETE are allowed", nil)
}

case "remote_shares":
var shareID string
shareID, r.URL.Path = router.ShiftPath(r.URL.Path)

log.Debug().Str("share_id", shareID).Str("tail", r.URL.Path).Msg("http routing")

switch r.Method {
case "GET":
if shareID == "" {
h.listFederatedShares(w, r)
} else {
h.getFederatedShare(w, r, shareID)
}
default:
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "Only GET method is allowed", nil)
}

default:
switch r.Method {
case "GET":
h.getShare(w, r, head)
case "PUT":
// FIXME: isPublicShare is already doing a GetShare and GetPublicShare,
// we should just reuse that object when doing updates
if h.isPublicShare(r, strings.ReplaceAll(head, "/", "")) {
h.updatePublicShare(w, r, strings.ReplaceAll(head, "/", ""))
return
}
h.updateShare(w, r, head) // TODO PUT is used with incomplete data to update a share
case "DELETE":
shareID := strings.ReplaceAll(head, "/", "")
if h.isPublicShare(r, shareID) {
h.removePublicShare(w, r, shareID)
return
}
h.removeUserShare(w, r, head)
default:
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "Only GET, POST and PUT are allowed", nil)
}
}
}

func (h *Handler) createShare(w http.ResponseWriter, r *http.Request) {
// CreateShare handles POST requests on /apps/files_sharing/api/v1/shares
func (h *Handler) CreateShare(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
shareType, err := strconv.Atoi(r.FormValue("shareType"))
if err != nil {
@@ -329,9 +246,11 @@ func (h *Handler) extractPermissions(w http.ResponseWriter, r *http.Request, ri
// PublicShareContextName represent cross boundaries context for the name of the public share
type PublicShareContextName string

func (h *Handler) getShare(w http.ResponseWriter, r *http.Request, shareID string) {
// GetShare handles GET requests on /apps/files_sharing/api/v1/shares/(shareid)
func (h *Handler) GetShare(w http.ResponseWriter, r *http.Request) {
var share *conversions.ShareData
var resourceID *provider.ResourceId
shareID := chi.URLParam(r, "shareid")
ctx := r.Context()
logger := appctx.GetLogger(r.Context())
logger.Debug().Str("shareID", shareID).Msg("get share by id")
@@ -442,6 +361,18 @@ func (h *Handler) getShare(w http.ResponseWriter, r *http.Request, shareID strin
response.WriteOCSSuccess(w, r, []*conversions.ShareData{share})
}

// UpdateShare handles PUT requests on /apps/files_sharing/api/v1/shares/(shareid)
func (h *Handler) UpdateShare(w http.ResponseWriter, r *http.Request) {
shareID := chi.URLParam(r, "shareid")
// FIXME: isPublicShare is already doing a GetShare and GetPublicShare,
// we should just reuse that object when doing updates
if h.isPublicShare(r, shareID) {
h.updatePublicShare(w, r, shareID)
return
}
h.updateShare(w, r, shareID) // TODO PUT is used with incomplete data to update a share}
}

func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID string) {
ctx := r.Context()

@@ -537,15 +468,30 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st
response.WriteOCSSuccess(w, r, share)
}

func (h *Handler) isListSharesWithMe(w http.ResponseWriter, r *http.Request) (listSharedWithMe bool) {
// RemoveShare handles DELETE requests on /apps/files_sharing/api/v1/shares/(shareid)
func (h *Handler) RemoveShare(w http.ResponseWriter, r *http.Request) {
shareID := chi.URLParam(r, "shareid")
if h.isPublicShare(r, shareID) {
h.removePublicShare(w, r, shareID)
return
}
h.removeUserShare(w, r, shareID)
}

// ListShares handles GET requests on /apps/files_sharing/api/v1/shares
func (h *Handler) ListShares(w http.ResponseWriter, r *http.Request) {
if r.FormValue("shared_with_me") != "" {
var err error
listSharedWithMe, err = strconv.ParseBool(r.FormValue("shared_with_me"))
listSharedWithMe, err := strconv.ParseBool(r.FormValue("shared_with_me"))
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err)
}
if listSharedWithMe {
h.listSharesWithMe(w, r)
return
}
}
return
h.listSharesWithOthers(w, r)
}

const (

This file was deleted.

Original file line number Diff line number Diff line change
@@ -217,9 +217,7 @@ func (h *Handler) Init(c *config.Config) {
}

// Handler renders the capabilities
func (h *Handler) Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c := h.getCapabilitiesForUserAgent(r.UserAgent())
response.WriteOCSSuccess(w, r, c)
})
func (h *Handler) GetCapabilities(w http.ResponseWriter, r *http.Request) {
c := h.getCapabilitiesForUserAgent(r.UserAgent())
response.WriteOCSSuccess(w, r, c)
}
64 changes: 0 additions & 64 deletions internal/http/services/owncloud/ocs/handlers/cloud/cloud.go

This file was deleted.

Original file line number Diff line number Diff line change
@@ -30,7 +30,8 @@ import (
type Handler struct {
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// GetSelf handles GET requests on /cloud/user
func (h *Handler) GetSelf(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

// TODO move user to handler parameter?
59 changes: 23 additions & 36 deletions internal/http/services/owncloud/ocs/handlers/cloud/users/users.go
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ import (
"github.com/cs3org/reva/pkg/appctx"
ctxpkg "github.com/cs3org/reva/pkg/ctx"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/pkg/rhttp/router"
"github.com/go-chi/chi/v5"
)

// Handler renders user data for the user id given in the url path
@@ -41,43 +41,14 @@ type Handler struct {
}

// Init initializes this and any contained handlers
func (h *Handler) Init(c *config.Config) error {
func (h *Handler) Init(c *config.Config) {
h.gatewayAddr = c.GatewaySvc
return nil
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

var user string
user, r.URL.Path = router.ShiftPath(r.URL.Path)

// FIXME use ldap to fetch user info
u, ok := ctxpkg.ContextGetUser(ctx)
if !ok {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "missing user in context", fmt.Errorf("missing user in context"))
return
}
if user != u.Username {
// FIXME allow fetching other users info? only for admins
response.WriteOCSError(w, r, http.StatusForbidden, "user id mismatch", fmt.Errorf("%s tried to access %s user info endpoint", u.Id.OpaqueId, user))
return
}

var head string
head, r.URL.Path = router.ShiftPath(r.URL.Path)
switch head {
case "":
h.handleUsers(w, r, u)
return
case "groups":
response.WriteOCSSuccess(w, r, &Groups{})
return
default:
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "Not found", nil)
return
}

// GetGroups handles GET requests on /cloud/users/groups
// TODO: implement
func (h *Handler) GetGroups(w http.ResponseWriter, r *http.Request) {
response.WriteOCSSuccess(w, r, &Groups{})
}

// Quota holds quota information
@@ -104,10 +75,26 @@ type Groups struct {
Groups []string `json:"groups" xml:"groups>element"`
}

func (h *Handler) handleUsers(w http.ResponseWriter, r *http.Request, u *userpb.User) {
// GetUsers handles GET requests on /cloud/users
// Only allow self-read currently. TODO: List Users and Get on other users (both require
// administrative privileges)
func (h *Handler) GetUsers(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
sublog := appctx.GetLogger(r.Context())

user := chi.URLParam(r, "userid")
// FIXME use ldap to fetch user info
u, ok := ctxpkg.ContextGetUser(ctx)
if !ok {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "missing user in context", fmt.Errorf("missing user in context"))
return
}
if user != u.Username {
// FIXME allow fetching other users info? only for admins
response.WriteOCSError(w, r, http.StatusForbidden, "user id mismatch", fmt.Errorf("%s tried to access %s user info endpoint", u.Id.OpaqueId, user))
return
}

gc, err := pool.GetGatewayServiceClient(h.gatewayAddr)
if err != nil {
sublog.Error().Err(err).Msg("error getting gateway client")
6 changes: 2 additions & 4 deletions internal/http/services/owncloud/ocs/handlers/config/config.go
Original file line number Diff line number Diff line change
@@ -53,8 +53,6 @@ func (h *Handler) Init(c *config.Config) {
}

// Handler renders the config
func (h *Handler) Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
response.WriteOCSSuccess(w, r, h.c)
})
func (h *Handler) GetConfig(w http.ResponseWriter, r *http.Request) {
response.WriteOCSSuccess(w, r, h.c)
}
96 changes: 71 additions & 25 deletions internal/http/services/owncloud/ocs/ocs.go
Original file line number Diff line number Diff line change
@@ -22,29 +22,29 @@ import (
"net/http"

"github.com/cs3org/reva/internal/http/services/owncloud/ocs/config"
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/handlers/apps/sharing/sharees"
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares"
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/handlers/cloud/capabilities"
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/handlers/cloud/user"
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/handlers/cloud/users"
configHandler "github.com/cs3org/reva/internal/http/services/owncloud/ocs/handlers/config"
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/response"
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/rhttp/global"
"github.com/cs3org/reva/pkg/rhttp/router"
"github.com/go-chi/chi/v5"
"github.com/mitchellh/mapstructure"
"github.com/rs/zerolog"
)

const (
apiV1 = "v1.php"
apiV2 = "v2.php"
)

func init() {
global.Register("ocs", New)
}

type svc struct {
c *config.Config
V1Handler *V1Handler
c *config.Config
router *chi.Mux
}

// New returns a new capabilitiessvc
func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) {
conf := &config.Config{}
if err := mapstructure.Decode(m, conf); err != nil {
@@ -53,13 +53,13 @@ func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error)

conf.Init()

r := chi.NewRouter()
s := &svc{
c: conf,
V1Handler: new(V1Handler),
c: conf,
router: r,
}

// initialize handlers and set default configs
if err := s.V1Handler.init(conf); err != nil {
if err := s.routerInit(); err != nil {
return nil, err
}

@@ -78,20 +78,66 @@ func (s *svc) Unprotected() []string {
return []string{}
}

func (s *svc) routerInit() error {
capabilitiesHandler := new(capabilities.Handler)
userHandler := new(user.Handler)
usersHandler := new(users.Handler)
configHandler := new(configHandler.Handler)
sharesHandler := new(shares.Handler)
shareesHandler := new(sharees.Handler)
capabilitiesHandler.Init(s.c)
usersHandler.Init(s.c)
configHandler.Init(s.c)
sharesHandler.Init(s.c)
shareesHandler.Init(s.c)

s.router.Route("/v{version:(1|2)}.php", func(r chi.Router) {
r.Use(response.VersionCtx)
r.Route("/apps/files_sharing/api/v1", func(r chi.Router) {
r.Route("/shares", func(r chi.Router) {
r.Get("/", sharesHandler.ListShares)
r.Options("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})
r.Post("/", sharesHandler.CreateShare)
r.Route("/pending/{shareid}", func(r chi.Router) {
r.Post("/", sharesHandler.AcceptReceivedShare)
r.Delete("/", sharesHandler.RejectReceivedShare)
})
r.Route("/remote_shares", func(r chi.Router) {
r.Get("/", sharesHandler.ListFederatedShares)
r.Get("/{shareid}", sharesHandler.GetFederatedShare)
})
r.Get("/{shareid}", sharesHandler.GetShare)
r.Put("/{shareid}", sharesHandler.UpdateShare)
r.Delete("/{shareid}", sharesHandler.RemoveShare)
})
r.Get("/sharees", shareesHandler.FindSharees)
})

// placeholder for notifications
r.Get("/apps/notifications/api/v1/notifications", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})

r.Get("/config", configHandler.GetConfig)

r.Route("/cloud", func(r chi.Router) {
r.Get("/capabilities", capabilitiesHandler.GetCapabilities)
r.Get("/user", userHandler.GetSelf)
r.Route("/users", func(r chi.Router) {
r.Get("/{userid}", usersHandler.GetUsers)
r.Get("/{userid}/groups", usersHandler.GetGroups)
})
})
})
return nil
}

func (s *svc) Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log := appctx.GetLogger(r.Context())

var head string
head, r.URL.Path = router.ShiftPath(r.URL.Path)

log.Debug().Str("head", head).Str("tail", r.URL.Path).Msg("ocs routing")

if !(head == apiV1 || head == apiV2) {
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "Not found", nil)
return
}
ctx := response.WithAPIVersion(r.Context(), head)
s.V1Handler.Handler().ServeHTTP(w, r.WithContext(ctx))
log.Debug().Str("path", r.URL.Path).Msg("ocs routing")
s.router.ServeHTTP(w, r)
})
}
20 changes: 16 additions & 4 deletions internal/http/services/owncloud/ocs/response/response.go
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ import (
"reflect"

"github.com/cs3org/reva/pkg/appctx"
"github.com/go-chi/chi/v5"
)

type key int
@@ -233,8 +234,19 @@ func OcsV2StatusCodes(meta Meta) int {
}

// WithAPIVersion puts the api version in the context.
func WithAPIVersion(parent context.Context, version string) context.Context {
return context.WithValue(parent, apiVersionKey, version)
func VersionCtx(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
version := chi.URLParam(r, "version")
if version == "" {
WriteOCSError(w, r, MetaBadRequest.StatusCode, "unknown ocs api version", nil)
return
}
w.Header().Set("Ocs-Api-Version", version)

// store version in context so handlers can access it
ctx := context.WithValue(r.Context(), apiVersionKey, version)
next.ServeHTTP(w, r.WithContext(ctx))
})
}

// APIVersion retrieves the api version from the context.
@@ -249,9 +261,9 @@ func APIVersion(ctx context.Context) string {
func statusCodeMapper(version string) func(Meta) int {
var mapper func(Meta) int
switch version {
case "v1.php":
case "1":
mapper = OcsV1StatusCodes
case "v2.php":
case "2":
mapper = OcsV2StatusCodes
default:
mapper = defaultStatusCodeMapper
66 changes: 0 additions & 66 deletions internal/http/services/owncloud/ocs/v1.go

This file was deleted.

0 comments on commit 57c47a8

Please sign in to comment.