jetstack / kube-oidc-proxy

Reverse proxy to authenticate to managed Kubernetes API servers via OIDC.
https://jetstack.io
Apache License 2.0
477 stars 91 forks source link

Adds --flush-interval to set the flush interval of proxy handler #137

Closed JoshVanL closed 4 years ago

JoshVanL commented 4 years ago

This PR adds the flag --flush-interval. This sets the proxy handler to flush request bodies at the given duration. The default is 50ms. If zero, no flushing is done. If negative, it will flush immediately. The proxy handler will ignore the value is a streaming request is recognized and will flush immediately.

/assign @simonswine fixes #135

jetstack-bot commented 4 years ago

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: JoshVanL

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files: - ~~[OWNERS](https://github.com/jetstack/kube-oidc-proxy/blob/master/OWNERS)~~ [JoshVanL] Approvers can indicate their approval by writing `/approve` in a comment Approvers can cancel approval by writing `/approve cancel` in a comment
mkinsley commented 4 years ago

This looks great, thanks a bunch. 50 msec seems like a reasonable default setting. I'm a bit curious about the comment:

The proxy handler will ignore the value is a streaming request is recognized and will flush immediately.

From what I've observed (the root of the issue), the proxy wasn't ever flushing partial buffers on streaming connections. The streaming response from GET pods watch=true was where things were hanging.

JoshVanL commented 4 years ago

@mkinsley so I'd need to dig into the std library, but seems that in that case, it just wasn't detecting that as a streaming connection. For example, exec is streaming correctly. It looks like it's just not "smart" enough. I could be missing something though, and misunderstanding

mkinsley commented 4 years ago

I took a look: https://golang.org/src/net/http/httputil/reverseproxy.go#L367 . The stdlib is only keying off Content-Type to determine if the response is streaming.

If I'm understanding the HTTP RFC (and assuming HTTP/2) , the absence of a Content-Length header implies streaming. In HTTP 1.1 we could look for transfer-encoding: chunked.

// flushInterval returns the p.FlushInterval value, conditionally
// overriding its value for a specific request/response.
func (p *ReverseProxy) flushInterval(req *http.Request, res *http.Response) time.Duration {
    resCT := res.Header.Get("Content-Type")

    // For Server-Sent Events responses, flush immediately.
    // The MIME type is defined in https://www.w3.org/TR/eventsource/#text-event-stream
    if resCT == "text/event-stream" {
        return -1 // negative means immediately
    }

    // TODO: more specific cases? e.g. res.ContentLength == -1?
    return p.FlushInterval
}
munnerz commented 4 years ago

/cc

JoshVanL commented 4 years ago

/unassign @simonswine /assign @munnerz

munnerz commented 4 years ago

/lgtm