mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-23 06:07:47 +00:00
test: integration suite with real Traefik, redis-shared limits, streaming assertions
Adds integration/ (separate module): docker compose stack with real Traefik v3.5 + localPlugins, mock openai/anthropic/gemini/tool providers, shared Redis, and a raw-TCP streaming timing probe. 6/7 tests pass; streaming incrementality fails on a confirmed external yaegi/Traefik bug (see task-15-report.md), not a plugin defect. Fixes 4 real Yaegi-interpretation bugs surfaced by running the plugin under real Traefik for the first time (none caught by go test or yaegi-check, which never exercises chat/embeddings/streaming/Redis): - .traefik.yml: add basePkg (Traefik derives the yaegi binding identifier from the module path, not the package's own declared name; without this override the plugin never loads at all). - registry.go: resolveAgainst's multi-value return panicked yaegi on an inline string concatenation; assign to a local first. - routes_unified.go: errors.As panicked yaegi on interpreted pointer error types; use plain type assertions (both types are always returned bare, never wrapped). - sse.go: readSSE's dispatch closure hit the same multi-value-assignment panic as registry.go; split into separate statements. - resp.go: respErr as a defined string type was indistinguishable from a plain string in a yaegi type assertion, misreading every successful Redis SELECT reply as failed and silently disabling rate limiting; changed to a struct.
This commit is contained in:
+11
-4
@@ -225,14 +225,21 @@ func (g *Gateway) handleAdapterError(sw *statusTrackingWriter, err error, provid
|
||||
return
|
||||
}
|
||||
|
||||
var perr *providerHTTPError
|
||||
if errors.As(err, &perr) {
|
||||
// Plain type assertions, not errors.As: providerHTTPError and
|
||||
// translateError are both always returned bare from every adapter and
|
||||
// translate_*.go call site — never wrapped via fmt.Errorf("%w", ...) —
|
||||
// so errors.As's unwrap-chain walk buys nothing here, and yaegi
|
||||
// v0.16.1 panics ("errors: *target must be interface or implement
|
||||
// error") calling errors.As with an interpreted pointer type as its
|
||||
// target, even though that type's Error() method is right there.
|
||||
// Verified empirically under real Traefik (Task 15's integration
|
||||
// suite); tools/yaegi-check never exercises this call path.
|
||||
if perr, ok := err.(*providerHTTPError); ok {
|
||||
writeProviderUpstreamError(sw, providerName, perr)
|
||||
return
|
||||
}
|
||||
|
||||
var terr *translateError
|
||||
if errors.As(err, &terr) {
|
||||
if terr, ok := err.(*translateError); ok {
|
||||
status := http.StatusBadRequest
|
||||
if terr.notSupported {
|
||||
status = http.StatusNotImplemented
|
||||
|
||||
Reference in New Issue
Block a user