Skip to content

Commit f6966e9

Browse files
committed
more
Signed-off-by: Takeshi Yoneda <[email protected]>
1 parent c868d43 commit f6966e9

File tree

9 files changed

+123
-68
lines changed

9 files changed

+123
-68
lines changed

cmd/dynamic_module/main.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// Copyright Envoy AI Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
16
package main
27

38
import (
@@ -7,14 +12,15 @@ import (
712
"os"
813
"time"
914

15+
"github.com/prometheus/client_golang/prometheus"
16+
otelprom "go.opentelemetry.io/otel/exporters/prometheus"
17+
1018
"github.com/envoyproxy/ai-gateway/internal/backendauth"
11-
"github.com/envoyproxy/ai-gateway/internal/dynamic_module"
12-
"github.com/envoyproxy/ai-gateway/internal/dynamic_module/sdk"
19+
"github.com/envoyproxy/ai-gateway/internal/dynamicmodule"
20+
"github.com/envoyproxy/ai-gateway/internal/dynamicmodule/sdk"
1321
"github.com/envoyproxy/ai-gateway/internal/filterapi"
1422
"github.com/envoyproxy/ai-gateway/internal/internalapi"
1523
"github.com/envoyproxy/ai-gateway/internal/metrics"
16-
"github.com/prometheus/client_golang/prometheus"
17-
otelprom "go.opentelemetry.io/otel/exporters/prometheus"
1824
)
1925

2026
func main() {} // This must be present to make a shared library.
@@ -31,7 +37,7 @@ func init() {
3137
Level: slog.LevelDebug, // Adjust log level from environment variable if needed.
3238
}))
3339
if err := filterapi.StartConfigWatcher(context.Background(),
34-
os.Getenv("AI_GATEWAY_DYNAMIC_MODULE_FILTER_CONFIG_PATH"), g, logger, time.Second*5); err != nil {
40+
os.Getenv("AI_GATEWAY_dynamicmodule_FILTER_CONFIG_PATH"), g, logger, time.Second*5); err != nil {
3541
panic("failed to start filter config watcher: " + err.Error())
3642
}
3743
sdk.NewHTTPFilterConfig = g.newHTTPFilterConfig
@@ -40,7 +46,7 @@ func init() {
4046
// globalState implements [filterapi.ConfigReceiver] to load filter configuration.
4147
type globalState struct {
4248
fc *filterapi.RuntimeConfig
43-
env *dynamic_module.Env
49+
env *dynamicmodule.Env
4450
}
4551

4652
// newHTTPFilterConfig creates a new http filter based on the config.
@@ -49,9 +55,9 @@ type globalState struct {
4955
func (g *globalState) newHTTPFilterConfig(name string, _ []byte) sdk.HTTPFilterConfig {
5056
switch name {
5157
case "ai_gateway.router":
52-
return dynamic_module.NewRouterFilterConfig(g.env, &g.fc)
58+
return dynamicmodule.NewRouterFilterConfig(g.env, &g.fc)
5359
case "ai_gateway.upstream":
54-
return dynamic_module.NewUpstreamFilterConfig(g.env)
60+
return dynamicmodule.NewUpstreamFilterConfig(g.env)
5561
default:
5662
panic("unknown filter: " + name)
5763
}
@@ -81,21 +87,21 @@ func (g *globalState) initializeEnv() error {
8187
}
8288

8389
endpointPrefixes, err := internalapi.ParseEndpointPrefixes(os.Getenv(
84-
"AI_GATEWAY_DYNAMIC_MODULE_FILTER_ENDPOINT_PREFIXES",
90+
"AI_GATEWAY_dynamicmodule_FILTER_ENDPOINT_PREFIXES",
8591
))
8692
if err != nil {
8793
return fmt.Errorf("failed to parse endpoint prefixes: %w", err)
8894
}
8995

9096
metricsRequestHeaderAttributes, err := internalapi.ParseRequestHeaderAttributeMapping(os.Getenv(
91-
"AI_GATEWAY_DYNAMIC_MODULE_FILTER_METRICS_REQUEST_HEADER_ATTRIBUTES",
97+
"AI_GATEWAY_dynamicmodule_FILTER_METRICS_REQUEST_HEADER_ATTRIBUTES",
9298
))
9399
if err != nil {
94100
return fmt.Errorf("failed to parse metrics header mapping: %w", err)
95101
}
96102

97-
g.env = &dynamic_module.Env{
98-
RootPrefix: os.Getenv("AI_GATEWAY_DYNAMIC_MODULE_ROOT_PREFIX"),
103+
g.env = &dynamicmodule.Env{
104+
RootPrefix: os.Getenv("AI_GATEWAY_dynamicmodule_ROOT_PREFIX"),
99105
EndpointPrefixes: endpointPrefixes,
100106
ChatCompletionMetricsFactory: metrics.NewChatCompletionFactory(meter, metricsRequestHeaderAttributes),
101107
MessagesMetricsFactory: metrics.NewMessagesFactory(meter, metricsRequestHeaderAttributes),

internal/dynamic_module/sdk/cgoflags_darwin.go

Lines changed: 0 additions & 6 deletions
This file was deleted.

internal/dynamic_module/dynamic_module.go renamed to internal/dynamicmodule/dynamic_module.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
package dynamic_module
1+
// Copyright Envoy AI Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
6+
package dynamicmodule
27

38
import (
49
"github.com/envoyproxy/ai-gateway/internal/internalapi"
@@ -21,6 +26,8 @@ const (
2126
rerankEndpoint
2227
// messagesEndpoint represents the /v1/messages endpoint of anthropic.
2328
messagesEndpoint
29+
// modelsEndpoint represents the /v1/models endpoint.
30+
modelsEndpoint
2431
)
2532

2633
// Env holds the environment configuration for the dynamic module that is process-wide.

internal/dynamic_module/router_filter.go renamed to internal/dynamicmodule/router_filter.go

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,26 @@
1-
package dynamic_module
1+
// Copyright Envoy AI Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
6+
package dynamicmodule
27

38
import (
49
"encoding/json"
510
"fmt"
611
"io"
12+
"path"
713
"strings"
814
"unsafe"
915

16+
openaisdk "github.com/openai/openai-go/v2"
17+
1018
"github.com/envoyproxy/ai-gateway/internal/apischema/anthropic"
1119
cohereschema "github.com/envoyproxy/ai-gateway/internal/apischema/cohere"
1220
"github.com/envoyproxy/ai-gateway/internal/apischema/openai"
13-
"github.com/envoyproxy/ai-gateway/internal/dynamic_module/sdk"
21+
"github.com/envoyproxy/ai-gateway/internal/dynamicmodule/sdk"
1422
"github.com/envoyproxy/ai-gateway/internal/filterapi"
1523
"github.com/envoyproxy/ai-gateway/internal/internalapi"
16-
openaisdk "github.com/openai/openai-go/v2"
1724
)
1825

1926
const routerFilterPointerDynamicMetadataKey = "router_filter_pointer"
@@ -24,11 +31,13 @@ type (
2431
// This is mostly for debugging purposes, it does not do anything except
2532
// setting a response header with the version of the dynamic module.
2633
routerFilterConfig struct {
27-
fcr **filterapi.RuntimeConfig
34+
fcr **filterapi.RuntimeConfig
35+
prefixToEndpoint map[string]endpoint
2836
}
2937
// routerFilter implements [sdk.HTTPFilter].
3038
routerFilter struct {
31-
fc *filterapi.RuntimeConfig
39+
routerFilterConfig *routerFilterConfig
40+
runtimeFilterConfig *filterapi.RuntimeConfig
3241
endpoint endpoint
3342
originalHeaders map[string]string
3443
originalRequestBody any
@@ -40,12 +49,24 @@ type (
4049

4150
// NewRouterFilterConfig creates a new instance of an implementation of [sdk.HTTPFilterConfig] for the router filter.
4251
func NewRouterFilterConfig(env *Env, fcr **filterapi.RuntimeConfig) sdk.HTTPFilterConfig {
43-
return &routerFilterConfig{fcr: fcr}
52+
prefixToEndpoint := map[string]endpoint{
53+
path.Join(env.RootPrefix, env.EndpointPrefixes.OpenAI, "/v1/chat/completions"): chatCompletionsEndpoint,
54+
path.Join(env.RootPrefix, env.EndpointPrefixes.OpenAI, "/v1/completions"): completionsEndpoint,
55+
path.Join(env.RootPrefix, env.EndpointPrefixes.OpenAI, "/v1/embeddings"): embeddingsEndpoint,
56+
path.Join(env.RootPrefix, env.EndpointPrefixes.OpenAI, "/v1/images/generations"): imagesGenerationsEndpoint,
57+
path.Join(env.RootPrefix, env.EndpointPrefixes.Cohere, "/v2/rerank"): rerankEndpoint,
58+
path.Join(env.RootPrefix, env.EndpointPrefixes.OpenAI, "/v1/models"): modelsEndpoint,
59+
path.Join(env.RootPrefix, env.EndpointPrefixes.Anthropic, "/v1/messages"): messagesEndpoint,
60+
}
61+
return &routerFilterConfig{
62+
fcr: fcr,
63+
prefixToEndpoint: prefixToEndpoint,
64+
}
4465
}
4566

4667
// NewFilter implements [sdk.HTTPFilterConfig].
4768
func (f *routerFilterConfig) NewFilter() sdk.HTTPFilter {
48-
return &routerFilter{fc: *f.fcr}
69+
return &routerFilter{routerFilterConfig: f, runtimeFilterConfig: *f.fcr}
4970
}
5071

5172
// RequestHeaders implements [sdk.HTTPFilter].
@@ -55,32 +76,16 @@ func (f *routerFilter) RequestHeaders(e sdk.EnvoyHTTPFilter, _ bool) sdk.Request
5576
if queryIndex := strings.Index(p, "?"); queryIndex != -1 {
5677
p = p[:queryIndex]
5778
}
58-
// TODO: prefix config.
59-
switch p {
60-
case "/v1/chat/completions":
61-
f.endpoint = chatCompletionsEndpoint
62-
return sdk.RequestHeadersStatusContinue
63-
case "/v1/completions":
64-
f.endpoint = completionsEndpoint
65-
return sdk.RequestHeadersStatusContinue
66-
case "/v1/embeddings":
67-
f.endpoint = embeddingsEndpoint
68-
return sdk.RequestHeadersStatusContinue
69-
case "/v1/images/generations":
70-
f.endpoint = imagesGenerationsEndpoint
71-
return sdk.RequestHeadersStatusContinue
72-
case "/cohere/v2/rerank":
73-
f.endpoint = rerankEndpoint
74-
return sdk.RequestHeadersStatusContinue
75-
case "/anthropic/v1/messages":
76-
f.endpoint = messagesEndpoint
77-
return sdk.RequestHeadersStatusContinue
78-
case "/v1/models":
79-
return f.handleModelsEndpoint(e)
80-
default:
79+
ep, ok := f.routerFilterConfig.prefixToEndpoint[p]
80+
if !ok {
8181
e.SendLocalReply(404, nil, []byte(fmt.Sprintf("unsupported path: %s", p)))
8282
return sdk.RequestHeadersStatusStopIteration
8383
}
84+
f.endpoint = ep
85+
if f.endpoint == modelsEndpoint {
86+
return f.handleModelsEndpoint(e)
87+
}
88+
return sdk.RequestHeadersStatusContinue
8489
}
8590

8691
// RequestBody implements [sdk.HTTPFilter].
@@ -148,7 +153,7 @@ func (f *routerFilter) ResponseBody(sdk.EnvoyHTTPFilter, bool) sdk.ResponseBodyS
148153
//
149154
// This is called on request headers phase.
150155
func (f *routerFilter) handleModelsEndpoint(e sdk.EnvoyHTTPFilter) sdk.RequestHeadersStatus {
151-
config := *f.fc
156+
config := f.runtimeFilterConfig
152157
models := openai.ModelList{
153158
Object: "list",
154159
Data: make([]openai.Model, 0, len(config.DeclaredModels)),

internal/dynamic_module/sdk/abi_envoy_v1.36.go renamed to internal/dynamicmodule/sdk/abi_envoy_v1.36.go

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
//go:build envoy_v1.36
1+
// Copyright Envoy AI Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
25

36
package sdk
47

@@ -175,7 +178,7 @@ func envoy_dynamic_module_on_http_filter_config_new(
175178

176179
//export envoy_dynamic_module_on_http_filter_config_destroy
177180
func envoy_dynamic_module_on_http_filter_config_destroy(ptr uintptr) {
178-
pinnedFilterConfig := unwrapPinnedHTTPFilterConfig(uintptr(ptr))
181+
pinnedFilterConfig := unwrapPinnedHTTPFilterConfig(ptr)
179182
memManager.unpinHTTPFilterConfig(pinnedFilterConfig)
180183
}
181184

@@ -184,7 +187,7 @@ func envoy_dynamic_module_on_http_filter_new(
184187
filterConfigPtr uintptr,
185188
_ uintptr,
186189
) uintptr {
187-
pinnedFilterConfig := unwrapPinnedHTTPFilterConfig(uintptr(filterConfigPtr))
190+
pinnedFilterConfig := unwrapPinnedHTTPFilterConfig(filterConfigPtr)
188191
filterConfig := pinnedFilterConfig.obj
189192
filter := filterConfig.NewFilter()
190193
if filter == nil {
@@ -200,7 +203,7 @@ func envoy_dynamic_module_on_http_filter_new(
200203
func envoy_dynamic_module_on_http_filter_destroy(
201204
filterPtr uintptr,
202205
) {
203-
pinned := unwrapPinnedHTTPFilter(uintptr(filterPtr))
206+
pinned := unwrapPinnedHTTPFilter(filterPtr)
204207
// Unpin the filter from the memory manager.
205208
memManager.unpinHTTPFilter(pinned)
206209
}
@@ -211,8 +214,8 @@ func envoy_dynamic_module_on_http_filter_request_headers(
211214
filterModulePtr uintptr,
212215
endOfStream bool,
213216
) uintptr {
214-
pinned := unwrapPinnedHTTPFilter(uintptr(filterModulePtr))
215-
status := pinned.obj.RequestHeaders(envoyFilter{raw: filterEnvoyPtr}, bool(endOfStream))
217+
pinned := unwrapPinnedHTTPFilter(filterModulePtr)
218+
status := pinned.obj.RequestHeaders(envoyFilter{raw: filterEnvoyPtr}, endOfStream)
216219
return uintptr(status)
217220
}
218221

@@ -222,8 +225,8 @@ func envoy_dynamic_module_on_http_filter_request_body(
222225
filterModulePtr uintptr,
223226
endOfStream bool,
224227
) uintptr {
225-
pinned := unwrapPinnedHTTPFilter(uintptr(filterModulePtr))
226-
status := pinned.obj.RequestBody(envoyFilter{raw: uintptr(filterEnvoyPtr)}, bool(endOfStream))
228+
pinned := unwrapPinnedHTTPFilter(filterModulePtr)
229+
status := pinned.obj.RequestBody(envoyFilter{raw: filterEnvoyPtr}, endOfStream)
227230
return uintptr(status)
228231
}
229232

@@ -238,8 +241,8 @@ func envoy_dynamic_module_on_http_filter_response_headers(
238241
filterModulePtr uintptr,
239242
endOfStream bool,
240243
) uintptr {
241-
pinned := unwrapPinnedHTTPFilter(uintptr(filterModulePtr))
242-
status := pinned.obj.ResponseHeaders(envoyFilter{raw: uintptr(filterEnvoyPtr)}, bool(endOfStream))
244+
pinned := unwrapPinnedHTTPFilter(filterModulePtr)
245+
status := pinned.obj.ResponseHeaders(envoyFilter{raw: filterEnvoyPtr}, endOfStream)
243246
return uintptr(status)
244247
}
245248

@@ -249,8 +252,8 @@ func envoy_dynamic_module_on_http_filter_response_body(
249252
filterModulePtr uintptr,
250253
endOfStream bool,
251254
) uintptr {
252-
pinned := unwrapPinnedHTTPFilter(uintptr(filterModulePtr))
253-
status := pinned.obj.ResponseBody(envoyFilter{raw: uintptr(filterEnvoyPtr)}, bool(endOfStream))
255+
pinned := unwrapPinnedHTTPFilter(filterModulePtr)
256+
status := pinned.obj.ResponseBody(envoyFilter{raw: filterEnvoyPtr}, endOfStream)
254257
return uintptr(status)
255258
}
256259

@@ -274,7 +277,14 @@ func envoy_dynamic_module_on_http_filter_http_callout_done(
274277
bodyVectorPtr uintptr,
275278
bodyVectorSize C.size_t,
276279
) {
277-
panic("TODO")
280+
_ = filterEnvoyPtr
281+
_ = filterModulePtr
282+
_ = calloutID
283+
_ = result
284+
_ = headersPtr
285+
_ = headersSize
286+
_ = bodyVectorPtr
287+
_ = bodyVectorSize
278288
}
279289

280290
//export envoy_dynamic_module_on_http_filter_scheduled
@@ -283,6 +293,9 @@ func envoy_dynamic_module_on_http_filter_scheduled(
283293
filterModulePtr uintptr,
284294
eventID C.uint64_t,
285295
) {
296+
_ = filterEnvoyPtr
297+
_ = filterModulePtr
298+
_ = eventID
286299
}
287300

288301
// GetRequestHeader implements [EnvoyHTTPFilter].
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright Envoy AI Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
6+
//go:build darwin && cgo
7+
8+
package sdk
9+
10+
// #cgo LDFLAGS: -Wl,-undefined,dynamic_lookup
11+
import "C"

internal/dynamic_module/sdk/gosdk.go renamed to internal/dynamicmodule/sdk/gosdk.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// Copyright Envoy AI Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
16
package sdk
27

38
import "io"

internal/dynamic_module/sdk/mem.go renamed to internal/dynamicmodule/sdk/mem.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// Copyright Envoy AI Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
16
package sdk
27

38
import (

0 commit comments

Comments
 (0)