Documentation ¶
Overview ¶
Package servicectx facilitates exchanging arbitrary properties across microservices via HTTP headers, query strings, OpenTelemetry/OpenTracing baggage, and/or Go Context.
Index ¶
- Constants
- func GetPropertyName(serviceName, option string) string
- func InjectIntoContextFromRequest(ctx context.Context, req *http.Request) context.Context
- func InjectIntoHeadersFromContext(ctx context.Context, header http.Header)
- func ParsePropertyName(name string) (serviceName, option string, ok bool)
- func ReplaceUrlBranch(url, branch string) string
- type Properties
- func (p Properties) Get(serviceName, prop, defaultValue string) string
- func (p Properties) GetBool(serviceName, prop string, defaultValue bool) bool
- func (p Properties) GetByService(serviceName string) Values
- func (p Properties) GetDuration(serviceName, prop string, defaultValue time.Duration) time.Duration
- func (p Properties) GetInt(serviceName, prop string, defaultValue int) int
- func (p Properties) HasProperty(serviceName, option string) bool
- func (p Properties) HasService(serviceName string) bool
- func (p Properties) HeaderMap() map[string]string
- func (p Properties) InjectIntoContext(ctx context.Context) context.Context
- func (p Properties) InjectIntoHeaders(headers http.Header)
- func (p Properties) Merge(other Properties) Properties
- func (p Properties) QueryString() string
- func (p Properties) QueryValues() url.Values
- func (p Properties) Set(serviceName, prop, value string) Properties
- type Values
Examples ¶
Constants ¶
const NamePrefix = "x-service"
NamePrefix a prefix at the beginning of a property name indicating it belongs to this package
const Separator = "-"
const UrlBranchPlaceholder = "$branch"
UrlBranchPlaceholder is a part of URL to be replaced with a branch name
Variables ¶
This section is empty.
Functions ¶
func GetPropertyName ¶ added in v0.2.0
GetPropertyName builds a string from service name and property name
func InjectIntoContextFromRequest ¶ added in v0.2.0
InjectIntoContextFromRequest parses properties from request and adds them into context
Example ¶
An example HTTP client and server, with properties exchanged internally through `context.Context`
props := New() // the "api url" will be used by the handler below props.Set("api", "url", "http://my-custom-api") // and the "billing branch" will just be passed downstream to the remote service props.Set("billing", "branch", "hotfix-123") req := httptest.NewRequest(http.MethodGet, "/?username=Alex", nil) props.InjectIntoHeaders(req.Header) handler := func(w http.ResponseWriter, r *http.Request) { // parse properties from request and add them to a context. // it's ok if no special headers or query args were sent: an empty usable struct is then used instead. ctx := InjectIntoContextFromRequest(r.Context(), r) // an apiCall is probably defined in another package; // its `username` argument is a part of business logic, // but properties, being an arbitrary ancillary data, are passed within the context. apiCall := func(ctx context.Context, username string) string { // props are retrieved from a context props := FromContext(ctx) // the remote API address is taken from these props (or default URL is used instead). url := props.Get("api", "url", "http://api") url += "?username=" + username apiRequest, _ := http.NewRequest("GET", url, nil) // the properties are propagated further within the headers props.InjectIntoHeaders(apiRequest.Header) // ...execute remote call // _, _ = http.DefaultClient.Do(apiRequest) return fmt.Sprintf("Calling remote API at %s with headers:\n%+v", url, apiRequest.Header) } // execute remote call and print the results back w.Write([]byte(apiCall(ctx, r.URL.Query().Get("username")))) } w := httptest.NewRecorder() handler(w, req) res := w.Result() responseBytes, _ := ioutil.ReadAll(res.Body) fmt.Println(string(responseBytes))
Output: Calling remote API at http://my-custom-api?username=Alex with headers: map[X-Service-Api-Url:[http://my-custom-api] X-Service-Billing-Branch:[hotfix-123]]
func InjectIntoHeadersFromContext ¶
InjectIntoHeadersFromContext adds properties from context into http.Header
func ParsePropertyName ¶ added in v0.2.0
ParsePropertyName parses a string like "x-service-api-branch" into service name ("api"), property name ("branch"), and a boolean success flag
func ReplaceUrlBranch ¶
ReplaceUrlBranch replaces branch placeholder in URL with an actual branch name.
Types ¶
type Properties ¶ added in v0.2.0
Properties grouped by a service name
func FromContext ¶
func FromContext(ctx context.Context) Properties
FromContext returns properties from context. If there are no properties in the context, an empty usable instance is returned.
func FromHeaders ¶
func FromHeaders(headers http.Header) Properties
FromHeaders constructs properties from HTTP headers
func FromQueryString ¶
func FromQueryString(query string) Properties
FromQueryString parses properties from an HTTP query string
func FromQueryValues ¶ added in v0.2.0
func FromQueryValues(values url.Values) Properties
FromQueryValues parses properties from a parsed HTTP query string
func FromRequest ¶ added in v0.2.0
func FromRequest(req *http.Request) Properties
FromRequest constructs properties from HTTP headers and query string of the request. Query string properties have a priority over HTTP headers.
Example ¶
An example HTTP client and server that exchange properties via HTTP headers
// a client defines some properties to be sent to a server props := New() props.Set("api", "version", "1.0.1") props.Set("billing", "branch", "bugfix-123") req := httptest.NewRequest(http.MethodGet, "/", nil) // insert the props into request headers props.InjectIntoHeaders(req.Header) // a simple request handler that parses incoming properties and prints them back in response handler := func(w http.ResponseWriter, r *http.Request) { props := FromHeaders(r.Header) // print an API version, or use a default version 1.0.0 w.Write([]byte(fmt.Sprintf("API version: %s\n", props.Get("api", "version", "1.0.0")))) // configure a billing service URL with a custom branch, or use a default `main` branch billingServiceUrl := ReplaceUrlBranch( "http://billing-$branch", props.Get("billing", "branch", "main"), ) w.Write([]byte(fmt.Sprintf("Billing service url: %s\n", billingServiceUrl))) } // call the handler above w := httptest.NewRecorder() handler(w, req) res := w.Result() responseBytes, _ := ioutil.ReadAll(res.Body) fmt.Println(string(responseBytes))
Output: API version: 1.0.1 Billing service url: http://billing-bugfix-123
func (Properties) Get ¶ added in v0.2.0
func (p Properties) Get(serviceName, prop, defaultValue string) string
Get returns an property value for a given service
func (Properties) GetBool ¶ added in v0.3.0
func (p Properties) GetBool(serviceName, prop string, defaultValue bool) bool
GetBool returns a property value for a given service as boolean
func (Properties) GetByService ¶ added in v0.2.0
func (p Properties) GetByService(serviceName string) Values
GetByService returns all options for a given service
func (Properties) GetDuration ¶ added in v0.2.0
GetDuration returns a property value for a given service as time.Duration
func (Properties) GetInt ¶ added in v0.2.0
func (p Properties) GetInt(serviceName, prop string, defaultValue int) int
GetInt returns a property value for a given service as an integer
func (Properties) HasProperty ¶ added in v0.2.0
func (p Properties) HasProperty(serviceName, option string) bool
HasProperty checks if a given property exists for a service
func (Properties) HasService ¶ added in v0.2.0
func (p Properties) HasService(serviceName string) bool
HasService checks if there are options for a given service
func (Properties) HeaderMap ¶ added in v0.2.0
func (p Properties) HeaderMap() map[string]string
HeaderMap returns options as a map of HTTP headers
func (Properties) InjectIntoContext ¶ added in v0.2.0
func (p Properties) InjectIntoContext(ctx context.Context) context.Context
InjectIntoContext adds properties to the context
func (Properties) InjectIntoHeaders ¶ added in v0.2.0
func (p Properties) InjectIntoHeaders(headers http.Header)
InjectIntoHeaders adds property headers to http.Header
func (Properties) Merge ¶ added in v0.2.0
func (p Properties) Merge(other Properties) Properties
Merge merges two sets of properties. The receiver is modified and returned for chaining.
func (Properties) QueryString ¶ added in v0.2.0
func (p Properties) QueryString() string
QueryString converts properties to an HTTP query string
func (Properties) QueryValues ¶ added in v0.2.0
func (p Properties) QueryValues() url.Values
QueryValues converts properties to a set of HTTP query parameters
func (Properties) Set ¶ added in v0.2.0
func (p Properties) Set(serviceName, prop, value string) Properties
Set sets a property value for a given service