简体   繁体   中英

How can I set HTTP request headers when using Go-Github and an http.Transport?

I am writing an app that uses the GitHub API to look at repositories in my GitHub orgs. I am using the github.com/google/go-github library.

I am also using the github.com/gregjones/httpcache so that I can do token based authentication as well as set the conditional headers for the API calls. I have got authentication working thus:

ctx := context.Background()

// GitHUb API authentication
transport = &oauth2.Transport{
    Source: oauth2.StaticTokenSource(
        &oauth2.Token{
            AccessToken: gh.tokens.GitHub.Token,
        },
    ),
}

// Configure HTTP memory caching
transport = &httpcache.Transport{
    Transport:           transport,
    Cache:               httpcache.NewMemoryCache(),
    MarkCachedResponses: true,
}

// Create the http client that GutHUb will use
httpClient := &http.Client{
    Transport: transport,
}

// Attempt to login to GitHub
client := github.NewClient(httpClient)

However I am unable to work out how to add the necessary If-Match header when I use client.Repositories.Get for example. This is so I can work out if the repo has changed in the last 24 hours for exampple.

I have searched how to do this, but the examples I come across show how to create an HTTP client and then create a request (so the headers can be added) and then do a Do action on it. However As I am using the client directly I do not have that option.

The documentation for go-github states that for conditional requests:

The GitHub API has good support for conditional requests which will help prevent you from burning through your rate limit, as well as help speed up your application. go-github does not handle conditional requests directly, but is instead designed to work with a caching http.Transport. We recommend using https://github.com/gregjones/httpcache for that.

Learn more about GitHub conditional requests at https://developer.github.com/v3/#conditional-requests .

I do not know how to add it in my code, any help is greatly appreciated.

As tends to be the case with these things, shortly after posting my question I found the answer.

The trick is to set the headers using the Base in the Oauth2 transport thus:

transport = &oauth2.Transport{
    Source: oauth2.StaticTokenSource(
        &oauth2.Token{
            AccessToken: gh.tokens.GitHub.Token,
        },
    ),
    Base: &transportHeaders{
        modifiedSince: modifiedSince,
    },
}

The struct and method look like:

type transportHeaders struct {
    modifiedSince string
}

func (t *transportHeaders) RoundTrip(req *http.Request) (*http.Response, error) {

    // Determine the last modified date based on the transportHeader options
    // Do not add any headers if blank or zero
    if t.modifiedSince != "" {
        req.Header.Set("If-Modified-Since", t.modifiedSince)
    }

    return http.DefaultTransport.RoundTrip(req)
}

So by doing this I can intercept the call to RoundTrip and add my own header. This now means I can check the resources and see if they return a 304 HTTP status code. For example:

ERRO[0001] Error retrieving repository                   error="GET https://api.github.com/repos/chef-partners/camsa-setup: 304  []" name=camsa-setup vcs=github

I worked out how to do this after coming across this page - https://github.com/rmichela/go-reddit/blob/bd882abbb7496c54dbde66d92c35ad95d4db1211/authenticator.go#L117

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM