s
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
package gitrpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
|
||||
"simplegit/gitrpc/v1/v1connect"
|
||||
)
|
||||
|
||||
type GitRpcClient struct {
|
||||
baseURL string
|
||||
http *http.Client
|
||||
svc v1connect.GitServiceClient
|
||||
}
|
||||
|
||||
func NewClient(baseURL string) *GitRpcClient {
|
||||
httpClient := &http.Client{Timeout: 30 * time.Second}
|
||||
svc := v1connect.NewGitServiceClient(
|
||||
httpClient,
|
||||
baseURL,
|
||||
connect.WithInterceptors(tokenInterceptor()),
|
||||
)
|
||||
return &GitRpcClient{
|
||||
baseURL: baseURL,
|
||||
http: httpClient,
|
||||
svc: svc,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *GitRpcClient) GitService() v1connect.GitServiceClient { return c.svc }
|
||||
|
||||
type tokenCtxKey struct{}
|
||||
|
||||
func WithToken(ctx context.Context, token string) context.Context {
|
||||
return context.WithValue(ctx, tokenCtxKey{}, token)
|
||||
}
|
||||
|
||||
func tokenFromContext(ctx context.Context) (string, bool) {
|
||||
t, ok := ctx.Value(tokenCtxKey{}).(string)
|
||||
return t, ok
|
||||
}
|
||||
|
||||
func tokenInterceptor() connect.UnaryInterceptorFunc {
|
||||
return func(next connect.UnaryFunc) connect.UnaryFunc {
|
||||
return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
|
||||
if token, ok := tokenFromContext(ctx); ok {
|
||||
req.Header().Set("Authorization", "Bearer "+token)
|
||||
}
|
||||
return next(ctx, req)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func IsNotFound(err error) bool {
|
||||
return err != nil && connect.CodeOf(err) == connect.CodeNotFound
|
||||
}
|
||||
|
||||
func (c *GitRpcClient) GetRaw(ctx context.Context, repo, ref, path string) (io.ReadCloser, error) {
|
||||
return c.getBinary(ctx, "/raw", repo, url.Values{"ref": {ref}, "file": {path}})
|
||||
}
|
||||
|
||||
func (c *GitRpcClient) GetPatch(ctx context.Context, repo, sha string) (io.ReadCloser, error) {
|
||||
return c.getBinary(ctx, "/patch", repo, url.Values{"sha": {sha}})
|
||||
}
|
||||
|
||||
func (c *GitRpcClient) GetArchive(ctx context.Context, repo, ref, format string) (io.ReadCloser, error) {
|
||||
v := url.Values{"ref": {ref}}
|
||||
if format != "" {
|
||||
v.Set("format", format)
|
||||
}
|
||||
return c.getBinary(ctx, "/archive", repo, v)
|
||||
}
|
||||
|
||||
func (c *GitRpcClient) getBinary(ctx context.Context, endpoint, repo string, extra url.Values) (io.ReadCloser, error) {
|
||||
v := url.Values{"repo": {repo}}
|
||||
for k, vs := range extra {
|
||||
v[k] = vs
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.baseURL+endpoint+"?"+v.Encode(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if token, ok := tokenFromContext(ctx); ok {
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
}
|
||||
resp, err := c.http.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode >= 400 {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
return nil, fmt.Errorf("gitrpc %s: %s: %s", endpoint, resp.Status, body)
|
||||
}
|
||||
return resp.Body, nil
|
||||
}
|
||||
Reference in New Issue
Block a user