Implemented flushing interval (#23)
* Implemented flushing interval When proxying streaming responses, it would not flush the response writer buffer until some seemingly random point (maybe the number of bytes?). This makes it flush every 1 second by default, but with a configurable interval. * flushing CHANGELOG * gofmt and goimports
This commit is contained in:
parent
787d3da9d2
commit
01c5f5ae3b
@ -10,6 +10,8 @@
|
|||||||
- [#21](https://github.com/pusher/oauth2_proxy/pull/21) Docker Improvement (@yaegashi)
|
- [#21](https://github.com/pusher/oauth2_proxy/pull/21) Docker Improvement (@yaegashi)
|
||||||
- Move Docker base image from debian to alpine
|
- Move Docker base image from debian to alpine
|
||||||
- Install ca-certificates in docker image
|
- Install ca-certificates in docker image
|
||||||
|
- [#23](https://github.com/pusher/oauth2_proxy/pull/21) Flushed streaming responses
|
||||||
|
- Long-running upstream responses will get flushed every <timeperiod> (1 second by default)
|
||||||
- [#24](https://github.com/pusher/oauth2_proxy/pull/24) Redirect fix (@agentgonzo)
|
- [#24](https://github.com/pusher/oauth2_proxy/pull/24) Redirect fix (@agentgonzo)
|
||||||
- After a successful login, you will be redirected to your original URL rather than /
|
- After a successful login, you will be redirected to your original URL rather than /
|
||||||
|
|
||||||
|
@ -76,6 +76,12 @@ func (l *responseLogger) Size() int {
|
|||||||
return l.size
|
return l.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *responseLogger) Flush() {
|
||||||
|
if flusher, ok := l.w.(http.Flusher); ok {
|
||||||
|
flusher.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// logMessageData is the container for all values that are available as variables in the request logging format.
|
// logMessageData is the container for all values that are available as variables in the request logging format.
|
||||||
// All values are pre-formatted strings so it is easy to use them in the format string.
|
// All values are pre-formatted strings so it is easy to use them in the format string.
|
||||||
type logMessageData struct {
|
type logMessageData struct {
|
||||||
|
1
main.go
1
main.go
@ -43,6 +43,7 @@ func main() {
|
|||||||
flagSet.Bool("skip-provider-button", false, "will skip sign-in-page to directly reach the next step: oauth/start")
|
flagSet.Bool("skip-provider-button", false, "will skip sign-in-page to directly reach the next step: oauth/start")
|
||||||
flagSet.Bool("skip-auth-preflight", false, "will skip authentication for OPTIONS requests")
|
flagSet.Bool("skip-auth-preflight", false, "will skip authentication for OPTIONS requests")
|
||||||
flagSet.Bool("ssl-insecure-skip-verify", false, "skip validation of certificates presented when using HTTPS")
|
flagSet.Bool("ssl-insecure-skip-verify", false, "skip validation of certificates presented when using HTTPS")
|
||||||
|
flagSet.Duration("flush-interval", time.Duration(1)*time.Second, "period between response flushing when streaming responses")
|
||||||
|
|
||||||
flagSet.Var(&emailDomains, "email-domain", "authenticate emails with the specified domain (may be given multiple times). Use * to authenticate any email")
|
flagSet.Var(&emailDomains, "email-domain", "authenticate emails with the specified domain (may be given multiple times). Use * to authenticate any email")
|
||||||
flagSet.String("azure-tenant", "common", "go to a tenant-specific or common (tenant-independent) endpoint.")
|
flagSet.String("azure-tenant", "common", "go to a tenant-specific or common (tenant-independent) endpoint.")
|
||||||
|
@ -110,8 +110,10 @@ func (u *UpstreamProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// NewReverseProxy creates a new reverse proxy for proxying requests to upstream
|
// NewReverseProxy creates a new reverse proxy for proxying requests to upstream
|
||||||
// servers
|
// servers
|
||||||
func NewReverseProxy(target *url.URL) (proxy *httputil.ReverseProxy) {
|
func NewReverseProxy(target *url.URL, flushInterval time.Duration) (proxy *httputil.ReverseProxy) {
|
||||||
return httputil.NewSingleHostReverseProxy(target)
|
proxy = httputil.NewSingleHostReverseProxy(target)
|
||||||
|
proxy.FlushInterval = flushInterval
|
||||||
|
return proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
func setProxyUpstreamHostHeader(proxy *httputil.ReverseProxy, target *url.URL) {
|
func setProxyUpstreamHostHeader(proxy *httputil.ReverseProxy, target *url.URL) {
|
||||||
@ -154,7 +156,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
|
|||||||
case httpScheme, httpsScheme:
|
case httpScheme, httpsScheme:
|
||||||
u.Path = ""
|
u.Path = ""
|
||||||
log.Printf("mapping path %q => upstream %q", path, u)
|
log.Printf("mapping path %q => upstream %q", path, u)
|
||||||
proxy := NewReverseProxy(u)
|
proxy := NewReverseProxy(u, opts.FlushInterval)
|
||||||
if !opts.PassHostHeader {
|
if !opts.PassHostHeader {
|
||||||
setProxyUpstreamHostHeader(proxy, u)
|
setProxyUpstreamHostHeader(proxy, u)
|
||||||
} else {
|
} else {
|
||||||
|
@ -39,7 +39,7 @@ func TestNewReverseProxy(t *testing.T) {
|
|||||||
backendHost := net.JoinHostPort(backendHostname, backendPort)
|
backendHost := net.JoinHostPort(backendHostname, backendPort)
|
||||||
proxyURL, _ := url.Parse(backendURL.Scheme + "://" + backendHost + "/")
|
proxyURL, _ := url.Parse(backendURL.Scheme + "://" + backendHost + "/")
|
||||||
|
|
||||||
proxyHandler := NewReverseProxy(proxyURL)
|
proxyHandler := NewReverseProxy(proxyURL, time.Second)
|
||||||
setProxyUpstreamHostHeader(proxyHandler, proxyURL)
|
setProxyUpstreamHostHeader(proxyHandler, proxyURL)
|
||||||
frontend := httptest.NewServer(proxyHandler)
|
frontend := httptest.NewServer(proxyHandler)
|
||||||
defer frontend.Close()
|
defer frontend.Close()
|
||||||
@ -61,7 +61,7 @@ func TestEncodedSlashes(t *testing.T) {
|
|||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
|
||||||
b, _ := url.Parse(backend.URL)
|
b, _ := url.Parse(backend.URL)
|
||||||
proxyHandler := NewReverseProxy(b)
|
proxyHandler := NewReverseProxy(b, time.Second)
|
||||||
setProxyDirector(proxyHandler)
|
setProxyDirector(proxyHandler)
|
||||||
frontend := httptest.NewServer(proxyHandler)
|
frontend := httptest.NewServer(proxyHandler)
|
||||||
defer frontend.Close()
|
defer frontend.Close()
|
||||||
|
27
options.go
27
options.go
@ -51,19 +51,20 @@ type Options struct {
|
|||||||
CookieSecure bool `flag:"cookie-secure" cfg:"cookie_secure"`
|
CookieSecure bool `flag:"cookie-secure" cfg:"cookie_secure"`
|
||||||
CookieHTTPOnly bool `flag:"cookie-httponly" cfg:"cookie_httponly"`
|
CookieHTTPOnly bool `flag:"cookie-httponly" cfg:"cookie_httponly"`
|
||||||
|
|
||||||
Upstreams []string `flag:"upstream" cfg:"upstreams"`
|
Upstreams []string `flag:"upstream" cfg:"upstreams"`
|
||||||
SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex"`
|
SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex"`
|
||||||
PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth"`
|
PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth"`
|
||||||
BasicAuthPassword string `flag:"basic-auth-password" cfg:"basic_auth_password"`
|
BasicAuthPassword string `flag:"basic-auth-password" cfg:"basic_auth_password"`
|
||||||
PassAccessToken bool `flag:"pass-access-token" cfg:"pass_access_token"`
|
PassAccessToken bool `flag:"pass-access-token" cfg:"pass_access_token"`
|
||||||
PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header"`
|
PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header"`
|
||||||
SkipProviderButton bool `flag:"skip-provider-button" cfg:"skip_provider_button"`
|
SkipProviderButton bool `flag:"skip-provider-button" cfg:"skip_provider_button"`
|
||||||
PassUserHeaders bool `flag:"pass-user-headers" cfg:"pass_user_headers"`
|
PassUserHeaders bool `flag:"pass-user-headers" cfg:"pass_user_headers"`
|
||||||
SSLInsecureSkipVerify bool `flag:"ssl-insecure-skip-verify" cfg:"ssl_insecure_skip_verify"`
|
SSLInsecureSkipVerify bool `flag:"ssl-insecure-skip-verify" cfg:"ssl_insecure_skip_verify"`
|
||||||
SetXAuthRequest bool `flag:"set-xauthrequest" cfg:"set_xauthrequest"`
|
SetXAuthRequest bool `flag:"set-xauthrequest" cfg:"set_xauthrequest"`
|
||||||
SetAuthorization bool `flag:"set-authorization-header" cfg:"set_authorization_header"`
|
SetAuthorization bool `flag:"set-authorization-header" cfg:"set_authorization_header"`
|
||||||
PassAuthorization bool `flag:"pass-authorization-header" cfg:"pass_authorization_header"`
|
PassAuthorization bool `flag:"pass-authorization-header" cfg:"pass_authorization_header"`
|
||||||
SkipAuthPreflight bool `flag:"skip-auth-preflight" cfg:"skip_auth_preflight"`
|
SkipAuthPreflight bool `flag:"skip-auth-preflight" cfg:"skip_auth_preflight"`
|
||||||
|
FlushInterval time.Duration `flag:"flush-interval" cfg:"flush_interval"`
|
||||||
|
|
||||||
// These options allow for other providers besides Google, with
|
// These options allow for other providers besides Google, with
|
||||||
// potential overrides.
|
// potential overrides.
|
||||||
|
Loading…
Reference in New Issue
Block a user