| @@ -34,10 +34,18 @@ type handlerInterceptorNoStreamTestHost struct { · 33 unmodified lines |
| 34 | *handlerInterceptorTestHost | 34 | *handlerInterceptorTestHost |
| 35 | } | 35 | } |
| 36 | | 36 | |
| | 37 | type handlerInterceptorDisabledRequestTestHost struct { |
| | 38 | *handlerInterceptorTestHost |
| | 39 | } |
| | 40 | |
| 37 | func (h *handlerInterceptorNoStreamTestHost) HasStreamInterceptors() bool { | 41 | func (h *handlerInterceptorNoStreamTestHost) HasStreamInterceptors() bool { |
| 38 | return false | 42 | return false |
| 39 | } | 43 | } |
| 40 | | 44 | |
| | 45 | func (h *handlerInterceptorDisabledRequestTestHost) HasRequestInterceptors() bool { |
| | 46 | return false |
| | 47 | } |
| | 48 | |
| 41 | func (h *handlerInterceptorTestHost) InterceptRequestBeforeAuth(ctx context.Context, req pluginapi.RequestInterceptRequest) pluginapi.RequestInterceptResponse { | 49 | func (h *handlerInterceptorTestHost) InterceptRequestBeforeAuth(ctx context.Context, req pluginapi.RequestInterceptRequest) pluginapi.RequestInterceptResponse { |
| 42 | if h != nil && h.interceptRequestBeforeAuth != nil { | 50 | if h != nil && h.interceptRequestBeforeAuth != nil { |
| 43 | return h.interceptRequestBeforeAuth(ctx, req) | 51 | return h.interceptRequestBeforeAuth(ctx, req) |
| @@ -566,6 +574,80 @@ func TestHandlerRequestInterceptorRewritesExecutorRequest(t *testing.T) { · 522 unmodified lines |
| 566 | } | 574 | } |
| 567 | } | 575 | } |
| 568 | | 576 | |
| | 577 | func TestHandlerSkipsDisabledRequestInterceptorsWithoutCopyingPayload(t *testing.T) { |
| | 578 | payload := []byte(`{"model":"disabled-interceptor-model"}`) |
| | 579 | called := false |
| | 580 | handler := NewBaseAPIHandlers(&sdkconfig.SDKConfig{}, nil) |
| | 581 | handler.SetPluginHost(&handlerInterceptorDisabledRequestTestHost{ |
| | 582 | handlerInterceptorTestHost: &handlerInterceptorTestHost{ |
| | 583 | interceptRequestBeforeAuth: func(context.Context, pluginapi.RequestInterceptRequest) pluginapi.RequestInterceptResponse { |
| | 584 | called = true |
| | 585 | return pluginapi.RequestInterceptResponse{Body: []byte(`{"unexpected":true}`)} |
| | 586 | }, |
| | 587 | }, |
| | 588 | }) |
| | 589 | |
| | 590 | req := coreexecutor.Request{Model: "disabled-interceptor-model", Payload: payload} |
| | 591 | opts := coreexecutor.Options{OriginalRequest: payload} |
| | 592 | gotReq, gotOpts, err := handler.applyRequestInterceptorsBeforeAuth(context.Background(), "openai", req.Model, "test-req", req, opts, "") |
| | 593 | if err != nil { |
| | 594 | t.Fatalf("unexpected error: %v", err) |
| | 595 | } |
| | 596 | |
| | 597 | if called { |
| | 598 | t.Fatal("disabled request interceptor was called") |
| | 599 | } |
| | 600 | if len(gotReq.Payload) != len(payload) || &gotReq.Payload[0] != &payload[0] { |
| | 601 | t.Fatal("request payload was copied") |
| | 602 | } |
| | 603 | if len(gotOpts.OriginalRequest) != len(payload) || &gotOpts.OriginalRequest[0] != &payload[0] { |
| | 604 | t.Fatal("original request was copied") |
| | 605 | } |
| | 606 | } |
| | 607 | |
| | 608 | func BenchmarkHandlerRequestInterceptors(b *testing.B) { |
| | 609 | sizes := []struct { |
| | 610 | name string |
| | 611 | bytes int |
| | 612 | }{ |
| | 613 | {name: "1KiB", bytes: 1 << 10}, |
| | 614 | {name: "1MiB", bytes: 1 << 20}, |
| | 615 | {name: "8MiB", bytes: 8 << 20}, |
| | 616 | } |
| | 617 | hosts := []struct { |
| | 618 | name string |
| | 619 | host PluginInterceptorHost |
| | 620 | }{ |
| | 621 | { |
| | 622 | name: "disabled", |
| | 623 | host: &handlerInterceptorDisabledRequestTestHost{ |
| | 624 | handlerInterceptorTestHost: &handlerInterceptorTestHost{}, |
| | 625 | }, |
| | 626 | }, |
| | 627 | {name: "active", host: &handlerInterceptorTestHost{}}, |
| | 628 | } |
| | 629 | |
| | 630 | for _, size := range sizes { |
| | 631 | payload := make([]byte, size.bytes) |
| | 632 | req := coreexecutor.Request{Model: "benchmark-model", Payload: payload} |
| | 633 | opts := coreexecutor.Options{OriginalRequest: payload} |
| | 634 | for _, host := range hosts { |
| | 635 | b.Run(host.name+"/"+size.name, func(b *testing.B) { |
| | 636 | handler := NewBaseAPIHandlers(&sdkconfig.SDKConfig{}, nil) |
| | 637 | handler.SetPluginHost(host.host) |
| | 638 | b.ReportAllocs() |
| | 639 | b.ResetTimer() |
| | 640 | for range b.N { |
| | 641 | gotReq, gotOpts, _ := handler.applyRequestInterceptorsBeforeAuth(context.Background(), "openai", req.Model, "benchmark-req", req, opts, "") |
| | 642 | if len(gotReq.Payload) != size.bytes || len(gotOpts.OriginalRequest) != size.bytes { |
| | 643 | b.Fatal("request payload length changed") |
| | 644 | } |
| | 645 | } |
| | 646 | }) |
| | 647 | } |
| | 648 | } |
| | 649 | } |
| | 650 | |
| 569 | func TestHandlerRequestInterceptorEmptyBodyKeepsOriginalPayload(t *testing.T) { | 651 | func TestHandlerRequestInterceptorEmptyBodyKeepsOriginalPayload(t *testing.T) { |
| 570 | model := "handler-interceptor-empty-body-model" | 652 | model := "handler-interceptor-empty-body-model" |
| 571 | executor := &interceptorCaptureExecutor{} | 653 | executor := &interceptorCaptureExecutor{} |