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