-
Notifications
You must be signed in to change notification settings - Fork 14
/
utils.go
114 lines (100 loc) · 2.44 KB
/
utils.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
package couchdb
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"mime"
"mime/multipart"
"net/http"
"net/textproto"
"os"
"path/filepath"
"github.com/zemirco/uid"
)
// Get mime type from file name.
func mimeType(name string) string {
ext := filepath.Ext(name)
return mime.TypeByExtension(ext)
}
// Convert HTTP response from CouchDB into Error.
func newError(res *http.Response) error {
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
defer res.Body.Close()
error := &Error{}
err = json.Unmarshal(body, &error)
if err != nil {
return err
}
error.Method = res.Request.Method
error.URL = res.Request.URL.String()
error.StatusCode = res.StatusCode
return error
}
// Write JSON to multipart/related.
func writeJSON(document *Document, writer *multipart.Writer, file *os.File) error {
partHeaders := textproto.MIMEHeader{}
partHeaders.Set("Content-Type", "application/json")
part, err := writer.CreatePart(partHeaders)
if err != nil {
return err
}
stat, err := file.Stat()
if err != nil {
return err
}
path := file.Name()
// make empty map
document.Attachments = make(map[string]Attachment)
attachment := Attachment{
Follows: true,
ContentType: mimeType(path),
Length: stat.Size(),
}
// add attachment to map
filename := filepath.Base(path)
document.Attachments[filename] = attachment
bytes, err := json.Marshal(document)
if err != nil {
return err
}
_, err = part.Write(bytes)
if err != nil {
return err
}
return nil
}
// Write actual file content to multipart/related.
func writeMultipart(writer *multipart.Writer, file io.Reader) error {
part, err := writer.CreatePart(textproto.MIMEHeader{})
if err != nil {
return err
}
// copy file content into multipart message
_, err = io.Copy(part, file)
if err != nil {
return err
}
return nil
}
// RandDBName returns random CouchDB database name.
// See the docs for database name rules.
// http://docs.couchdb.org/en/2.0.0/api/database/common.html#put--db
func RandDBName(length int) (string, error) {
// fastest string concatenation
var buffer bytes.Buffer
// generate first character, must be a letter
first := uid.NewBytes(1, "abcdefghijklmnopqrstuvwxyz")
if _, err := buffer.WriteString(first); err != nil {
return "", err
}
// generate last characters
last := uid.NewBytes(length-1, "abcdefghijklmnopqrstuvwxyz0123456789")
if _, err := buffer.WriteString(last); err != nil {
return "", err
}
return buffer.String(), nil
}