@@ -70,78 +70,6 @@ Below is a table of all of the possible URI parameter substitutions and associat
7070| ` <reference> ` | Tag or digest | ` WithReference ` (` Request ` ) |
7171| ` <session_id> ` | Session ID for upload | ` WithSessionID ` (` Request ` ) |
7272
73- ## Example
74-
75- The following is an example of a resumable blob upload and subsequent manifest upload:
76-
77- ``` go
78- package main
79-
80- import (
81- " github.com/bloodorangeio/reggie"
82- godigest " github.com/opencontainers/go-digest"
83-
84- )
85-
86- func main () {
87- client := reggie.NewClient (" http://localhost:5000" ,
88- WithDefaultName (" my/repo" ),
89- WithDebug (true ))
90-
91- // get the session URL
92- req := client.NewRequest (reggie.POST , " /v2/<name>/blobs/uploads" )
93- resp , err := client.Do (req)
94- if err != nil {
95- // handle error
96- }
97-
98- blob := []byte (" {}\n " )
99- blobChunk1 := blob[:1 ]
100- blobChunk1Range := fmt.Sprintf (" 0-%d " , len (blobChunk1)-1 )
101- blobChunk2 := blob[1 :]
102- blobChunk2Range := fmt.Sprintf (" 0-%d " , len (blobChunk2)-1 )
103- blobDigest := godigest.FromBytes (blob).String ()
104-
105- // upload the first chunk
106- req = client.NewRequest (reggie.PATCH , resp.GetRelativeLocation ())
107- req.SetHeader (" Content-Type" , " application/octet-stream" )
108- req.SetHeader (" Content-Length" , fmt.Sprintf (" %d " , len (blobChunk1)))
109- req.SetHeader (" Content-Range" , blobChunk1Range)
110- req.SetBody (blobChunk1)
111- resp, err = client.Do (req)
112- if err != nil {
113- // handle error
114- }
115-
116- // upload the final chunk and close the session
117- req = client.NewRequest (reggie.PUT , resp.GetRelativeLocation ())
118- req.SetHeader (" Content-Length" , fmt.Sprintf (" %d " , len (blobChunk2)))
119- req.SetHeader (" Content-Range" , blobChunk2Range)
120- req.SetHeader (" Content-Type" , " application/octet-stream" )
121- req.SetQueryParam (" digest" , blobDigest)
122- req.SetBody (blobChunk2)
123- resp, err = client.Do (req)
124- if err != nil {
125- // handle error
126- }
127-
128- // upload the manifest
129- manifest = []byte (fmt.Sprintf (
130- " { \" mediaType\" : \" application/vnd.oci.image.manifest.v1+json\" , \" config\" : { \" digest\" : \" %s \" , " +
131- " \" mediaType\" : \" application/vnd.oci.image.config.v1+json\" ," +" \" size\" : %d }, \" layers\" : [], " +
132- " \" schemaVersion\" : 2 }" ,
133- blobDigest, len (blob)))
134- req = client.NewRequest (reggie.PUT , " /v2/<name>/manifests/<reference>" , reggie.WithReference (" test" ))
135- req.SetHeader (" Content-Type" , " application/vnd.oci.image.manifest.v1+json" )
136- req.SetBody (manifest)
137- resp, err = client.Do (req)
138- if err != nil {
139- // handle error
140- }
141- }
142-
143- ```
144-
14573## Other Features
14674
14775### Error Parsing
@@ -184,3 +112,108 @@ Requests made by Reggie will use a custom value by default for the `User-Agent`
184112```
185113User-Agent: reggie/0.1.1 (https://github.com/bloodorangeio/reggie)
186114```
115+
116+ ## Example
117+
118+ The following is an example of a resumable blob upload and subsequent manifest upload:
119+
120+ ``` go
121+ package main
122+
123+ import (
124+ " fmt"
125+
126+ " github.com/bloodorangeio/reggie"
127+ godigest " github.com/opencontainers/go-digest"
128+ )
129+
130+ func main () {
131+ // construct client pointing to your registry
132+ client , err := reggie.NewClient (" http://localhost:5000" ,
133+ reggie.WithDefaultName (" my/repo" ),
134+ reggie.WithDebug (true ))
135+ if err != nil {
136+ panic (err)
137+ }
138+
139+ // get the session URL
140+ req := client.NewRequest (reggie.POST , " /v2/<name>/blobs/uploads/" )
141+ resp , err := client.Do (req)
142+ if err != nil {
143+ panic (err)
144+ }
145+
146+ // a blob for an empty manifest config, separated into 2 chunks ("{" and "}")
147+ blob := []byte (" {}" )
148+ blobChunk1 := blob[:1 ]
149+ blobChunk1Range := fmt.Sprintf (" 0-%d " , len (blobChunk1)-1 )
150+ blobChunk2 := blob[1 :]
151+ blobChunk2Range := fmt.Sprintf (" %d -%d " , len (blobChunk1), len (blob)-1 )
152+ blobDigest := godigest.FromBytes (blob).String ()
153+
154+ // upload the first chunk
155+ req = client.NewRequest (reggie.PATCH , resp.GetRelativeLocation ())
156+ req.SetHeader (" Content-Type" , " application/octet-stream" ).
157+ SetHeader (" Content-Length" , fmt.Sprintf (" %d " , len (blobChunk1))).
158+ SetHeader (" Content-Range" , blobChunk1Range).
159+ SetBody (blobChunk1)
160+ resp, err = client.Do (req)
161+ if err != nil {
162+ panic (err)
163+ }
164+
165+ // 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))).
168+ SetHeader (" Content-Range" , blobChunk2Range).
169+ SetHeader (" Content-Type" , " application/octet-stream" ).
170+ SetQueryParam (" digest" , blobDigest).
171+ SetBody (blobChunk2)
172+ resp, err = client.Do (req)
173+ if err != nil {
174+ panic (err)
175+ }
176+
177+ // validate the uploaded blob content
178+ req = client.NewRequest (reggie.GET , " /v2/<name>/blobs/<digest>" ,
179+ reggie.WithDigest (blobDigest))
180+ resp, err = client.Do (req)
181+ if err != nil {
182+ panic (err)
183+ }
184+ fmt.Printf (" Blob content:\n %s \n " , resp.String ())
185+
186+ // upload the manifest (referencing the uploaded blob)
187+ ref := " test"
188+ 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)))
199+ 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" ).
202+ SetBody (manifest)
203+ resp, err = client.Do (req)
204+ if err != nil {
205+ panic (err)
206+ }
207+
208+ // validate the uploaded manifest content
209+ req = client.NewRequest (reggie.GET , " /v2/<name>/manifests/<reference>" ,
210+ reggie.WithReference (ref))
211+ req.SetHeader (" Accept" , " application/vnd.oci.image.manifest.v1+json" )
212+ resp, err = client.Do (req)
213+ if err != nil {
214+ panic (err)
215+ }
216+ fmt.Printf (" Manifest content:\n %s \n " , resp.String ())
217+ }
218+
219+ ```
0 commit comments