github.com/m3db/m3@v1.5.0/src/query/api/v1/handler/topic/common.go (about) 1 // Copyright (c) 2020 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package topic 22 23 import ( 24 "net/http" 25 "strings" 26 27 clusterclient "github.com/m3db/m3/src/cluster/client" 28 "github.com/m3db/m3/src/cluster/kv" 29 "github.com/m3db/m3/src/cluster/placementhandler/handleroptions" 30 "github.com/m3db/m3/src/cmd/services/m3query/config" 31 "github.com/m3db/m3/src/msg/topic" 32 "github.com/m3db/m3/src/query/util/queryhttp" 33 xerrors "github.com/m3db/m3/src/x/errors" 34 "github.com/m3db/m3/src/x/instrument" 35 36 "github.com/gogo/protobuf/jsonpb" 37 "github.com/gogo/protobuf/proto" 38 ) 39 40 const ( 41 // DefaultTopicName is the default topic name 42 DefaultTopicName = "aggregated_metrics" 43 // HeaderTopicName is the header used to specify the topic name. 44 HeaderTopicName = "topic-name" 45 ) 46 47 type serviceFn func(clusterClient clusterclient.Client, opts handleroptions.ServiceOptions) (topic.Service, error) 48 49 // Handler represents a generic handler for topic endpoints. 50 // nolint: structcheck 51 type Handler struct { 52 // This is used by other topic Handlers 53 client clusterclient.Client 54 cfg config.Configuration 55 56 serviceFn serviceFn 57 instrumentOpts instrument.Options 58 } 59 60 // Service gets a topic service from m3cluster client 61 func Service(clusterClient clusterclient.Client, opts handleroptions.ServiceOptions) (topic.Service, error) { 62 kvOverride := kv.NewOverrideOptions(). 63 SetEnvironment(opts.ServiceEnvironment). 64 SetZone(opts.ServiceZone) 65 topicOpts := topic.NewServiceOptions(). 66 SetConfigService(clusterClient). 67 SetKVOverrideOptions(kvOverride) 68 return topic.NewService(topicOpts) 69 } 70 71 // RegisterRoutes registers the topic routes 72 func RegisterRoutes( 73 r *queryhttp.EndpointRegistry, 74 client clusterclient.Client, 75 cfg config.Configuration, 76 instrumentOpts instrument.Options, 77 ) error { 78 if err := r.Register(queryhttp.RegisterOptions{ 79 Path: InitURL, 80 Handler: newInitHandler(client, cfg, instrumentOpts), 81 Methods: []string{InitHTTPMethod}, 82 }); err != nil { 83 return err 84 } 85 if err := r.Register(queryhttp.RegisterOptions{ 86 Path: GetURL, 87 Handler: newGetHandler(client, cfg, instrumentOpts), 88 Methods: []string{GetHTTPMethod}, 89 }); err != nil { 90 return err 91 } 92 if err := r.Register(queryhttp.RegisterOptions{ 93 Path: AddURL, 94 Handler: newAddHandler(client, cfg, instrumentOpts), 95 Methods: []string{AddHTTPMethod}, 96 }); err != nil { 97 return err 98 } 99 if err := r.Register(queryhttp.RegisterOptions{ 100 Path: UpdateURL, 101 Handler: newUpdateHandler(client, cfg, instrumentOpts), 102 Methods: []string{UpdateHTTPMethod}, 103 }); err != nil { 104 return err 105 } 106 if err := r.Register(queryhttp.RegisterOptions{ 107 Path: DeleteURL, 108 Handler: newDeleteHandler(client, cfg, instrumentOpts), 109 Methods: []string{DeleteHTTPMethod}, 110 }); err != nil { 111 return err 112 } 113 return nil 114 } 115 116 func topicName(headers http.Header) string { 117 if v := strings.TrimSpace(headers.Get(HeaderTopicName)); v != "" { 118 return v 119 } 120 return DefaultTopicName 121 } 122 123 func parseRequest(r *http.Request, m proto.Message) error { 124 defer r.Body.Close() 125 126 if err := jsonpb.Unmarshal(r.Body, m); err != nil { 127 return xerrors.NewInvalidParamsError(err) 128 } 129 130 return nil 131 }