1 package storage
2
3
4
5
6 import (
7 "encoding/xml"
8 "fmt"
9 "net/http"
10 "net/url"
11 "strconv"
12 "strings"
13 )
14
15
16
17 type BlobStorageClient struct {
18 client Client
19 auth authentication
20 }
21
22
23
24 func (b *BlobStorageClient) GetServiceProperties() (*ServiceProperties, error) {
25 return b.client.getServiceProperties(blobServiceName, b.auth)
26 }
27
28
29
30 func (b *BlobStorageClient) SetServiceProperties(props ServiceProperties) error {
31 return b.client.setServiceProperties(props, blobServiceName, b.auth)
32 }
33
34
35
36
37
38 type ListContainersParameters struct {
39 Prefix string
40 Marker string
41 Include string
42 MaxResults uint
43 Timeout uint
44 }
45
46
47 func (b *BlobStorageClient) GetContainerReference(name string) *Container {
48 return &Container{
49 bsc: b,
50 Name: name,
51 }
52 }
53
54
55
56 func GetContainerReferenceFromSASURI(sasuri url.URL) (*Container, error) {
57 path := strings.Split(sasuri.Path, "/")
58 if len(path) <= 1 {
59 return nil, fmt.Errorf("could not find a container in URI: %s", sasuri.String())
60 }
61 c, err := newSASClientFromURL(&sasuri)
62 if err != nil {
63 return nil, err
64 }
65 cli := c.GetBlobService()
66 return &Container{
67 bsc: &cli,
68 Name: path[1],
69 sasuri: sasuri,
70 }, nil
71 }
72
73
74
75
76
77 func (b BlobStorageClient) ListContainers(params ListContainersParameters) (*ContainerListResponse, error) {
78 q := mergeParams(params.getParameters(), url.Values{"comp": {"list"}})
79 uri := b.client.getEndpoint(blobServiceName, "", q)
80 headers := b.client.getStandardHeaders()
81
82 type ContainerAlias struct {
83 bsc *BlobStorageClient
84 Name string `xml:"Name"`
85 Properties ContainerProperties `xml:"Properties"`
86 Metadata BlobMetadata
87 sasuri url.URL
88 }
89 type ContainerListResponseAlias struct {
90 XMLName xml.Name `xml:"EnumerationResults"`
91 Xmlns string `xml:"xmlns,attr"`
92 Prefix string `xml:"Prefix"`
93 Marker string `xml:"Marker"`
94 NextMarker string `xml:"NextMarker"`
95 MaxResults int64 `xml:"MaxResults"`
96 Containers []ContainerAlias `xml:"Containers>Container"`
97 }
98
99 var outAlias ContainerListResponseAlias
100 resp, err := b.client.exec(http.MethodGet, uri, headers, nil, b.auth)
101 if err != nil {
102 return nil, err
103 }
104 defer resp.Body.Close()
105 err = xmlUnmarshal(resp.Body, &outAlias)
106 if err != nil {
107 return nil, err
108 }
109
110 out := ContainerListResponse{
111 XMLName: outAlias.XMLName,
112 Xmlns: outAlias.Xmlns,
113 Prefix: outAlias.Prefix,
114 Marker: outAlias.Marker,
115 NextMarker: outAlias.NextMarker,
116 MaxResults: outAlias.MaxResults,
117 Containers: make([]Container, len(outAlias.Containers)),
118 }
119 for i, cnt := range outAlias.Containers {
120 out.Containers[i] = Container{
121 bsc: &b,
122 Name: cnt.Name,
123 Properties: cnt.Properties,
124 Metadata: map[string]string(cnt.Metadata),
125 sasuri: cnt.sasuri,
126 }
127 }
128
129 return &out, err
130 }
131
132 func (p ListContainersParameters) getParameters() url.Values {
133 out := url.Values{}
134
135 if p.Prefix != "" {
136 out.Set("prefix", p.Prefix)
137 }
138 if p.Marker != "" {
139 out.Set("marker", p.Marker)
140 }
141 if p.Include != "" {
142 out.Set("include", p.Include)
143 }
144 if p.MaxResults != 0 {
145 out.Set("maxresults", strconv.FormatUint(uint64(p.MaxResults), 10))
146 }
147 if p.Timeout != 0 {
148 out.Set("timeout", strconv.FormatUint(uint64(p.Timeout), 10))
149 }
150
151 return out
152 }
153
154 func writeMetadata(h http.Header) map[string]string {
155 metadata := make(map[string]string)
156 for k, v := range h {
157
158
159
160
161
162
163
164
165
166 k = strings.ToLower(k)
167 if len(v) == 0 || !strings.HasPrefix(k, strings.ToLower(userDefinedMetadataHeaderPrefix)) {
168 continue
169 }
170
171 k = k[len(userDefinedMetadataHeaderPrefix):]
172 metadata[k] = v[len(v)-1]
173 }
174 return metadata
175 }
176
View as plain text