Skip to content

Commit b6c5215

Browse files
jdolitskypmengelbert
authored andcommitted
Fix issues with missing headers (#15)
* disable compression, redo SetBody Signed-off-by: Josh Dolitsky <[email protected]> * add additional testing Signed-off-by: Josh Dolitsky <[email protected]> * test passing in verifying request body Signed-off-by: Josh Dolitsky <[email protected]> * update readme example Signed-off-by: Josh Dolitsky <[email protected]>
1 parent 29eefd9 commit b6c5215

File tree

4 files changed

+70
-28
lines changed

4 files changed

+70
-28
lines changed

README.md

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ import (
130130
func main() {
131131
// construct client pointing to your registry
132132
client, err := reggie.NewClient("http://localhost:5000",
133-
reggie.WithDefaultName("my/repo"),
133+
reggie.WithDefaultName("myorg/myrepo"),
134134
reggie.WithDebug(true))
135135
if err != nil {
136136
panic(err)
@@ -152,8 +152,8 @@ func main() {
152152
blobDigest := godigest.FromBytes(blob).String()
153153

154154
// upload the first chunk
155-
req = client.NewRequest(reggie.PATCH, resp.GetRelativeLocation())
156-
req.SetHeader("Content-Type", "application/octet-stream").
155+
req = client.NewRequest(reggie.PATCH, resp.GetRelativeLocation()).
156+
SetHeader("Content-Type", "application/octet-stream").
157157
SetHeader("Content-Length", fmt.Sprintf("%d", len(blobChunk1))).
158158
SetHeader("Content-Range", blobChunk1Range).
159159
SetBody(blobChunk1)
@@ -163,8 +163,8 @@ func main() {
163163
}
164164

165165
// upload the final chunk and close the session
166-
req = client.NewRequest(reggie.PUT, resp.GetRelativeLocation())
167-
req.SetHeader("Content-Length", fmt.Sprintf("%d", len(blobChunk2))).
166+
req = client.NewRequest(reggie.PUT, resp.GetRelativeLocation()).
167+
SetHeader("Content-Length", fmt.Sprintf("%d", len(blobChunk2))).
168168
SetHeader("Content-Range", blobChunk2Range).
169169
SetHeader("Content-Type", "application/octet-stream").
170170
SetQueryParam("digest", blobDigest).
@@ -184,21 +184,15 @@ func main() {
184184
fmt.Printf("Blob content:\n%s\n", resp.String())
185185

186186
// upload the manifest (referencing the uploaded blob)
187-
ref := "test"
187+
ref := "mytag"
188188
manifest := []byte(fmt.Sprintf(
189-
`{
190-
"mediaType": "application/vnd.oci.image.manifest.v1+json",
191-
"config": {
192-
"digest": "%s",
193-
"mediaType": "application/vnd.oci.image.config.v1+json",
194-
"size": %d
195-
},
196-
"layers": [],
197-
"schemaVersion": 2
198-
}`, blobDigest, len(blob)))
189+
"{ \"mediaType\": \"application/vnd.oci.image.manifest.v1+json\", \"config\": { \"digest\": \"%s\", "+
190+
"\"mediaType\": \"application/vnd.oci.image.config.v1+json\","+" \"size\": %d }, \"layers\": [], "+
191+
"\"schemaVersion\": 2 }",
192+
blobDigest, len(blob)))
199193
req = client.NewRequest(reggie.PUT, "/v2/<name>/manifests/<reference>",
200-
reggie.WithReference(ref))
201-
req.SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
194+
reggie.WithReference(ref)).
195+
SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
202196
SetBody(manifest)
203197
resp, err = client.Do(req)
204198
if err != nil {
@@ -207,13 +201,12 @@ func main() {
207201

208202
// validate the uploaded manifest content
209203
req = client.NewRequest(reggie.GET, "/v2/<name>/manifests/<reference>",
210-
reggie.WithReference(ref))
211-
req.SetHeader("Accept", "application/vnd.oci.image.manifest.v1+json")
204+
reggie.WithReference(ref)).
205+
SetHeader("Accept", "application/vnd.oci.image.manifest.v1+json")
212206
resp, err = client.Do(req)
213207
if err != nil {
214208
panic(err)
215209
}
216210
fmt.Printf("Manifest content:\n%s\n", resp.String())
217211
}
218-
219212
```

client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,5 +144,6 @@ func createTransport() *http.Transport {
144144
TLSHandshakeTimeout: 10 * time.Second,
145145
ExpectContinueTimeout: 1 * time.Second,
146146
MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
147+
DisableCompression: true,
147148
}
148149
}

client_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package reggie
22

33
import (
4+
"bytes"
45
"encoding/base64"
56
"fmt"
67
"net/http"
@@ -9,6 +10,11 @@ import (
910
"testing"
1011
)
1112

13+
var (
14+
lastCapturedRequest *http.Request
15+
lastCapturedRequestBodyStr string
16+
)
17+
1218
func TestClient(t *testing.T) {
1319
authTestServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1420
expectedAuthHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte("testuser:testpass"))
@@ -23,6 +29,11 @@ func TestClient(t *testing.T) {
2329
defer authTestServer.Close()
2430

2531
registryTestServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
32+
lastCapturedRequest = r
33+
buf := new(bytes.Buffer)
34+
buf.ReadFrom(lastCapturedRequest.Body)
35+
lastCapturedRequestBodyStr = buf.String()
36+
2637
h := r.Header.Get("Authorization")
2738
if h == "Bearer abc123" {
2839
w.Header().Set("Location", "http://abc123location.io/v2/blobs/uploads/e361aeb8-3181-11ea-850d-2e728ce88125")
@@ -185,4 +196,40 @@ func TestClient(t *testing.T) {
185196
t.Fatalf("Expected error with bad address")
186197
}
187198

199+
// Make sure headers and body match after going through auth
200+
req = client.NewRequest(PUT, "/a/b/c").
201+
SetHeader("Content-Length", "3").
202+
SetHeader("Content-Range", "0-2").
203+
SetHeader("Content-Type", "application/octet-stream").
204+
SetQueryParam("digest", "xyz").
205+
SetBody([]byte("abc"))
206+
_, err = client.Do(req)
207+
if err != nil {
208+
t.Fatalf("Errors executing request: %s", err)
209+
}
210+
211+
// 5 headers expected: the ones we set plus "Authorization" and "User-Agent"
212+
numHeaders := len(lastCapturedRequest.Header)
213+
if numHeaders != 5 {
214+
fmt.Println(lastCapturedRequest.Header)
215+
t.Fatalf("Expected 5 headers total, instead got %d", numHeaders)
216+
}
217+
218+
// Just to be safe, lets check each of the 5 headers are ones we expect
219+
for _, h := range []string{
220+
"Content-Length",
221+
"Content-Range",
222+
"Content-Type",
223+
"Authorization",
224+
"User-Agent",
225+
} {
226+
if lastCapturedRequest.Header.Get(h) == "" {
227+
t.Fatalf("Missing header: %s", h)
228+
}
229+
}
230+
231+
// Check that the body did not get lost somewhere in the multi-layer transport
232+
if lastCapturedRequestBodyStr != "abc" {
233+
t.Fatalf("Expected body to be \"abc\" but instead got %s", lastCapturedRequestBodyStr)
234+
}
188235
}

request.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package reggie
22

33
import (
4-
"bytes"
54
"fmt"
6-
"io/ioutil"
75
"regexp"
86

97
"gopkg.in/resty.v1"
@@ -53,11 +51,19 @@ func WithSessionID(id string) requestOption {
5351
}
5452
}
5553

54+
// SetBody wraps the resty SetBody and returns the request, allowing method chaining
55+
func (req *Request) SetBody(body []byte) *Request {
56+
req.Request.SetBody(body)
57+
return req
58+
}
59+
60+
// SetHeader wraps the resty SetHeader and returns the request, allowing method chaining
5661
func (req *Request) SetHeader(header, content string) *Request {
5762
req.Request.SetHeader(header, content)
5863
return req
5964
}
6065

66+
// SetQueryParam wraps the resty SetQueryParam and returns the request, allowing method chaining
6167
func (req *Request) SetQueryParam(param, content string) *Request {
6268
req.Request.SetQueryParam(param, content)
6369
return req
@@ -79,11 +85,6 @@ func (req *Request) Execute(method, url string) (*Response, error) {
7985
return resp, err
8086
}
8187

82-
func (req *Request) SetBody(body []byte) *Request {
83-
req.Request.SetBody(ioutil.NopCloser(bytes.NewReader(body)))
84-
return req
85-
}
86-
8788
func validateRequest(req *Request) error {
8889
re := regexp.MustCompile("<name>|<reference>|<digest>|<session_id>|//{2,}")
8990
matches := re.FindAllString(req.URL, -1)

0 commit comments

Comments
 (0)