Skip to content

Commit c982e6f

Browse files
authored
feat: add new envelope transport (#1094)
1 parent 10448bc commit c982e6f

File tree

15 files changed

+2991
-549
lines changed

15 files changed

+2991
-549
lines changed

dsn.go

Lines changed: 11 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -1,233 +1,37 @@
11
package sentry
22

33
import (
4-
"encoding/json"
5-
"fmt"
6-
"net/url"
7-
"strconv"
8-
"strings"
9-
"time"
4+
"github.com/getsentry/sentry-go/internal/protocol"
105
)
116

12-
type scheme string
7+
// Re-export protocol types to maintain public API compatibility
138

14-
const (
15-
schemeHTTP scheme = "http"
16-
schemeHTTPS scheme = "https"
17-
)
18-
19-
func (scheme scheme) defaultPort() int {
20-
switch scheme {
21-
case schemeHTTPS:
22-
return 443
23-
case schemeHTTP:
24-
return 80
25-
default:
26-
return 80
27-
}
9+
// Dsn is used as the remote address source to client transport.
10+
type Dsn struct {
11+
protocol.Dsn
2812
}
2913

3014
// DsnParseError represents an error that occurs if a Sentry
3115
// DSN cannot be parsed.
32-
type DsnParseError struct {
33-
Message string
34-
}
35-
36-
func (e DsnParseError) Error() string {
37-
return "[Sentry] DsnParseError: " + e.Message
38-
}
39-
40-
// Dsn is used as the remote address source to client transport.
41-
type Dsn struct {
42-
scheme scheme
43-
publicKey string
44-
secretKey string
45-
host string
46-
port int
47-
path string
48-
projectID string
49-
}
16+
type DsnParseError = protocol.DsnParseError
5017

5118
// NewDsn creates a Dsn by parsing rawURL. Most users will never call this
5219
// function directly. It is provided for use in custom Transport
5320
// implementations.
5421
func NewDsn(rawURL string) (*Dsn, error) {
55-
// Parse
56-
parsedURL, err := url.Parse(rawURL)
22+
protocolDsn, err := protocol.NewDsn(rawURL)
5723
if err != nil {
58-
return nil, &DsnParseError{fmt.Sprintf("invalid url: %v", err)}
59-
}
60-
61-
// Scheme
62-
var scheme scheme
63-
switch parsedURL.Scheme {
64-
case "http":
65-
scheme = schemeHTTP
66-
case "https":
67-
scheme = schemeHTTPS
68-
default:
69-
return nil, &DsnParseError{"invalid scheme"}
70-
}
71-
72-
// PublicKey
73-
publicKey := parsedURL.User.Username()
74-
if publicKey == "" {
75-
return nil, &DsnParseError{"empty username"}
76-
}
77-
78-
// SecretKey
79-
var secretKey string
80-
if parsedSecretKey, ok := parsedURL.User.Password(); ok {
81-
secretKey = parsedSecretKey
82-
}
83-
84-
// Host
85-
host := parsedURL.Hostname()
86-
if host == "" {
87-
return nil, &DsnParseError{"empty host"}
88-
}
89-
90-
// Port
91-
var port int
92-
if p := parsedURL.Port(); p != "" {
93-
port, err = strconv.Atoi(p)
94-
if err != nil {
95-
return nil, &DsnParseError{"invalid port"}
96-
}
97-
} else {
98-
port = scheme.defaultPort()
99-
}
100-
101-
// ProjectID
102-
if parsedURL.Path == "" || parsedURL.Path == "/" {
103-
return nil, &DsnParseError{"empty project id"}
104-
}
105-
pathSegments := strings.Split(parsedURL.Path[1:], "/")
106-
projectID := pathSegments[len(pathSegments)-1]
107-
108-
if projectID == "" {
109-
return nil, &DsnParseError{"empty project id"}
110-
}
111-
112-
// Path
113-
var path string
114-
if len(pathSegments) > 1 {
115-
path = "/" + strings.Join(pathSegments[0:len(pathSegments)-1], "/")
116-
}
117-
118-
return &Dsn{
119-
scheme: scheme,
120-
publicKey: publicKey,
121-
secretKey: secretKey,
122-
host: host,
123-
port: port,
124-
path: path,
125-
projectID: projectID,
126-
}, nil
127-
}
128-
129-
// String formats Dsn struct into a valid string url.
130-
func (dsn Dsn) String() string {
131-
var url string
132-
url += fmt.Sprintf("%s://%s", dsn.scheme, dsn.publicKey)
133-
if dsn.secretKey != "" {
134-
url += fmt.Sprintf(":%s", dsn.secretKey)
135-
}
136-
url += fmt.Sprintf("@%s", dsn.host)
137-
if dsn.port != dsn.scheme.defaultPort() {
138-
url += fmt.Sprintf(":%d", dsn.port)
24+
return nil, err
13925
}
140-
if dsn.path != "" {
141-
url += dsn.path
142-
}
143-
url += fmt.Sprintf("/%s", dsn.projectID)
144-
return url
145-
}
146-
147-
// Get the scheme of the DSN.
148-
func (dsn Dsn) GetScheme() string {
149-
return string(dsn.scheme)
150-
}
151-
152-
// Get the public key of the DSN.
153-
func (dsn Dsn) GetPublicKey() string {
154-
return dsn.publicKey
155-
}
156-
157-
// Get the secret key of the DSN.
158-
func (dsn Dsn) GetSecretKey() string {
159-
return dsn.secretKey
160-
}
161-
162-
// Get the host of the DSN.
163-
func (dsn Dsn) GetHost() string {
164-
return dsn.host
165-
}
166-
167-
// Get the port of the DSN.
168-
func (dsn Dsn) GetPort() int {
169-
return dsn.port
170-
}
171-
172-
// Get the path of the DSN.
173-
func (dsn Dsn) GetPath() string {
174-
return dsn.path
26+
return &Dsn{Dsn: *protocolDsn}, nil
17527
}
17628

177-
// Get the project ID of the DSN.
178-
func (dsn Dsn) GetProjectID() string {
179-
return dsn.projectID
180-
}
181-
182-
// GetAPIURL returns the URL of the envelope endpoint of the project
183-
// associated with the DSN.
184-
func (dsn Dsn) GetAPIURL() *url.URL {
185-
var rawURL string
186-
rawURL += fmt.Sprintf("%s://%s", dsn.scheme, dsn.host)
187-
if dsn.port != dsn.scheme.defaultPort() {
188-
rawURL += fmt.Sprintf(":%d", dsn.port)
189-
}
190-
if dsn.path != "" {
191-
rawURL += dsn.path
192-
}
193-
rawURL += fmt.Sprintf("/api/%s/%s/", dsn.projectID, "envelope")
194-
parsedURL, _ := url.Parse(rawURL)
195-
return parsedURL
196-
}
197-
198-
// RequestHeaders returns all the necessary headers that have to be used in the transport when seinding events
29+
// RequestHeaders returns all the necessary headers that have to be used in the transport when sending events
19930
// to the /store endpoint.
20031
//
20132
// Deprecated: This method shall only be used if you want to implement your own transport that sends events to
20233
// the /store endpoint. If you're using the transport provided by the SDK, all necessary headers to authenticate
20334
// against the /envelope endpoint are added automatically.
20435
func (dsn Dsn) RequestHeaders() map[string]string {
205-
auth := fmt.Sprintf("Sentry sentry_version=%s, sentry_timestamp=%d, "+
206-
"sentry_client=sentry.go/%s, sentry_key=%s", apiVersion, time.Now().Unix(), SDKVersion, dsn.publicKey)
207-
208-
if dsn.secretKey != "" {
209-
auth = fmt.Sprintf("%s, sentry_secret=%s", auth, dsn.secretKey)
210-
}
211-
212-
return map[string]string{
213-
"Content-Type": "application/json",
214-
"X-Sentry-Auth": auth,
215-
}
216-
}
217-
218-
// MarshalJSON converts the Dsn struct to JSON.
219-
func (dsn Dsn) MarshalJSON() ([]byte, error) {
220-
return json.Marshal(dsn.String())
221-
}
222-
223-
// UnmarshalJSON converts JSON data to the Dsn struct.
224-
func (dsn *Dsn) UnmarshalJSON(data []byte) error {
225-
var str string
226-
_ = json.Unmarshal(data, &str)
227-
newDsn, err := NewDsn(str)
228-
if err != nil {
229-
return err
230-
}
231-
*dsn = *newDsn
232-
return nil
36+
return dsn.Dsn.RequestHeaders(SDKVersion)
23337
}

0 commit comments

Comments
 (0)