fix: immediate fixes from Opus review (v0.1.22)
- trigger: CronJob moved to deployNS (sless-fn-{userNS}), was tr.Namespace
Reason: with NetworkPolicy default-deny, pod in user-ns can't reach
Service in sless-fn-ns. Co-locating CronJob with Service guarantees
connectivity regardless of NetworkPolicy configuration.
handleTriggerDeletion updated consistently.
- trigger: pin curlimages/curl to 8.5.0 (was :latest)
Reason: reproducibility, no unexpected behavior changes from image updates.
- function: sort env vars in buildDeployment (was non-deterministic map range)
Reason: non-deterministic order caused k8s to detect container spec 'change'
on every reconcile → unnecessary pod restarts. Sorted order is stable.
- function: cleanup kaniko Job in handleDeletion
Reason: if Function deleted during Building phase, kaniko Job continued
running, wasting CPU/memory and pushing an unused image.
- invoke: filter hop-by-hop headers in proxy response (RFC 2616 §13.5.1)
Reason: Transfer-Encoding especially dangerous — forwarding it corrupts
response body framing for the client.
- config: SLESS_API_TOKEN no longer required
Reason: dead code — field loaded but never passed to any component.
Auth uses validateJWT() middleware, not static token.
Namespace lifecycle: user namespaces preserved on destroy (not changed).
E2E: apply 4 resources + destroy clean. Operator v0.1.22 deployed.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Изменено: 2026-03-09
|
||||
// Изменено: 2026-03-11
|
||||
// invoke.go — прокси-обработчик для вызова HTTP-триггеров функций.
|
||||
// Маршрут: ANY /fn/{namespace}/{name} и /fn/{namespace}/{name}/**
|
||||
// Не защищён auth-токеном — это публичный эндпоинт для вызова функций.
|
||||
@@ -23,6 +23,20 @@ import (
|
||||
// Таймаут 30s — достаточно для холодного старта функции.
|
||||
var httpClient = &http.Client{Timeout: 30 * time.Second}
|
||||
|
||||
// hopByHopHeaders — заголовки которые нельзя пробрасывать через прокси (RFC 2616 §13.5.1).
|
||||
// Они управляют соединением между двумя узлами, а не end-to-end.
|
||||
// Особо опасен Transfer-Encoding: если пробросить его, клиент неверно интерпретирует тело.
|
||||
var hopByHopHeaders = map[string]bool{
|
||||
"Connection": true,
|
||||
"Keep-Alive": true,
|
||||
"Proxy-Authenticate": true,
|
||||
"Proxy-Authorization": true,
|
||||
"Te": true,
|
||||
"Trailers": true,
|
||||
"Transfer-Encoding": true,
|
||||
"Upgrade": true,
|
||||
}
|
||||
|
||||
// InvokeFunction проксирует входящий запрос к Service функции в кластере.
|
||||
// Namespace выбирается из пути, имя функции — тоже из пути.
|
||||
// Сохраняет метод, тело, Content-Type, sub-path и query string.
|
||||
@@ -71,8 +85,13 @@ func (h *Handler) InvokeFunction(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Копируем заголовки и статус из ответа функции
|
||||
// Копируем заголовки и статус из ответа функции.
|
||||
// Hop-by-hop заголовки фильтруем: они управляют конкретным TCP-соединением
|
||||
// и не должны пробрасываться через прокси (RFC 2616 §13.5.1).
|
||||
for k, vals := range resp.Header {
|
||||
if hopByHopHeaders[k] {
|
||||
continue
|
||||
}
|
||||
for _, v := range vals {
|
||||
w.Header().Add(k, v)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user