github.com/cs3org/reva/v2@v2.27.7/internal/http/services/dataprovider/dataprovider.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 dataprovider
    20  
    21  import (
    22  	"fmt"
    23  	"net/http"
    24  
    25  	"github.com/mitchellh/mapstructure"
    26  	"github.com/rs/zerolog"
    27  
    28  	"github.com/cs3org/reva/v2/pkg/appctx"
    29  	"github.com/cs3org/reva/v2/pkg/events"
    30  	"github.com/cs3org/reva/v2/pkg/events/stream"
    31  	datatxregistry "github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/registry"
    32  	"github.com/cs3org/reva/v2/pkg/rhttp/global"
    33  	"github.com/cs3org/reva/v2/pkg/rhttp/router"
    34  	"github.com/cs3org/reva/v2/pkg/storage"
    35  	"github.com/cs3org/reva/v2/pkg/storage/fs/registry"
    36  )
    37  
    38  func init() {
    39  	global.Register("dataprovider", New)
    40  }
    41  
    42  type config struct {
    43  	Prefix             string                            `mapstructure:"prefix" docs:"data;The prefix to be used for this HTTP service"`
    44  	Driver             string                            `mapstructure:"driver" docs:"localhome;The storage driver to be used."`
    45  	Drivers            map[string]map[string]interface{} `mapstructure:"drivers" docs:"url:pkg/storage/fs/localhome/localhome.go;The configuration for the storage driver"`
    46  	DataTXs            map[string]map[string]interface{} `mapstructure:"data_txs" docs:"url:pkg/rhttp/datatx/manager/simple/simple.go;The configuration for the data tx protocols"`
    47  	NatsAddress        string                            `mapstructure:"nats_address"`
    48  	NatsClusterID      string                            `mapstructure:"nats_clusterID"`
    49  	NatsTLSInsecure    bool                              `mapstructure:"nats_tls_insecure"`
    50  	NatsRootCACertPath string                            `mapstructure:"nats_root_ca_cert_path"`
    51  	NatsEnableTLS      bool                              `mapstructure:"nats_enable_tls"`
    52  	NatsUsername       string                            `mapstructure:"nats_username"`
    53  	NatsPassword       string                            `mapstructure:"nats_password"`
    54  }
    55  
    56  func (c *config) init() {
    57  	if c.Prefix == "" {
    58  		c.Prefix = "data"
    59  	}
    60  	if c.Driver == "" {
    61  		c.Driver = "localhome"
    62  	}
    63  }
    64  
    65  type svc struct {
    66  	conf    *config
    67  	handler http.Handler
    68  	storage storage.FS
    69  	dataTXs map[string]http.Handler
    70  }
    71  
    72  // New returns a new datasvc
    73  func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) {
    74  	conf := &config{}
    75  	if err := mapstructure.Decode(m, conf); err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	conf.init()
    80  
    81  	var evstream events.Stream
    82  
    83  	if conf.NatsAddress == "" || conf.NatsClusterID == "" {
    84  		log.Warn().Msg("missing or incomplete nats configuration. Events will not be published.")
    85  	} else {
    86  		s, err := stream.NatsFromConfig("dataprovider", false, stream.NatsConfig{
    87  			Endpoint:             conf.NatsAddress,
    88  			Cluster:              conf.NatsClusterID,
    89  			EnableTLS:            conf.NatsEnableTLS,
    90  			TLSInsecure:          conf.NatsTLSInsecure,
    91  			TLSRootCACertificate: conf.NatsRootCACertPath,
    92  			AuthUsername:         conf.NatsUsername,
    93  			AuthPassword:         conf.NatsPassword,
    94  		})
    95  		if err != nil {
    96  			return nil, err
    97  		}
    98  
    99  		evstream = s
   100  	}
   101  
   102  	fs, err := getFS(conf, evstream, log)
   103  	if err != nil {
   104  		return nil, err
   105  	}
   106  
   107  	dataTXs, err := getDataTXs(conf, fs, evstream, log)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	s := &svc{
   113  		storage: fs,
   114  		conf:    conf,
   115  		dataTXs: dataTXs,
   116  	}
   117  
   118  	err = s.setHandler()
   119  	return s, err
   120  }
   121  
   122  func getFS(c *config, stream events.Stream, log *zerolog.Logger) (storage.FS, error) {
   123  	if f, ok := registry.NewFuncs[c.Driver]; ok {
   124  		return f(c.Drivers[c.Driver], stream, log)
   125  	}
   126  	return nil, fmt.Errorf("driver not found: %s", c.Driver)
   127  }
   128  
   129  func getDataTXs(c *config, fs storage.FS, publisher events.Publisher, log *zerolog.Logger) (map[string]http.Handler, error) {
   130  	if c.DataTXs == nil {
   131  		c.DataTXs = make(map[string]map[string]interface{})
   132  	}
   133  	if len(c.DataTXs) == 0 {
   134  		c.DataTXs["simple"] = make(map[string]interface{})
   135  		c.DataTXs["simple"]["cache_store"] = "noop"
   136  		c.DataTXs["simple"]["cache_database"] = "reva"
   137  		c.DataTXs["spaces"] = make(map[string]interface{})
   138  		c.DataTXs["spaces"]["cache_store"] = "noop"
   139  		c.DataTXs["spaces"]["cache_database"] = "reva"
   140  		c.DataTXs["tus"] = make(map[string]interface{})
   141  		c.DataTXs["tus"]["cache_store"] = "noop"
   142  		c.DataTXs["tus"]["cache_database"] = "reva"
   143  	}
   144  
   145  	txs := make(map[string]http.Handler)
   146  	for t := range c.DataTXs {
   147  		if f, ok := datatxregistry.NewFuncs[t]; ok {
   148  			if tx, err := f(c.DataTXs[t], publisher, log); err == nil {
   149  				if handler, err := tx.Handler(fs); err == nil {
   150  					txs[t] = handler
   151  				}
   152  			}
   153  		}
   154  	}
   155  	return txs, nil
   156  }
   157  
   158  func (s *svc) Close() error {
   159  	return nil
   160  }
   161  
   162  func (s *svc) Unprotected() []string {
   163  	return []string{
   164  		"/tus",
   165  	}
   166  }
   167  
   168  func (s *svc) Prefix() string {
   169  	return s.conf.Prefix
   170  }
   171  
   172  func (s *svc) Handler() http.Handler {
   173  	return s.handler
   174  }
   175  
   176  func (s *svc) setHandler() error {
   177  
   178  	s.handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   179  		log := appctx.GetLogger(r.Context())
   180  		log.Debug().Msgf("dataprovider routing: path=%s", r.URL.Path)
   181  
   182  		head, tail := router.ShiftPath(r.URL.Path)
   183  
   184  		if handler, ok := s.dataTXs[head]; ok {
   185  			r.URL.Path = tail
   186  			handler.ServeHTTP(w, r)
   187  			return
   188  		}
   189  
   190  		// If we don't find a prefix match for any of the protocols, upload the resource
   191  		// through the direct HTTP protocol
   192  		if handler, ok := s.dataTXs["simple"]; ok {
   193  			handler.ServeHTTP(w, r)
   194  			return
   195  		}
   196  
   197  		w.WriteHeader(http.StatusInternalServerError)
   198  	})
   199  
   200  	return nil
   201  }