working commit

This commit is contained in:
2026-02-27 19:04:57 +02:00
parent 7de22e3816
commit 9fa5a00421
12 changed files with 210 additions and 213 deletions

View File

@@ -7,17 +7,16 @@ import (
"strconv" "strconv"
) )
func (cli *Client) BlobExists(ctx context.Context, rawref string) (bool, int64, error) { func (cli *Client) BlobExists(ctx context.Context, rawrepo string, digest string) (bool, int64, error) {
var err error var err error
var exist bool var exist bool
var size int64 var size int64
ref, err := NewReference(rawref) ref, err := NewRepository(rawrepo)
if err != nil { if err != nil {
return exist, size, err return exist, size, err
} }
uri := ref.Blob() uri := ref.Blob(digest)
user, pass := ref.Userinfo()
fmt.Println(uri) fmt.Println(uri)
req, err := http.NewRequestWithContext(ctx, http.MethodHead, uri, nil) req, err := http.NewRequestWithContext(ctx, http.MethodHead, uri, nil)
@@ -27,14 +26,6 @@ func (cli *Client) BlobExists(ctx context.Context, rawref string) (bool, int64,
req.Header.Set("User-Agent", cli.userAgent) req.Header.Set("User-Agent", cli.userAgent)
req.Header.Set("Accept", "*/*") req.Header.Set("Accept", "*/*")
if cli.authenticator != nil {
authHeader, authKey, err := cli.authenticator.MakeHeader(user, pass)
if err != nil {
return exist, size, err
}
req.Header.Set(authHeader, authKey)
}
resp, err := cli.httpClient.Do(req) resp, err := cli.httpClient.Do(req)
if err != nil { if err != nil {
return exist, size, err return exist, size, err

View File

@@ -2,13 +2,13 @@ package client
import ( import (
"crypto/tls" "crypto/tls"
"encoding/base64"
"net/http" "net/http"
) )
type Client struct { type Client struct {
httpClient *http.Client httpClient *http.Client
authenticator Authenticator userAgent string
userAgent string
} }
func NewClient() *Client { func NewClient() *Client {
@@ -22,28 +22,88 @@ func NewClient() *Client {
} }
} }
func (cli *Client) SetAuthenticator(auth Authenticator) {
cli.authenticator = auth
}
func (cli *Client) SetTransport(transport http.RoundTripper) { func (cli *Client) SetTransport(transport http.RoundTripper) {
cli.httpClient.Transport = transport cli.httpClient.Transport = transport
} }
type WrapTransport struct { type MiddlewareFunc func(next http.RoundTripper) http.RoundTripper
transport http.RoundTripper
func (cli *Client) UseMiddleware(mwFunc MiddlewareFunc) {
cli.httpClient.Transport = mwFunc(cli.httpClient.Transport)
} }
func NewWrapTransport(transport http.RoundTripper) *WrapTransport { // ExampleMiddleware
return &WrapTransport{ func NewExampleMiddleware() MiddlewareFunc {
transport: transport, return func(next http.RoundTripper) http.RoundTripper {
return newExampleTransport(next)
} }
} }
func (wrap *WrapTransport) RoundTrip(req *http.Request) (*http.Response, error) { type ExampleTransport struct {
return wrap.transport.RoundTrip(req) next http.RoundTripper
} }
func newExampleTransport(next http.RoundTripper) *ExampleTransport {
return &ExampleTransport{
next: next,
}
}
func (tran ExampleTransport) RoundTrip(req *http.Request) (*http.Response, error) {
return tran.next.RoundTrip(req)
}
// BasicAuthMiddleware
func NewBasicAuthMiddleware(user, pass string) MiddlewareFunc {
return func(next http.RoundTripper) http.RoundTripper {
return newBasicAuthMW(next, user, pass)
}
}
type BasicAuthMW struct {
user, pass string
next http.RoundTripper
}
func newBasicAuthMW(next http.RoundTripper, user, pass string) *BasicAuthMW {
return &BasicAuthMW{
user: user,
pass: pass,
next: next,
}
}
func (tran BasicAuthMW) RoundTrip(req *http.Request) (*http.Response, error) {
pair := base64.StdEncoding.EncodeToString([]byte(tran.user + ":" + tran.pass))
req.Header.Set("Authorization", "Basic "+pair)
return tran.next.RoundTrip(req)
}
// BearerAuthMiddleware
func NewBearerAuthMiddleware(token string) MiddlewareFunc {
return func(next http.RoundTripper) http.RoundTripper {
return newBearerAuthMW(next, token)
}
}
type BearerAuthMW struct {
token string
next http.RoundTripper
}
func newBearerAuthMW(next http.RoundTripper, token string) *BearerAuthMW {
return &BearerAuthMW{
token: token,
next: next,
}
}
func (tran BearerAuthMW) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Set("Authorization", "Bearer "+tran.token)
return tran.next.RoundTrip(req)
}
// DefaultTransport
type DefaultTransport struct { type DefaultTransport struct {
transport http.RoundTripper transport http.RoundTripper
} }

View File

@@ -12,15 +12,16 @@ import (
"time" "time"
) )
func TestClientGetManifest(t *testing.T) { func xxxTestClientGetManifest(t *testing.T) {
rawrefs := []string{ rawrepo := "mirror.gcr.io/alpine"
"mirror.gcr.io/alpine:3.20.0", tags := []string{
"mirror.gcr.io/alpine:sha256:29e5ba63e79337818e6c63cfcc68e2ab4e9ca483853b2de303bfbfba9372426c", "3.20.0",
"sha256:29e5ba63e79337818e6c63cfcc68e2ab4e9ca483853b2de303bfbfba9372426c",
} }
for _, rawref := range rawrefs { for _, tag := range tags {
cli := NewClient() cli := NewClient()
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
exist, mime, man, err := cli.GetManifest(ctx, rawref) exist, mime, man, err := cli.GetManifest(ctx, rawrepo, tag)
require.NoError(t, err) require.NoError(t, err)
require.True(t, exist) require.True(t, exist)
@@ -32,15 +33,17 @@ func TestClientGetManifest(t *testing.T) {
} }
} }
func xxxTestClientManifestExists(t *testing.T) { func TestClientManifestExists(t *testing.T) {
rawrefs := []string{ rawrepo := "mirror.gcr.io/alpine"
"mirror.gcr.io/alpine:3.20.0", tags := []string{
"mirror.gcr.io/alpine:sha256:29e5ba63e79337818e6c63cfcc68e2ab4e9ca483853b2de303bfbfba9372426c", "3.20.0",
"sha256:29e5ba63e79337818e6c63cfcc68e2ab4e9ca483853b2de303bfbfba9372426c",
} }
for _, rawref := range rawrefs { for _, tag := range tags {
cli := NewClient() cli := NewClient()
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
exist, mime, size, csum, err := cli.ManifestExists(ctx, rawref) exist, mime, size, csum, err := cli.ManifestExists(ctx, rawrepo, tag)
require.NoError(t, err) require.NoError(t, err)
require.True(t, exist) require.True(t, exist)
@@ -52,13 +55,14 @@ func xxxTestClientManifestExists(t *testing.T) {
} }
func xxxTestClientBlobExists(t *testing.T) { func xxxTestClientBlobExists(t *testing.T) {
rawrefs := []string{ rawrepos := []string{
"mirror.gcr.io/alpine:sha256:3b8747b05489980f63da1d2b8e5a444c55777f69540394397b0bc1c76c3e41f2", "mirror.gcr.io/alpine",
} }
for _, rawref := range rawrefs { for _, rawrepo := range rawrepos {
cli := NewClient() cli := NewClient()
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
exist, size, err := cli.BlobExists(ctx, rawref) digest := "sha256:3b8747b05489980f63da1d2b8e5a444c55777f69540394397b0bc1c76c3e41f2"
exist, size, err := cli.BlobExists(ctx, rawrepo, digest)
require.NoError(t, err) require.NoError(t, err)
require.True(t, exist) require.True(t, exist)
@@ -66,52 +70,37 @@ func xxxTestClientBlobExists(t *testing.T) {
} }
} }
func xxxTestClientGetBlob(t *testing.T) { func TestClientGetBlob(t *testing.T) {
rawrefs := []string{ rawrepos := []string{
"mirror.gcr.io/alpine:sha256:3b8747b05489980f63da1d2b8e5a444c55777f69540394397b0bc1c76c3e41f2", "mirror.gcr.io/alpine",
} }
for _, rawref := range rawrefs { for _, rawrepo := range rawrepos {
cli := NewClient() cli := NewClient()
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
buffer := bytes.NewBuffer(nil) buffer := bytes.NewBuffer(nil)
exist, err := cli.GetBlob(ctx, rawref, buffer) digest := "sha256:3b8747b05489980f63da1d2b8e5a444c55777f69540394397b0bc1c76c3e41f2"
exist, err := cli.GetBlob(ctx, rawrepo, buffer, digest)
require.NoError(t, err) require.NoError(t, err)
require.True(t, exist) require.True(t, exist)
fmt.Printf("Size: %d\n", len(buffer.Bytes())) fmt.Printf("Size: %d\n", len(buffer.Bytes()))
} }
} }
func TestClientGetUpload(t *testing.T) { func xxxxTestClientGetUpload(t *testing.T) {
rawrefs := []string{ rawrepos := []string{
"mstore:mstore@localhost:1025/alpine:3.20.0", "mstore:mstore@localhost:1025/alpine:3.20.0",
} }
for _, rawref := range rawrefs { cli := NewClient()
cli.UseMiddleware(NewBasicAuthMiddleware("mstore", "mstore"))
for _, rawrepo := range rawrepos {
var err error var err error
var loc string var loc string
{ {
cli := NewClient()
cli.SetAuthenticator(NewBasicAuthenticator())
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
loc, err = cli.GetUpload(ctx, rawref) loc, err = cli.GetUpload(ctx, rawrepo)
require.NoError(t, err) require.NoError(t, err)
fmt.Printf("Location: %s\n", loc) fmt.Printf("Upload Location: %s\n", loc)
}
{
srcsize := 1024 + 145
srcdata := make([]byte, srcsize)
_, err = rand.Read(srcdata)
require.NoError(t, err)
src := bytes.NewReader(srcdata)
digest := SHA256Digest(srcdata)
cli := NewClient()
cli.SetAuthenticator(NewBasicAuthenticator())
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
bloc, err := cli.PutUpload(ctx, rawref, src, loc, digest, int64(len(srcdata)))
require.NoError(t, err)
fmt.Printf("Location: %s\n", bloc)
} }
{ {
srcsize := 1024 + 145 srcsize := 1024 + 145
@@ -122,13 +111,49 @@ func TestClientGetUpload(t *testing.T) {
src := bytes.NewReader(srcdata) src := bytes.NewReader(srcdata)
//digest := SHA256Digest(srcdata) //digest := SHA256Digest(srcdata)
cli := NewClient()
cli.SetAuthenticator(NewBasicAuthenticator())
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
bloc, err := cli.PatchUpload(ctx, rawref, src, loc, int64(len(srcdata))) bloc, err := cli.PatchUpload(ctx, rawrepo, src, loc, int64(len(srcdata)))
require.NoError(t, err) require.NoError(t, err)
fmt.Printf("Location: %s\n", bloc) fmt.Printf("Path Location: %s\n", bloc)
}
{
srcsize := 1024 + 145
srcdata := make([]byte, srcsize)
_, err = rand.Read(srcdata)
require.NoError(t, err)
src := bytes.NewReader(srcdata)
digest := SHA256Digest(srcdata)
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
bloc, err := cli.PutUpload(ctx, rawrepo, src, loc, digest, int64(len(srcdata)))
require.NoError(t, err)
fmt.Printf("Put blob Location: %s\n", bloc)
} }
} }
} }
func xxxxTestClientGetToken(t *testing.T) {
var token string
var err error
{
cli := NewClient()
cli.UseMiddleware(NewBasicAuthMiddleware("onborodin", "2Albert334"))
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
token, err = cli.GetToken(ctx, "https://auth.docker.io/token")
require.NoError(t, err)
}
fmt.Printf("Token: %s\n", token)
{
rawrepo := "docker.io/onborodin/toolbox:0.18"
cli := NewClient()
cli.UseMiddleware(NewBearerAuthMiddleware(token))
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
loc, err := cli.GetUpload(ctx, rawrepo)
require.NoError(t, err)
fmt.Printf("Upload Location: %s\n", loc)
}
}

View File

@@ -6,32 +6,21 @@ import (
"net/http" "net/http"
) )
func (cli *Client) DeleteManifest(ctx context.Context, rawref string) (bool, error) { func (cli *Client) DeleteManifest(ctx context.Context, rawrepo, tag string) (bool, error) {
var err error var err error
var exist bool var exist bool
ref, err := NewReference(rawref) ref, err := NewRepository(rawrepo)
if err != nil { if err != nil {
return exist, err return exist, err
} }
uri := ref.Manifest() uri := ref.Manifest(tag)
user, pass := ref.Userinfo()
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri, nil) req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri, nil)
if err != nil { if err != nil {
return exist, err return exist, err
} }
req.Header.Set("User-Agent", cli.userAgent) req.Header.Set("User-Agent", cli.userAgent)
req.Header.Set("Accept", "*/*") req.Header.Set("Accept", "*/*")
if cli.authenticator != nil {
authHeader, authKey, err := cli.authenticator.MakeHeader(user, pass)
if err != nil {
return exist, err
}
req.Header.Set(authHeader, authKey)
}
resp, err := cli.httpClient.Do(req) resp, err := cli.httpClient.Do(req)
if err != nil { if err != nil {
return exist, err return exist, err

View File

@@ -8,16 +8,15 @@ import (
"strconv" "strconv"
) )
func (cli *Client) GetBlob(ctx context.Context, rawref string, writer io.Writer) (bool, error) { func (cli *Client) GetBlob(ctx context.Context, rawrepo string, writer io.Writer, digest string) (bool, error) {
var err error var err error
var exist bool var exist bool
ref, err := NewReference(rawref) ref, err := NewRepository(rawrepo)
if err != nil { if err != nil {
return exist, err return exist, err
} }
uri := ref.Blob() uri := ref.Blob(digest)
user, pass := ref.Userinfo()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
if err != nil { if err != nil {
@@ -25,15 +24,6 @@ func (cli *Client) GetBlob(ctx context.Context, rawref string, writer io.Writer)
} }
req.Header.Set("User-Agent", cli.userAgent) req.Header.Set("User-Agent", cli.userAgent)
req.Header.Set("Accept", "*/*") req.Header.Set("Accept", "*/*")
if cli.authenticator != nil {
authHeader, authKey, err := cli.authenticator.MakeHeader(user, pass)
if err != nil {
return exist, err
}
req.Header.Set(authHeader, authKey)
}
resp, err := cli.httpClient.Do(req) resp, err := cli.httpClient.Do(req)
if err != nil { if err != nil {
return exist, err return exist, err

View File

@@ -9,18 +9,17 @@ import (
"strings" "strings"
) )
func (cli *Client) GetManifest(ctx context.Context, rawref string) (bool, string, []byte, error) { func (cli *Client) GetManifest(ctx context.Context, rawrepo, tag string) (bool, string, []byte, error) {
var err error var err error
var exist bool var exist bool
var mime string var mime string
var man []byte var man []byte
ref, err := NewReference(rawref) ref, err := NewRepository(rawrepo)
if err != nil { if err != nil {
return exist, mime, man, err return exist, mime, man, err
} }
uri := ref.Manifest() uri := ref.Manifest(tag)
user, pass := ref.Userinfo()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
if err != nil { if err != nil {
@@ -28,15 +27,6 @@ func (cli *Client) GetManifest(ctx context.Context, rawref string) (bool, string
} }
req.Header.Set("User-Agent", cli.userAgent) req.Header.Set("User-Agent", cli.userAgent)
req.Header.Set("Accept", "*/*") req.Header.Set("Accept", "*/*")
if cli.authenticator != nil {
authHeader, authKey, err := cli.authenticator.MakeHeader(user, pass)
if err != nil {
return exist, mime, man, err
}
req.Header.Set(authHeader, authKey)
}
resp, err := cli.httpClient.Do(req) resp, err := cli.httpClient.Do(req)
if err != nil { if err != nil {
return exist, mime, man, err return exist, mime, man, err

View File

@@ -6,16 +6,15 @@ import (
"net/http" "net/http"
) )
func (cli *Client) GetUpload(ctx context.Context, rawref string) (string, error) { func (cli *Client) GetUpload(ctx context.Context, rawrepo string) (string, error) {
var err error var err error
var loc string var loc string
ref, err := NewReference(rawref) ref, err := NewRepository(rawrepo)
if err != nil { if err != nil {
return loc, err return loc, err
} }
uri := ref.Upload() uri := ref.Upload()
user, pass := ref.Userinfo()
req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil) req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil)
if err != nil { if err != nil {
@@ -23,26 +22,20 @@ func (cli *Client) GetUpload(ctx context.Context, rawref string) (string, error)
} }
req.Header.Set("User-Agent", cli.userAgent) req.Header.Set("User-Agent", cli.userAgent)
req.Header.Set("Accept", "*/*") req.Header.Set("Accept", "*/*")
if cli.authenticator != nil {
authHeader, authKey, err := cli.authenticator.MakeHeader(user, pass)
if err != nil {
return loc, err
}
req.Header.Set(authHeader, authKey)
}
resp, err := cli.httpClient.Do(req) resp, err := cli.httpClient.Do(req)
if err != nil { if err != nil {
return loc, err return loc, err
} }
defer resp.Body.Close() defer resp.Body.Close()
fmt.Printf("=== %++v\n", resp.Header)
if resp.StatusCode != http.StatusAccepted { if resp.StatusCode != http.StatusAccepted {
err := fmt.Errorf("Unxected response code %s", resp.Status) err := fmt.Errorf("Unxected response code %s", resp.Status)
return loc, err return loc, err
} }
loc = resp.Header.Get("Location") loc = resp.Header.Get("Location")
if loc == "" { if loc == "" {
err := fmt.Errorf("Empty location declaration") err := fmt.Errorf("Empty location declaration")
return loc, err return loc, err

View File

@@ -7,19 +7,18 @@ import (
"strconv" "strconv"
) )
func (cli *Client) ManifestExists(ctx context.Context, rawref string) (bool, string, int64, string, error) { func (cli *Client) ManifestExists(ctx context.Context, rawrepo, tag string) (bool, string, int64, string, error) {
var err error var err error
var exist bool var exist bool
var mime string var mime string
var size int64 var size int64
var csum string var csum string
ref, err := NewReference(rawref) ref, err := NewRepository(rawrepo)
if err != nil { if err != nil {
return exist, mime, size, csum, err return exist, mime, size, csum, err
} }
uri := ref.Manifest() uri := ref.Manifest(tag)
user, pass := ref.Userinfo()
req, err := http.NewRequestWithContext(ctx, http.MethodHead, uri, nil) req, err := http.NewRequestWithContext(ctx, http.MethodHead, uri, nil)
if err != nil { if err != nil {
@@ -27,15 +26,6 @@ func (cli *Client) ManifestExists(ctx context.Context, rawref string) (bool, str
} }
req.Header.Set("User-Agent", cli.userAgent) req.Header.Set("User-Agent", cli.userAgent)
req.Header.Set("Accept", "*/*") req.Header.Set("Accept", "*/*")
if cli.authenticator != nil {
authHeader, authKey, err := cli.authenticator.MakeHeader(user, pass)
if err != nil {
return exist, mime, size, csum, err
}
req.Header.Set(authHeader, authKey)
}
resp, err := cli.httpClient.Do(req) resp, err := cli.httpClient.Do(req)
if err != nil { if err != nil {
return exist, mime, size, csum, err return exist, mime, size, csum, err

View File

@@ -8,11 +8,11 @@ import (
"strconv" "strconv"
) )
func (cli *Client) PatchUpload(ctx context.Context, rawref string, src io.Reader, uploc string, size int64) (string, error) { func (cli *Client) PatchUpload(ctx context.Context, rawrepo string, src io.Reader, uploc string, size int64) (string, error) {
var err error var err error
var ouloc string var ouloc string
ref, err := NewReference(rawref) ref, err := NewRepository(rawrepo)
if err != nil { if err != nil {
return ouloc, err return ouloc, err
} }
@@ -20,8 +20,6 @@ func (cli *Client) PatchUpload(ctx context.Context, rawref string, src io.Reader
if err != nil { if err != nil {
return ouloc, err return ouloc, err
} }
user, pass := ref.Userinfo()
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, uri, src) req, err := http.NewRequestWithContext(ctx, http.MethodPatch, uri, src)
if err != nil { if err != nil {
return ouloc, err return ouloc, err
@@ -29,13 +27,6 @@ func (cli *Client) PatchUpload(ctx context.Context, rawref string, src io.Reader
req.Header.Set("User-Agent", cli.userAgent) req.Header.Set("User-Agent", cli.userAgent)
req.Header.Set("Content-Type", "application/octet-stream") req.Header.Set("Content-Type", "application/octet-stream")
req.Header.Set("Content-Length", strconv.FormatInt(size, 10)) req.Header.Set("Content-Length", strconv.FormatInt(size, 10))
if cli.authenticator != nil {
authHeader, authKey, err := cli.authenticator.MakeHeader(user, pass)
if err != nil {
return ouloc, err
}
req.Header.Set(authHeader, authKey)
}
resp, err := cli.httpClient.Do(req) resp, err := cli.httpClient.Do(req)
if err != nil { if err != nil {
return ouloc, err return ouloc, err

View File

@@ -7,15 +7,14 @@ import (
"net/http" "net/http"
) )
func (cli *Client) PutManifest(ctx context.Context, rawref string, man []byte, mime string) error { func (cli *Client) PutManifest(ctx context.Context, rawrepo, tag string, man []byte, mime string) error {
var err error var err error
ref, err := NewReference(rawref) ref, err := NewRepository(rawrepo)
if err != nil { if err != nil {
return err return err
} }
uri := ref.Manifest() uri := ref.Manifest(tag)
user, pass := ref.Userinfo()
buffer := bytes.NewBuffer(man) buffer := bytes.NewBuffer(man)
req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, buffer) req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, buffer)
@@ -25,13 +24,6 @@ func (cli *Client) PutManifest(ctx context.Context, rawref string, man []byte, m
req.Header.Set("User-Agent", cli.userAgent) req.Header.Set("User-Agent", cli.userAgent)
req.Header.Set("Docker-Content-Digest", SHA256Digest(man)) req.Header.Set("Docker-Content-Digest", SHA256Digest(man))
req.Header.Set("Content-Type", mime) req.Header.Set("Content-Type", mime)
if cli.authenticator != nil {
authHeader, authKey, err := cli.authenticator.MakeHeader(user, pass)
if err != nil {
return err
}
req.Header.Set(authHeader, authKey)
}
resp, err := cli.httpClient.Do(req) resp, err := cli.httpClient.Do(req)
if err != nil { if err != nil {
return err return err

View File

@@ -8,11 +8,11 @@ import (
"strconv" "strconv"
) )
func (cli *Client) PutUpload(ctx context.Context, rawref string, src io.Reader, uploc, digest string, size int64) (string, error) { func (cli *Client) PutUpload(ctx context.Context, rawrepo string, src io.Reader, uploc, digest string, size int64) (string, error) {
var err error var err error
var bloc string var bloc string
ref, err := NewReference(rawref) ref, err := NewRepository(rawrepo)
if err != nil { if err != nil {
return bloc, err return bloc, err
} }
@@ -20,8 +20,6 @@ func (cli *Client) PutUpload(ctx context.Context, rawref string, src io.Reader,
if err != nil { if err != nil {
return bloc, err return bloc, err
} }
user, pass := ref.Userinfo()
req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, src) req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, src)
if err != nil { if err != nil {
return bloc, err return bloc, err
@@ -29,13 +27,6 @@ func (cli *Client) PutUpload(ctx context.Context, rawref string, src io.Reader,
req.Header.Set("User-Agent", cli.userAgent) req.Header.Set("User-Agent", cli.userAgent)
req.Header.Set("Content-Type", "application/octet-stream") req.Header.Set("Content-Type", "application/octet-stream")
req.Header.Set("Content-Length", strconv.FormatInt(size, 10)) req.Header.Set("Content-Length", strconv.FormatInt(size, 10))
if cli.authenticator != nil {
authHeader, authKey, err := cli.authenticator.MakeHeader(user, pass)
if err != nil {
return bloc, err
}
req.Header.Set(authHeader, authKey)
}
resp, err := cli.httpClient.Do(req) resp, err := cli.httpClient.Do(req)
if err != nil { if err != nil {
return bloc, err return bloc, err

View File

@@ -1,88 +1,87 @@
package client package client
import ( import (
"errors"
"net/url" "net/url"
"strings" "strings"
) )
type Reference struct { type Repository struct {
urlobj *url.URL urlobj *url.URL
user, pass string user, pass string
repo, tag string base string
} }
func NewReference(rawref string) (*Reference, error) { func NewRepository(rawrepo string) (*Repository, error) {
ref := &Reference{} repo := &Repository{}
if !strings.Contains(rawref, "://") { if !strings.Contains(rawrepo, "://") {
rawref = "https://" + rawref rawrepo = "https://" + rawrepo
} }
urlobj, err := url.Parse(rawref) urlobj, err := url.Parse(rawrepo)
if err != nil { if err != nil {
return ref, err return repo, err
} }
if urlobj.User != nil { if urlobj.User != nil {
ref.user = urlobj.User.Username() repo.user = urlobj.User.Username()
ref.pass, _ = urlobj.User.Password() repo.pass, _ = urlobj.User.Password()
urlobj.User = nil urlobj.User = nil
} }
repotag := strings.SplitN(urlobj.Path, ":", 2) repo.urlobj = urlobj
if len(repotag) != 2 { repo.base = repo.urlobj.Path
err = errors.New("Incorrect repo") repo.urlobj.Path = "/"
return ref, err repo.urlobj = urlobj
}
ref.urlobj = urlobj
ref.urlobj.Path = "/"
ref.repo = repotag[0]
ref.tag = repotag[1]
ref.urlobj = urlobj
return ref, err return repo, err
} }
func (ref *Reference) Manifest() string { func (repo *Repository) Manifest(tag string) string {
curl := ref.urlobj.JoinPath("/v2", ref.repo, "/manifests", ref.tag) curl := repo.urlobj.JoinPath("/v2", repo.base, "/manifests", tag)
return curl.String() return curl.String()
} }
func (ref *Reference) Blob() string { func (repo *Repository) Blob(digest string) string {
curl := ref.urlobj.JoinPath("/v2", ref.repo, "/blobs", ref.tag) curl := repo.urlobj.JoinPath("/v2", repo.base, "/blobs", digest)
return curl.String() return curl.String()
} }
func (ref *Reference) Upload() string { func (repo *Repository) Upload() string {
curl := ref.urlobj.JoinPath("/v2", ref.repo, "/blobs/uploads/") curl := repo.urlobj.JoinPath("/v2", repo.base, "/blobs/uploads/")
return curl.String() return curl.String()
} }
func (ref *Reference) Patch(loc string) (string, error) { func (repo *Repository) Patch(loc string) (string, error) {
var curl *url.URL var curl *url.URL
var out string var out string
var err error var err error
if isUUID(loc) {
curl = repo.urlobj.JoinPath("/v2/", repo.base, "/blobs/uploads/", loc)
return curl.String(), nil
}
if strings.Contains(loc, "://") { if strings.Contains(loc, "://") {
curl, err = url.Parse(loc) curl, err = url.Parse(loc)
if err != nil { if err != nil {
return out, err return out, err
} }
} else { } else {
curl = ref.urlobj.JoinPath(loc) curl = repo.urlobj.JoinPath(loc)
} }
out = curl.String() out = curl.String()
return out, err return out, err
} }
func (ref *Reference) Put(loc, digest string) (string, error) { func (repo *Repository) Put(loc, digest string) (string, error) {
var curl *url.URL var curl *url.URL
var out string var out string
var err error var err error
if strings.Contains(loc, "://") {
if isUUID(loc) {
curl = repo.urlobj.JoinPath("/v2/", repo.base, "/blobs/uploads/", loc)
} else if strings.Contains(loc, "://") {
curl, err = url.Parse(loc) curl, err = url.Parse(loc)
if err != nil { if err != nil {
return out, err return out, err
} }
} else { } else {
curl = ref.urlobj.JoinPath(loc) curl = repo.urlobj.JoinPath(loc)
} }
query := curl.Query() query := curl.Query()
query.Set("digest", digest) query.Set("digest", digest)
@@ -91,10 +90,6 @@ func (ref *Reference) Put(loc, digest string) (string, error) {
return out, err return out, err
} }
func (ref *Reference) Tag() string { func (repo *Repository) Userinfo() (string, string) {
return ref.tag return repo.user, repo.pass
}
func (ref *Reference) Userinfo() (string, string) {
return ref.user, ref.pass
} }