github.com/cs3org/reva/v2@v2.27.7/pkg/mentix/exchangers/reqexchanger.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 exchangers
    20  
    21  import (
    22  	"fmt"
    23  	"net/http"
    24  	"net/url"
    25  	"strings"
    26  
    27  	"github.com/rs/zerolog"
    28  
    29  	"github.com/cs3org/reva/v2/pkg/mentix/config"
    30  	"github.com/cs3org/reva/v2/pkg/mentix/meshdata"
    31  )
    32  
    33  // RequestExchanger is the interface implemented by exchangers that offer an HTTP endpoint.
    34  type RequestExchanger interface {
    35  	// Endpoint returns the (relative) endpoint of the exchanger.
    36  	Endpoint() string
    37  	// IsProtectedEndpoint returns true if the endpoint can only be accessed with authorization.
    38  	IsProtectedEndpoint() bool
    39  	// WantsRequest returns whether the exchanger wants to handle the incoming request.
    40  	WantsRequest(r *http.Request) bool
    41  	// HandleRequest handles the actual HTTP request.
    42  	HandleRequest(resp http.ResponseWriter, req *http.Request, conf *config.Configuration, log *zerolog.Logger)
    43  }
    44  
    45  type queryCallback func(*meshdata.MeshData, url.Values, *config.Configuration, *zerolog.Logger) (int, []byte, error)
    46  type extendedQueryCallback func(*meshdata.MeshData, []byte, url.Values, *config.Configuration, *zerolog.Logger) (meshdata.Vector, int, []byte, error)
    47  
    48  // BaseRequestExchanger implements basic exporter functionality common to all request exporters.
    49  type BaseRequestExchanger struct {
    50  	RequestExchanger
    51  
    52  	endpoint            string
    53  	isProtectedEndpoint bool
    54  
    55  	actionHandlers         map[string]queryCallback
    56  	extendedActionHandlers map[string]extendedQueryCallback
    57  }
    58  
    59  // Endpoint returns the (relative) endpoint of the exchanger.
    60  func (exchanger *BaseRequestExchanger) Endpoint() string {
    61  	// Ensure that the endpoint starts with a /
    62  	endpoint := exchanger.endpoint
    63  	if !strings.HasPrefix(endpoint, "/") {
    64  		endpoint = "/" + endpoint
    65  	}
    66  	return strings.TrimSpace(endpoint)
    67  }
    68  
    69  // IsProtectedEndpoint returns true if the endpoint can only be accessed with authorization.
    70  func (exchanger *BaseRequestExchanger) IsProtectedEndpoint() bool {
    71  	return exchanger.isProtectedEndpoint
    72  }
    73  
    74  // SetEndpoint sets the (relative) endpoint of the exchanger.
    75  func (exchanger *BaseRequestExchanger) SetEndpoint(endpoint string, isProtected bool) {
    76  	exchanger.endpoint = endpoint
    77  	exchanger.isProtectedEndpoint = isProtected
    78  }
    79  
    80  // WantsRequest returns whether the exchanger wants to handle the incoming request.
    81  func (exchanger *BaseRequestExchanger) WantsRequest(r *http.Request) bool {
    82  	return r.URL.Path == exchanger.Endpoint()
    83  }
    84  
    85  // HandleRequest handles the actual HTTP request.
    86  func (exchanger *BaseRequestExchanger) HandleRequest(resp http.ResponseWriter, req *http.Request, conf *config.Configuration, log *zerolog.Logger) error {
    87  	return nil
    88  }
    89  
    90  // RegisterActionHandler registers a new handler for the specified action.
    91  func (exchanger *BaseRequestExchanger) RegisterActionHandler(action string, callback queryCallback) {
    92  	if exchanger.actionHandlers == nil {
    93  		exchanger.actionHandlers = make(map[string]queryCallback)
    94  	}
    95  	exchanger.actionHandlers[action] = callback
    96  }
    97  
    98  // RegisterExtendedActionHandler registers a new handler for the specified extended action.
    99  func (exchanger *BaseRequestExchanger) RegisterExtendedActionHandler(action string, callback extendedQueryCallback) {
   100  	if exchanger.extendedActionHandlers == nil {
   101  		exchanger.extendedActionHandlers = make(map[string]extendedQueryCallback)
   102  	}
   103  	exchanger.extendedActionHandlers[action] = callback
   104  }
   105  
   106  // HandleAction executes the registered handler for the specified action, if any.
   107  func (exchanger *BaseRequestExchanger) HandleAction(meshData *meshdata.MeshData, body []byte, params url.Values, isExtended bool, conf *config.Configuration, log *zerolog.Logger) (meshdata.Vector, int, []byte, error) {
   108  	reqAction := params.Get("action")
   109  
   110  	if isExtended {
   111  		for action, handler := range exchanger.extendedActionHandlers {
   112  			if strings.EqualFold(action, reqAction) {
   113  				return handler(meshData, body, params, conf, log)
   114  			}
   115  		}
   116  	} else {
   117  		for action, handler := range exchanger.actionHandlers {
   118  			if strings.EqualFold(action, reqAction) {
   119  				status, data, err := handler(meshData, params, conf, log)
   120  				return nil, status, data, err
   121  			}
   122  		}
   123  	}
   124  
   125  	return nil, http.StatusNotFound, []byte{}, fmt.Errorf("unhandled query for action '%v'", reqAction)
   126  }