Skip to content

Commit e9c5f74

Browse files
authored
Fix serve origin and path overrides (#189)
* Fix serve origin and path overrides * Add changeset * Fix
1 parent 062a493 commit e9c5f74

File tree

5 files changed

+305
-29
lines changed

5 files changed

+305
-29
lines changed

.changeset/hip-ducks-join.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"inngestgo": patch
3+
---
4+
5+
Fix serve URL overrides

handler.go

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,14 @@ func (h *handler) inBandSync(
536536
Status: 400,
537537
}
538538
}
539-
if h.URL != nil {
540-
appURL = h.URL
539+
540+
appURL, err = overrideURL(appURL, h.handlerOpts)
541+
if err != nil {
542+
h.Logger.Error("error parsing app URL", "error", err)
543+
return publicerr.Error{
544+
Err: fmt.Errorf("error parsing app URL: %w", err),
545+
Status: 400,
546+
}
541547
}
542548

543549
fns, err := createFunctionConfigs(h.appName, h.funcs, *appURL, false)
@@ -596,9 +602,6 @@ func (h *handler) outOfBandSync(w http.ResponseWriter, r *http.Request) error {
596602
h.l.Lock()
597603
defer h.l.Unlock()
598604

599-
scheme := httputil.GetScheme(r)
600-
host := r.Host
601-
602605
// Get the sync ID from the URL and then remove it, since we don't want the
603606
// sync ID to show in the function URLs (that would affect the checksum and
604607
// is ugly in the UI)
@@ -607,15 +610,28 @@ func (h *handler) outOfBandSync(w http.ResponseWriter, r *http.Request) error {
607610
qp.Del("deployId")
608611
r.URL.RawQuery = qp.Encode()
609612

610-
pathAndParams := r.URL.String()
613+
appURL, err := url.Parse(fmt.Sprintf(
614+
"%s://%s%s?%s",
615+
httputil.GetScheme(r),
616+
r.Host,
617+
r.URL.Path,
618+
r.URL.RawQuery,
619+
))
620+
if err != nil {
621+
return fmt.Errorf("error parsing request URL: %w", err)
622+
}
623+
appURL, err = overrideURL(appURL, h.handlerOpts)
624+
if err != nil {
625+
return fmt.Errorf("error overriding request URL: %w", err)
626+
}
611627

612628
appVersion := ""
613629
if h.AppVersion != nil {
614630
appVersion = *h.AppVersion
615631
}
616632

617633
config := types.RegisterRequest{
618-
URL: fmt.Sprintf("%s://%s%s", scheme, host, pathAndParams),
634+
URL: appURL.String(),
619635
V: "1",
620636
DeployType: types.DeployTypePing,
621637
SDK: HeaderValueSDK,
@@ -628,7 +644,7 @@ func (h *handler) outOfBandSync(w http.ResponseWriter, r *http.Request) error {
628644
AppVersion: appVersion,
629645
}
630646

631-
fns, err := createFunctionConfigs(h.appName, h.funcs, *h.url(r), false)
647+
fns, err := createFunctionConfigs(h.appName, h.funcs, *appURL, false)
632648
if err != nil {
633649
return fmt.Errorf("error creating function configs: %w", err)
634650
}
@@ -695,17 +711,6 @@ func (h *handler) outOfBandSync(w http.ResponseWriter, r *http.Request) error {
695711
return nil
696712
}
697713

698-
func (h *handler) url(r *http.Request) *url.URL {
699-
if h.URL != nil {
700-
return h.URL
701-
}
702-
703-
// Get the current URL.
704-
scheme := httputil.GetScheme(r)
705-
u, _ := url.Parse(fmt.Sprintf("%s://%s%s", scheme, r.Host, r.RequestURI))
706-
return u
707-
}
708-
709714
func createFunctionConfigs(
710715
appName string,
711716
fns []ServableFunction,
@@ -1007,14 +1012,6 @@ func (h *handler) createSecureInspection() (*secureInspection, error) {
10071012
env = &val
10081013
}
10091014

1010-
var serveOrigin, servePath *string
1011-
if h.URL != nil {
1012-
serveOriginStr := h.URL.Scheme + "://" + h.URL.Host
1013-
serveOrigin = &serveOriginStr
1014-
1015-
servePath = &h.URL.Path
1016-
}
1017-
10181015
authenticationSucceeded = true
10191016
insecureInspection, err := h.createInsecureInspection(&authenticationSucceeded)
10201017
if err != nil {
@@ -1033,8 +1030,8 @@ func (h *handler) createSecureInspection() (*secureInspection, error) {
10331030
SDKVersion: SDKVersion,
10341031
SigningKeyFallbackHash: signingKeyFallbackHash,
10351032
SigningKeyHash: signingKeyHash,
1036-
ServeOrigin: serveOrigin,
1037-
ServePath: servePath,
1033+
ServeOrigin: serveOriginOverride(h.handlerOpts),
1034+
ServePath: servePathOverride(h.handlerOpts),
10381035
}, nil
10391036
}
10401037

handler_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,84 @@ func TestInBandSync(t *testing.T) {
10091009
r.NoError(err)
10101010
r.Equal("", string(respByt))
10111011
})
1012+
1013+
t.Run("override URL with env vars", func(t *testing.T) {
1014+
t.Setenv("INNGEST_SERVE_HOST", "https://override.com")
1015+
t.Setenv("INNGEST_SERVE_PATH", "/override/path")
1016+
1017+
r := require.New(t)
1018+
ctx := context.Background()
1019+
1020+
sig, _ := Sign(ctx, time.Now(), []byte(testKey), reqBodyByt)
1021+
req, err := http.NewRequest(
1022+
http.MethodPut,
1023+
server.URL,
1024+
bytes.NewReader(reqBodyByt),
1025+
)
1026+
r.NoError(err)
1027+
req.Header.Set("x-inngest-signature", sig)
1028+
req.Header.Set("x-inngest-sync-kind", "in_band")
1029+
resp, err := http.DefaultClient.Do(req)
1030+
r.NoError(err)
1031+
r.Equal(http.StatusOK, resp.StatusCode)
1032+
r.Equal(resp.Header.Get("x-inngest-sync-kind"), "in_band")
1033+
1034+
var respBody inBandSynchronizeResponse
1035+
err = json.NewDecoder(resp.Body).Decode(&respBody)
1036+
r.NoError(err)
1037+
1038+
r.Equal(
1039+
inBandSynchronizeResponse{
1040+
AppID: c.AppID(),
1041+
Env: toPtr("my-env"),
1042+
Functions: []ifn.SyncConfig{{
1043+
Name: "my-fn",
1044+
Slug: fmt.Sprintf("%s-my-fn", c.AppID()),
1045+
Steps: map[string]ifn.SDKStep{
1046+
"step": {
1047+
ID: "step",
1048+
Name: "my-fn",
1049+
Runtime: map[string]any{
1050+
"url": fmt.Sprintf("https://override.com/override/path?fnId=%s-my-fn&step=step", c.AppID()),
1051+
},
1052+
},
1053+
},
1054+
Triggers: []ifn.Trigger{EventTrigger("my-event", nil)},
1055+
}},
1056+
Inspection: map[string]any{
1057+
"api_origin": "https://api.inngest.com",
1058+
"app_id": "test-in-band-sync",
1059+
"authentication_succeeded": true,
1060+
"capabilities": map[string]any{
1061+
"in_band_sync": "v1",
1062+
"trust_probe": "v1",
1063+
"connect": "v1",
1064+
},
1065+
"env": "my-env",
1066+
"event_api_origin": "https://inn.gs",
1067+
"event_key_hash": "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090",
1068+
"framework": "",
1069+
"function_count": float64(1),
1070+
"has_event_key": true,
1071+
"has_signing_key": true,
1072+
"has_signing_key_fallback": true,
1073+
"mode": "cloud",
1074+
"schema_version": "2024-05-24",
1075+
"sdk_language": "go",
1076+
"sdk_version": SDKVersion,
1077+
"serve_origin": "https://override.com",
1078+
"serve_path": "/override/path",
1079+
"signing_key_fallback_hash": "signkey-test-df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119",
1080+
"signing_key_hash": "signkey-test-b2ed992186a5cb19f6668aade821f502c1d00970dfd0e35128d51bac4649916c",
1081+
},
1082+
SDKAuthor: "inngest",
1083+
SDKLanguage: "go",
1084+
SDKVersion: SDKVersion,
1085+
URL: "https://override.com/override/path",
1086+
},
1087+
respBody,
1088+
)
1089+
})
10121090
}
10131091

10141092
func TestConnectSync(t *testing.T) {

options.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package inngestgo
2+
3+
import (
4+
"fmt"
5+
"net/url"
6+
"os"
7+
)
8+
9+
func serveOriginOverride(hOpts handlerOpts) *string {
10+
if hOpts.ServeOrigin != nil {
11+
return hOpts.ServeOrigin
12+
}
13+
if hOpts.URL != nil {
14+
return Ptr(fmt.Sprintf("%s://%s", hOpts.URL.Scheme, hOpts.URL.Host))
15+
}
16+
if v := os.Getenv("INNGEST_SERVE_HOST"); v != "" {
17+
return &v
18+
}
19+
return nil
20+
}
21+
22+
func servePathOverride(hOpts handlerOpts) *string {
23+
if hOpts.ServePath != nil {
24+
return hOpts.ServePath
25+
}
26+
if hOpts.URL != nil {
27+
return Ptr(hOpts.URL.Path)
28+
}
29+
if v := os.Getenv("INNGEST_SERVE_PATH"); v != "" {
30+
return &v
31+
}
32+
return nil
33+
}
34+
35+
func overrideURL(u *url.URL, hOpts handlerOpts) (*url.URL, error) {
36+
origin := fmt.Sprintf("%s://%s", u.Scheme, u.Host)
37+
if override := serveOriginOverride(hOpts); override != nil {
38+
origin = *override
39+
}
40+
41+
path := u.Path
42+
if override := servePathOverride(hOpts); override != nil {
43+
path = *override
44+
}
45+
46+
rawURL := fmt.Sprintf("%s%s", origin, path)
47+
if u.RawQuery != "" {
48+
rawURL += "?" + u.RawQuery
49+
}
50+
51+
return url.Parse(rawURL)
52+
}

options_test.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package inngestgo
2+
3+
import (
4+
"fmt"
5+
"net/url"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestServeOriginOverride(t *testing.T) {
12+
t.Run("no override", func(t *testing.T) {
13+
r := require.New(t)
14+
hOpts := handlerOpts{}
15+
r.Nil(serveOriginOverride(hOpts))
16+
})
17+
18+
t.Run("ServeOrigin has highest precedence", func(t *testing.T) {
19+
r := require.New(t)
20+
21+
t.Setenv("INNGEST_SERVE_HOST", "https://env-var.com")
22+
url, err := url.Parse("https://URL.com/baz/qux")
23+
r.NoError(err)
24+
hOpts := handlerOpts{
25+
ServeOrigin: StrPtr("https://ServeOrigin.com/foo/bar"),
26+
URL: url,
27+
}
28+
r.Equal(*hOpts.ServeOrigin, *serveOriginOverride(hOpts))
29+
})
30+
31+
t.Run("URL has second highest precedence", func(t *testing.T) {
32+
r := require.New(t)
33+
34+
t.Setenv("INNGEST_SERVE_HOST", "https://env-var.com")
35+
url, err := url.Parse("https://URL.com/baz/qux")
36+
r.NoError(err)
37+
hOpts := handlerOpts{URL: url}
38+
r.Equal(fmt.Sprintf("%s://%s", url.Scheme, url.Host), *serveOriginOverride(hOpts))
39+
})
40+
41+
t.Run("INNGEST_SERVE_HOST has lowest precedence", func(t *testing.T) {
42+
r := require.New(t)
43+
t.Setenv("INNGEST_SERVE_HOST", "https://example.com")
44+
hOpts := handlerOpts{}
45+
r.Equal("https://example.com", *serveOriginOverride(hOpts))
46+
})
47+
}
48+
49+
func TestServePathOverride(t *testing.T) {
50+
t.Run("no override", func(t *testing.T) {
51+
r := require.New(t)
52+
hOpts := handlerOpts{}
53+
r.Nil(servePathOverride(hOpts))
54+
})
55+
56+
t.Run("ServePath has highest precedence", func(t *testing.T) {
57+
r := require.New(t)
58+
59+
t.Setenv("INNGEST_SERVE_PATH", "/env/var")
60+
url, err := url.Parse("https://URL.com/url/var")
61+
r.NoError(err)
62+
hOpts := handlerOpts{
63+
ServePath: StrPtr("/serve-path/var"),
64+
URL: url,
65+
}
66+
r.Equal(*hOpts.ServePath, *servePathOverride(hOpts))
67+
})
68+
69+
t.Run("URL has second highest precedence", func(t *testing.T) {
70+
r := require.New(t)
71+
72+
t.Setenv("INNGEST_SERVE_PATH", "/env/var")
73+
url, err := url.Parse("https://URL.com/url/var")
74+
r.NoError(err)
75+
hOpts := handlerOpts{URL: url}
76+
r.Equal(url.Path, *servePathOverride(hOpts))
77+
})
78+
79+
t.Run("INNGEST_SERVE_PATH has lowest precedence", func(t *testing.T) {
80+
r := require.New(t)
81+
t.Setenv("INNGEST_SERVE_PATH", "/env/var")
82+
hOpts := handlerOpts{}
83+
r.Equal("/env/var", *servePathOverride(hOpts))
84+
})
85+
}
86+
87+
func TestOverrideURL(t *testing.T) {
88+
originalURL, err := url.Parse("https://original.com/original?original")
89+
require.NoError(t, err)
90+
91+
t.Run("no override", func(t *testing.T) {
92+
r := require.New(t)
93+
hOpts := handlerOpts{}
94+
overrideURL, err := overrideURL(originalURL, hOpts)
95+
r.NoError(err)
96+
r.Equal(originalURL, overrideURL)
97+
})
98+
99+
t.Run("ServeOrigin/ServePath fields have highest precedence", func(t *testing.T) {
100+
r := require.New(t)
101+
102+
t.Setenv("INNGEST_SERVE_HOST", "https://env.com")
103+
t.Setenv("INNGEST_SERVE_PATH", "/env")
104+
r.NoError(err)
105+
hOpts := handlerOpts{
106+
ServeOrigin: StrPtr("https://serve-field.com"),
107+
ServePath: StrPtr("/serve-field"),
108+
URL: urlMustParse(t, "https://url-field.com/url-field?url-field"),
109+
}
110+
overrideURL, err := overrideURL(originalURL, hOpts)
111+
r.NoError(err)
112+
r.Equal("https://serve-field.com/serve-field?original", overrideURL.String())
113+
})
114+
115+
t.Run("URL field has second highest precedence", func(t *testing.T) {
116+
r := require.New(t)
117+
118+
t.Setenv("INNGEST_SERVE_HOST", "https://env.com")
119+
t.Setenv("INNGEST_SERVE_PATH", "/env")
120+
r.NoError(err)
121+
hOpts := handlerOpts{
122+
URL: urlMustParse(t, "https://url-field.com/url-field?url-field"),
123+
}
124+
overrideURL, err := overrideURL(hOpts.URL, hOpts)
125+
r.NoError(err)
126+
r.Equal("https://url-field.com/url-field?url-field", overrideURL.String())
127+
})
128+
129+
t.Run("env vars have lowest precedence", func(t *testing.T) {
130+
r := require.New(t)
131+
t.Setenv("INNGEST_SERVE_HOST", "https://env.com")
132+
t.Setenv("INNGEST_SERVE_PATH", "/env")
133+
hOpts := handlerOpts{}
134+
overrideURL, err := overrideURL(originalURL, hOpts)
135+
r.NoError(err)
136+
r.Equal("https://env.com/env?original", overrideURL.String())
137+
})
138+
}
139+
140+
func urlMustParse(t *testing.T, s string) *url.URL {
141+
url, err := url.Parse(s)
142+
require.NoError(t, err)
143+
return url
144+
}

0 commit comments

Comments
 (0)