Skip to content

Commit

Permalink
BREAKING CHANGE:Remove sub-packages, refactor
Browse files Browse the repository at this point in the history
BREAKING CHANGE!!!

This change focuses on removing the sub-packages that probably should
not have been included here, and moving moving the needed functionality
into the main wrp package.

Themes:
- Validators became Processor implementors, making composition easier.
- A number of Modifiers were added to replace other types of modifiers.
  An example of this is the ReplaceAnySelfLocator().
- Taking advantage of generics for less code when possible.
- Testing for the different types of messages so mistakes are caught
  more automatically using expectations and reflection against the
  Message struct.  This should help in detecting mistakes if fields are
  added.
  • Loading branch information
schmidtw committed Feb 2, 2025
1 parent 88a0d1e commit 5faa7fb
Show file tree
Hide file tree
Showing 66 changed files with 2,993 additions and 11,384 deletions.
14 changes: 2 additions & 12 deletions env.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,7 @@ import (
)

func toEnvMap(msg any) map[string]string {
v := reflect.ValueOf(msg)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
return nil
}

v = v.Elem()
v := reflect.ValueOf(msg).Elem()
t := v.Type()
envVars := make(map[string]string)

Expand Down Expand Up @@ -82,12 +77,7 @@ func toEnvMap(msg any) map[string]string {
}

func fromEnvMap(envVars []string, msg any) error {
v := reflect.ValueOf(msg)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
return fmt.Errorf("msg must be a pointer to a struct")
}

v = v.Elem()
v := reflect.ValueOf(msg).Elem()
t := v.Type()
envMap := make(map[string]string)
for _, envVar := range envVars {
Expand Down
4 changes: 0 additions & 4 deletions env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,6 @@ func TestEnvMap(t *testing.T) {
output: map[string]string{
"LABEL": "hello world,goodbye world",
},
}, {
name: "Not a struct",
input: "not a struct",
onlyTo: true,
},
{
name: "wrp.Message",
Expand Down
27 changes: 4 additions & 23 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,37 +1,18 @@
module github.com/xmidt-org/wrp-go/v3
module github.com/xmidt-org/wrp-go/v4

go 1.21

require (
github.com/davecgh/go-spew v1.1.1
github.com/go-kit/kit v0.13.0
github.com/go-kit/log v0.2.1
github.com/google/uuid v1.6.0
github.com/prometheus/client_golang v1.20.5
github.com/stretchr/testify v1.9.0
github.com/ugorji/go/codec v1.2.12
github.com/xmidt-org/httpaux v0.4.0
github.com/xmidt-org/sallust v0.2.2
github.com/xmidt-org/touchstone v0.1.7
github.com/xmidt-org/webpa-common v1.11.9
go.uber.org/multierr v1.11.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.59.1 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect
go.uber.org/dig v1.18.0 // indirect
go.uber.org/fx v1.22.2 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/sys v0.25.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
1,150 changes: 3 additions & 1,147 deletions go.sum

Large diffs are not rendered by default.

239 changes: 239 additions & 0 deletions header.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
// SPDX-FileCopyrightText: 2022 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

package wrp

import (
"fmt"
"net/http"
"reflect"
"strconv"
"strings"
)

func toHeaders(msg *Message, headers http.Header) {
v := reflect.ValueOf(msg).Elem()
t := v.Type()

for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
tag := parseHttpTag(field.Tag.Get("http"))
if tag == nil {
continue
}

if isEmptyValue(value) {
if tag.omitempty {
continue
}
headers.Set(tag.primary, "")

Check warning on line 30 in header.go

View check run for this annotation

Codecov / codecov/patch

header.go#L30

Added line #L30 was not covered by tests
}

switch value.Kind() {
case reflect.String:
headers.Set(tag.primary, value.String())
case reflect.Ptr:
if value.Elem().Kind() == reflect.Int64 {
if !value.IsNil() {
headers.Set(tag.primary, fmt.Sprintf("%d", value.Elem().Int()))
}
}
case reflect.Slice:
if value.Type().Elem().Kind() == reflect.String {
if tag.multiline {
for _, s := range value.Interface().([]string) {
headers.Add(tag.primary, s)
}
} else {
headers.Set(tag.primary, strings.Join(value.Interface().([]string), ","))
}
}
case reflect.Map:
if value.Type().Key().Kind() == reflect.String && value.Type().Elem().Kind() == reflect.String {
for k, v := range value.Interface().(map[string]string) {
headers.Add(tag.primary, k+"="+v)
}
}
case reflect.Int, reflect.Int64:
headers.Add(tag.primary, fmt.Sprintf("%d", value.Int()))
}
}
}

func fromHeaders(headers http.Header, msg *Message) error {
v := reflect.ValueOf(msg).Elem()
t := v.Type()

for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
tag := parseHttpTag(field.Tag.Get("http"))
if tag == nil {
continue
}

switch value.Kind() {
case reflect.TypeOf(MessageType(0)).Kind():
v := tag.get(headers)
if v == "" {
continue
}
msgType := StringToMessageType(v)
if msgType == LastMessageType {
return fmt.Errorf("unknown message type: %s", v)
}

Check warning on line 85 in header.go

View check run for this annotation

Codecov / codecov/patch

header.go#L84-L85

Added lines #L84 - L85 were not covered by tests
value.Set(reflect.ValueOf(msgType))
case reflect.String:
value.SetString(tag.get(headers))
case reflect.Ptr:
if value.Type().Elem().Kind() == reflect.Int64 {
v := tag.get(headers)
if v == "" {
continue
}
intVal, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return err
}
value.Set(reflect.ValueOf(&intVal))
}
case reflect.Slice:
if value.Type().Elem().Kind() == reflect.String {
lines := tag.all(headers)
final := make([]string, 0, len(lines))

for _, line := range lines {
list := strings.Split(line, ",")
for _, item := range list {
item = strings.TrimSpace(item)
if item != "" {
final = append(final, item)
}
}
}
if len(final) > 0 {
value.Set(reflect.ValueOf(final))
}
}
case reflect.Map:
if value.Type().Key().Kind() == reflect.String && value.Type().Elem().Kind() == reflect.String {
mapValue := make(map[string]string)
slice := tag.all(headers)
for _, item := range slice {
parts := strings.SplitN(item, "=", 2)
for i := range parts {
parts[i] = strings.TrimSpace(parts[i])
}

// If there is no value, append an empty string so that the
// key is still present
parts = append(parts, "")

if parts[0] != "" {
mapValue[parts[0]] = parts[1]
}
}
if len(mapValue) > 0 {
value.Set(reflect.ValueOf(mapValue))
}
}
case reflect.Int, reflect.Int64:
v := tag.get(headers)
if v == "" {
continue
}
intVal, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return err
}
value.SetInt(intVal)
}
}

