util.go

 1// Copyright The OpenTelemetry Authors
 2// SPDX-License-Identifier: Apache-2.0
 3
 4package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
 5
 6import (
 7	"net"
 8	"net/http"
 9	"strconv"
10	"strings"
11
12	"go.opentelemetry.io/otel"
13	"go.opentelemetry.io/otel/attribute"
14	semconvNew "go.opentelemetry.io/otel/semconv/v1.26.0"
15)
16
17// splitHostPort splits a network address hostport of the form "host",
18// "host%zone", "[host]", "[host%zone], "host:port", "host%zone:port",
19// "[host]:port", "[host%zone]:port", or ":port" into host or host%zone and
20// port.
21//
22// An empty host is returned if it is not provided or unparsable. A negative
23// port is returned if it is not provided or unparsable.
24func splitHostPort(hostport string) (host string, port int) {
25	port = -1
26
27	if strings.HasPrefix(hostport, "[") {
28		addrEnd := strings.LastIndex(hostport, "]")
29		if addrEnd < 0 {
30			// Invalid hostport.
31			return
32		}
33		if i := strings.LastIndex(hostport[addrEnd:], ":"); i < 0 {
34			host = hostport[1:addrEnd]
35			return
36		}
37	} else {
38		if i := strings.LastIndex(hostport, ":"); i < 0 {
39			host = hostport
40			return
41		}
42	}
43
44	host, pStr, err := net.SplitHostPort(hostport)
45	if err != nil {
46		return
47	}
48
49	p, err := strconv.ParseUint(pStr, 10, 16)
50	if err != nil {
51		return
52	}
53	return host, int(p) // nolint: gosec  // Byte size checked 16 above.
54}
55
56func requiredHTTPPort(https bool, port int) int { // nolint:revive
57	if https {
58		if port > 0 && port != 443 {
59			return port
60		}
61	} else {
62		if port > 0 && port != 80 {
63			return port
64		}
65	}
66	return -1
67}
68
69func serverClientIP(xForwardedFor string) string {
70	if idx := strings.Index(xForwardedFor, ","); idx >= 0 {
71		xForwardedFor = xForwardedFor[:idx]
72	}
73	return xForwardedFor
74}
75
76func netProtocol(proto string) (name string, version string) {
77	name, version, _ = strings.Cut(proto, "/")
78	name = strings.ToLower(name)
79	return name, version
80}
81
82var methodLookup = map[string]attribute.KeyValue{
83	http.MethodConnect: semconvNew.HTTPRequestMethodConnect,
84	http.MethodDelete:  semconvNew.HTTPRequestMethodDelete,
85	http.MethodGet:     semconvNew.HTTPRequestMethodGet,
86	http.MethodHead:    semconvNew.HTTPRequestMethodHead,
87	http.MethodOptions: semconvNew.HTTPRequestMethodOptions,
88	http.MethodPatch:   semconvNew.HTTPRequestMethodPatch,
89	http.MethodPost:    semconvNew.HTTPRequestMethodPost,
90	http.MethodPut:     semconvNew.HTTPRequestMethodPut,
91	http.MethodTrace:   semconvNew.HTTPRequestMethodTrace,
92}
93
94func handleErr(err error) {
95	if err != nil {
96		otel.Handle(err)
97	}
98}