-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtypes.go
90 lines (70 loc) · 2.02 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package natshttp
import (
"fmt"
"net/http"
"net/url"
"strings"
"github.com/nats-io/nats.go"
"github.com/juju/errors"
)
const (
HeaderPath = "X-Path"
HeaderQuery = "X-Query"
HeaderFragment = "X-Fragment"
HeaderStatus = "X-Status"
HeaderStatusCode = "X-Status-Code"
UrlScheme = "nats+http"
)
type Result[T any] struct {
Value T
Error error
}
func ReqToMsg(req *http.Request, msg *nats.Msg) error {
URL := req.URL
if URL.Scheme != UrlScheme {
return errors.Errorf("natshttp: url scheme must be '%s'", UrlScheme)
}
h := msg.Header
// we can't reliably transform the subject back into the PATH as there could be paths like /foo.zst
// we add it explicitly as a header to avoid this problem
h.Set(HeaderPath, URL.Path)
if URL.RawQuery != "" {
h.Set(HeaderQuery, URL.RawQuery)
}
if URL.RawFragment != "" {
h.Set(HeaderFragment, URL.RawFragment)
}
path := strings.ReplaceAll(URL.Path, "/", ".")
if len(path) == 1 {
path = ""
}
// <host>.<path>.<method>
msg.Subject = fmt.Sprintf("%s%s.%s", URL.Host, path, req.Method)
return nil
}
func MsgToRequest(prefix string, msg *nats.Msg, req *http.Request) error {
subject := msg.Subject
if subject[:len(prefix)] != prefix {
return errors.Errorf("subject '%s' doesn't begin with prefix '%s'", subject, prefix)
}
components := strings.Split(subject[len(prefix):], ".")
// last component of the subject is the Http Method
method := components[len(components)-1]
switch method {
case http.MethodGet, http.MethodPut, http.MethodPost, http.MethodDelete, http.MethodConnect, http.MethodHead, http.MethodOptions, http.MethodTrace, http.MethodPatch:
req.Method = method
default:
return errors.Errorf("natshttp: invalid http method '%s' in subject '%s'", method, subject)
}
req.Proto = "HTTP/1.1"
h := msg.Header
// join all but the last component
req.URL = &url.URL{
Scheme: UrlScheme,
Host: prefix,
Path: h.Get(HeaderPath),
RawQuery: h.Get(HeaderQuery),
RawFragment: h.Get(HeaderFragment),
}
return nil
}