return nil
}

func defaultAHeader(headers *http.Header, key string, value []string) {
list := headers.Values(key)
for _, v := range list {
v = strings.TrimSpace(v)
if v != "" {
return
}
}

if value == nil {
return
}

Check warning on line 168 in header.go

View check run for this annotation

Codecov / codecov/patch

header.go#L167-L168

Added lines #L167 - L168 were not covered by tests

headers.Set(key, value[0])
for i := 1; i < len(value); i++ {
headers.Add(key, value[i])
}

Check warning on line 173 in header.go

View check run for this annotation

Codecov / codecov/patch

header.go#L172-L173

Added lines #L172 - L173 were not covered by tests
}

type httpTag struct {
primary string
accepted []string
multiline bool
omitempty bool
}

func parseHttpTag(tag string) *httpTag {
if tag == "" || tag == "-" {
return nil
}

tagParts := strings.Split(tag, ",")

rv := httpTag{
primary: http.CanonicalHeaderKey(strings.TrimSpace(tagParts[0])),
accepted: make([]string, 0, len(tagParts)),
}

if rv.primary == "" {
return nil
}

Check warning on line 197 in header.go

View check run for this annotation

Codecov / codecov/patch

header.go#L196-L197

Added lines #L196 - L197 were not covered by tests

for _, val := range tagParts[1:] {
val = strings.TrimSpace(val)

switch val {
case "omitempty":
rv.omitempty = true
case "multiline":
rv.multiline = true
default:
rv.accepted = append(rv.accepted, val)
}
}

return &rv
}

func (tag httpTag) get(headers http.Header) string {
if v := headers.Get(tag.primary); v != "" {
return v
}
for _, accepted := range tag.accepted {
if v := headers.Get(accepted); v != "" {
return v
}
}

return ""
}

func (tag httpTag) all(headers http.Header) []string {
if v := headers[tag.primary]; len(v) > 0 {
return v
}
for _, accepted := range tag.accepted {
if v := headers[accepted]; len(v) > 0 {
return v
}
}

return nil
}
Loading

0 comments on commit 5faa7fb

Please sign in to comment.