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: get_contents.go
    path of file: ./repos/porter/api/server/handlers/gitinstallation
    
    the code of the file until where you have to start completion: package gitinstallation

import (
	"net/http"

	"github.com/google/go-github/v41/github"
	"github.com/porter-dev/porter/api/server/authz"
	"github.com/porter-dev/porter/api/server/handlers"
	"github.com/porter-dev/porter/api/server/shared"
	"github.com/porter-dev/porter/api/server/shared/apierrors"
	"github.com/porter-dev/porter/api/server/shared/commonutils"
	"github.com/porter-dev/porter/api/server/shared/config"
	"github.com/porter-dev/porter/api/types"
	"github.com/porter-dev/porter/internal/telemetry"
)

type GithubGetContentsHandler struct {
	handlers.PorterHandlerReadWriter
	authz.KubernetesAgentGetter
}

func NewGithubGetContentsHandler(
	config *config.Config,
	decoderValidator shared.RequestDecoderValidator,
	writer shared.ResultWriter,
) *GithubGetContentsHandler {
	return &GithubGetContentsHandler{
		PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
	}
}

func (c *GithubGetContentsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ctx, span := telemetry.NewSpan(r.Context(), "serve-github-get-contents")
	defer span.End()

	request := &types.GetContentsRequest{}
	if ok := c.DecodeAndValidate(w, r, request); !ok {
		err := telemetry.Error(ctx, span, nil, "invalid request")
		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
		return
	}

	owner, name, ok := commonutils.GetOwnerAndNameParams(c, w, r)
	if !ok {
		err := telemetry.Error(ctx, span, nil, "owner and name params not found")
		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
		return
	}

	branch, ok := commonuti
    
func (c *GithubGetContentsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ctx, span := telemetry.NewSpan(r.Context(), "serve-github-get-contents")
	defer span.End()

	request := &types.GetContentsRequest{}
	if ok := c.DecodeAndValidate(w, r, request); !ok {
		err := telemetry.Error(ctx, span, nil, "invalid request")
		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
		return
	}

	owner, name, ok := commonutils.GetOwnerAndNameParams(c, w, r)
	if !ok {
		err := telemetry.Error(ctx, span, nil, "owner and name params not found")
		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
		return
	}

	branch, ok := commonutils.GetBranchParam(c, w, r)
	if !ok {
		err := telemetry.Error(ctx, span, nil, "branch param not found")
		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
		return
	}

	client, err := GetGithubAppClientFromRequest(c.Config(), r)
	if err != nil {
		err = telemetry.Error(ctx, span, err, "could not get github app client from request")
		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
		return
	}

	telemetry.WithAttributes(
		span,
		telemetry.AttributeKV{Key: "repo-owner", Value: owner},
		telemetry.AttributeKV{Key: "repo-name", Value: name},
		telemetry.AttributeKV{Key: "repo-branch", Value: branch},
		telemetry.AttributeKV{Key: "repo-path", Value: request.Dir},
	)

	repoContentOptions := github.RepositoryContentGetOptions{}
	repoContentOptions.Ref = branch
	_, directoryContents, resp, err := client.Repositories.GetContents(
		ctx,
		owner,
		name,
		request.Dir,
		&repoContentOptions,
	)
	if err != nil {
		err = telemetry.Error(ctx, span, err, "could not get contents from github")
		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, resp.StatusCode))
		return
	}

	res := make(types.GetContentsResponse, 0)

	for i := range directoryContents {
		res = append(res, types.GithubDirectoryItem{
			Path: *directoryContents[i].Path,
			Type: *directoryContents[i].Type,
		})
	}

	c.WriteResult(w, r, res)
}