You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: container_gateway.go
    path of file: ./repos/arvados/lib/controller/localdb
    
    the code of the file until where you have to start completion: // Copyright (C) The Arvados Authors. All rights reserved.
//
// SPDX-License-Identifier: AGPL-3.0

package localdb

import (
	"bufio"
	"bytes"
	"context"
	"crypto/hmac"
	"crypto/sha256"
	"crypto/subtle"
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"strings"

	"git.arvados.org/arvados.git/lib/controller/rpc"
	"git.arvados.org/arvados.git/lib/service"
	"git.arvados.org/arvados.git/lib/webdavfs"
	"git.arvados.org/arvados.git/sdk/go/arvados"
	"git.arvados.org/arvados.git/sdk/go/auth"
	"git.arvados.org/arvados.git/sdk/go/ctxlog"
	"git.arvados.org/arvados.git/sdk/go/httpserver"
	keepweb "git.arvados.org/arvados.git/services/keep-web"
	"github.com/hashicorp/yamux"
	"golang.org/x/net/webdav"
)

var (
	forceProxyForTest       = false
	forceInternalURLForTest *arvados.URL
)

// ContainerRequestLog returns a WebDAV handler that reads logs from
// the indicated container request. It works by proxying the incoming
// HTTP request to
//
//   - the container gateway, if there is an associated container that
//     is running
//
//   - a different controller process, if there is a running container
//     whose gateway is accessible through a tunnel to a different
//     controller process
//
//   - keep-web, if saved logs exist and there is no gateway (or the
//     associated container is finished)
//
//   - an empty-collection stub, if there is no gateway and no saved
//     log
//
// For an incoming request
//
//	GET /arvados/v1/container_requests/{cr_uuid}/log/{c_uuid}{/c_log_path}
//
// The upstream request may be to {c_uuid}'s container gateway
//
//	GET /arvados/v1/container_requests/{cr_uuid}/log/{c_uuid}{/c_log_path}
//	X-Webdav-Prefix: /arvados/v1/container_requests/{cr_uuid}/log/{c_uuid}
//	X-Webdav-Source: /log
//
// ...or the upstream request may be to keep-web (where {cr_log_uuid}
// is the container request log collection UUID)
//
//	GET /arvados/v1/container_requests/{cr_uuid}/log/{c_uuid}{/c_log_path}
//	Host: {cr_log_uuid}.internal
//	X-Webdav-Prefix: /arvados/v1/container_requests/{cr_uuid}/log
//	X-Arvados-Container-Uuid: {c_uuid}
//
// ...or the request may be handled locally using an empty-collection
// stub.
func (conn *Conn) ContainerRequestLog(ctx context.Context, opts arvados.ContainerLogOptions) (http.Handler, error) {
	if opts.Method == "OPTIONS" && opts.Header.Get("Access-Control-Request-Method") != "" {
		return http.HandlerFunc(func(w http.Response
    
func (conn *Conn) serveContainerRequestLogViaKeepWeb(opts arvados.ContainerLogOptions, cr arvados.ContainerRequest, w http.ResponseWriter, r *http.Request) {
	if cr.LogUUID == "" {
		// Special case: if no log data exists yet, we serve
		// an empty collection by ourselves instead of
		// proxying to keep-web.
		conn.serveEmptyDir("/arvados/v1/container_requests/"+cr.UUID+"/log", w, r)
		return
	}
	myURL, _ := service.URLFromContext(r.Context())
	u := url.URL(myURL)
	myHostname := u.Hostname()
	var webdavBase arvados.URL
	var ok bool
	for webdavBase = range conn.cluster.Services.WebDAV.InternalURLs {
		ok = true
		u := url.URL(webdavBase)
		if h := u.Hostname(); h == "127.0.0.1" || h == "0.0.0.0" || h == "::1" || h == myHostname {
			// Prefer a keep-web service running on the
			// same host as us. (If we don't find one, we
			// pick one arbitrarily.)
			break
		}
	}
	if !ok {
		httpserver.Error(w, "no internalURLs configured for WebDAV service", http.StatusInternalServerError)
		return
	}
	proxy := &httputil.ReverseProxy{
		Director: func(r *http.Request) {
			r.URL.Scheme = webdavBase.Scheme
			r.URL.Host = webdavBase.Host
			// Outgoing Host header specifies the
			// collection ID.
			r.Host = cr.LogUUID + ".internal"
			// We already checked permission on the
			// container, so we can use a root token here
			// instead of counting on the "access to log
			// via container request and container"
			// permission check, which can be racy when a
			// request gets retried with a new container.
			r.Header.Set("Authorization", "Bearer "+conn.cluster.SystemRootToken)
			// We can't change r.URL.Path without
			// confusing WebDAV (request body and response
			// headers refer to the same paths) so we tell
			// keep-web to map the log collection onto the
			// containers/X/log/ namespace.
			r.Header.Set("X-Webdav-Prefix", "/arvados/v1/container_requests/"+cr.UUID+"/log")
			if len(opts.Path) >= 28 && opts.Path[6:13] == "-dz642-" {
				// "/arvados/v1/container_requests/{crUUID}/log/{cUUID}..."
				// proxies to
				// "/log for container {cUUID}..."
				r.Header.Set("X-Webdav-Prefix", "/arvados/v1/container_requests/"+cr.UUID+"/log/"+opts.Path[1:28])
				r.Header.Set("X-Webdav-Source", "/log for container "+opts.Path[1:28]+"/")
			}
		},
		ModifyResponse: func(resp *http.Response) error {
			preemptivelyDeduplicateHeaders(w.Header(), resp.Header)
			return nil
		},
	}
	if conn.cluster.TLS.Insecure {
		proxy.Transport = &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: conn.cluster.TLS.Insecure,
			},
		}
	}
	proxy.ServeHTTP(w, r)
}