-
Notifications
You must be signed in to change notification settings - Fork 5.3k
/
gateway-b2-anonymous.go
145 lines (134 loc) · 4.4 KB
/
gateway-b2-anonymous.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
* Minio Cloud Storage, (C) 2017 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cmd
import (
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
// AnonPutObject creates a new object anonymously with the incoming data,
func (l *b2Objects) AnonPutObject(bucket string, object string, size int64, data io.Reader,
metadata map[string]string, sha256sum string) (objInfo ObjectInfo, err error) {
return objInfo, traceError(NotImplemented{})
}
// mkRange converts offset, size into Range header equivalent.
func mkRange(offset, size int64) string {
if offset == 0 && size == 0 {
return ""
}
if size == 0 {
return fmt.Sprintf("%s%d-", byteRangePrefix, offset)
}
return fmt.Sprintf("%s%d-%d", byteRangePrefix, offset, offset+size-1)
}
// AnonGetObject - Get object anonymously
func (l *b2Objects) AnonGetObject(bucket string, object string, startOffset int64, length int64, writer io.Writer) error {
uri := fmt.Sprintf("%s/file/%s/%s", l.b2Client.DownloadURI, bucket, object)
req, err := http.NewRequest("GET", uri, nil)
if err != nil {
return err
}
rng := mkRange(startOffset, length)
if rng != "" {
req.Header.Set("Range", rng)
}
resp, err := l.anonClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
_, err = io.Copy(writer, resp.Body)
return err
}
// Converts http Header into ObjectInfo. This function looks for all the
// standard Backblaze B2 headers to convert into ObjectInfo.
//
// Content-Length is converted to Size.
// X-Bz-Upload-Timestamp is converted to ModTime.
// X-Bz-Info-<header>:<value> is converted to <header>:<value>
// Content-Type is converted to ContentType.
// X-Bz-Content-Sha1 is converted to ETag.
func headerToObjectInfo(bucket, object string, header http.Header) (objInfo ObjectInfo, err error) {
clen, err := strconv.ParseInt(header.Get("Content-Length"), 10, 64)
if err != nil {
return objInfo, err
}
timeStamp, err := strconv.ParseInt(header.Get("X-Bz-Upload-Timestamp"), 10, 64)
if err != nil {
return objInfo, err
}
info := make(map[string]string)
for key := range header {
if !strings.HasPrefix(key, "X-Bz-Info-") {
continue
}
name, err := url.QueryUnescape(strings.TrimPrefix(key, "X-Bz-Info-"))
if err != nil {
return objInfo, err
}
val, err := url.QueryUnescape(header.Get(key))
if err != nil {
return objInfo, err
}
info[name] = val
}
objInfo = ObjectInfo{
Bucket: bucket,
Name: object,
ContentType: header.Get("Content-Type"),
ModTime: time.Unix(timeStamp/1000, timeStamp%1000*1e6),
Size: clen,
ETag: header.Get("X-Bz-Content-Sha1"),
UserDefined: info,
}
return objInfo, nil
}
// AnonGetObjectInfo - Get object info anonymously
func (l *b2Objects) AnonGetObjectInfo(bucket string, object string) (objInfo ObjectInfo, err error) {
uri := fmt.Sprintf("%s/file/%s/%s", l.b2Client.DownloadURI, bucket, object)
req, err := http.NewRequest("HEAD", uri, nil)
if err != nil {
return objInfo, err
}
resp, err := l.anonClient.Do(req)
if err != nil {
return objInfo, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 && resp.StatusCode != 206 {
return objInfo, errors.New(resp.Status)
}
return headerToObjectInfo(bucket, object, resp.Header)
}
// AnonListObjects - List objects anonymously
func (l *b2Objects) AnonListObjects(bucket string, prefix string, marker string, delimiter string,
maxKeys int) (loi ListObjectsInfo, err error) {
return loi, traceError(NotImplemented{})
}
// AnonListObjectsV2 - List objects in V2 mode, anonymously
func (l *b2Objects) AnonListObjectsV2(bucket, prefix, continuationToken, delimiter string, maxKeys int,
fetchOwner bool, startAfter string) (loi ListObjectsV2Info, err error) {
return loi, traceError(NotImplemented{})
}
// AnonGetBucketInfo - Get bucket metadata anonymously.
func (l *b2Objects) AnonGetBucketInfo(bucket string) (bi BucketInfo, err error) {
return bi, traceError(NotImplemented{})
}