-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapi.go
218 lines (191 loc) · 4.92 KB
/
api.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
package api
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"path/filepath"
"time"
)
var (
// ErrNotFound is returned on a 404
ErrNotFound error = fmt.Errorf("Resource not found")
)
func basicAuth(username string) string {
auth := username + ":"
return base64.StdEncoding.EncodeToString([]byte(auth))
}
// PublishRequest is an instance to send data to a server and get a PDF. One
// Endpoint can have multiple PublishingRequests.
type PublishRequest struct {
endpoint *Endpoint
Version string
Files []PublishFile `json:"files"`
}
// AttachFile adds a file to the PublishRequest for the server. Usually you have
// to provide the layout and the data file. All assets (fonts, images) can be
// referenced by http(s) hyperlinks.
func (p *PublishRequest) AttachFile(pathToFile string) error {
filename := filepath.Base(pathToFile)
data, err := ioutil.ReadFile(pathToFile)
if err != nil {
return err
}
p.Files = append(p.Files, PublishFile{Filename: filename, Contents: data})
return nil
}
// PublishFile is a file for the publishing request.
type PublishFile struct {
Filename string `json:"filename"`
Contents []byte `json:"contents"`
}
// PublishResponse holds the id to the publishing process.
type PublishResponse struct {
endpoint *Endpoint
ID string
}
// Errormessage contains a message from the publisher together with its error
// code. The error message is a message from the publishing run (like image not
// found).
type Errormessage struct {
Code int `json:"code"`
Error string `json:"error"`
}
// ProcessStatus contains information about the current status of the PDF
// generation. If the Finished field is nil, Errors and Errormessages are not
// set.
type ProcessStatus struct {
Finished *time.Time
Errors int
Errormessages []Errormessage
}
// Status returns the status of the publishing run. If the process is still
// running, the Finished field is set to nil.
func (p *PublishResponse) Status() (*ProcessStatus, error) {
loc := p.endpoint.location + "/status/" + p.ID
req, err := http.NewRequest("GET", loc, nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(p.endpoint.password, "")
resp, err := p.endpoint.client.Do(req)
if err != nil {
return nil, err
}
buf, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
ps := &ProcessStatus{}
err = json.Unmarshal(buf, ps)
if err != nil {
return nil, err
}
return ps, nil
}
// Wait for the publishing process to finish. Return an error if something is
// wrong with the request. If there is an error during the publishing run but
// the request itself is without errors, the error is nil, but the returned
// publishing status has the numbers of errors set.
func (p *PublishResponse) Wait() (*ProcessStatus, error) {
loc := p.endpoint.location + "/wait/" + p.ID
req, err := http.NewRequest("GET", loc, nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(p.endpoint.password, "")
resp, err := p.endpoint.client.Do(req)
if err != nil {
return nil, err
}
buf, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
switch resp.StatusCode {
case 422:
var ae Error
err = json.Unmarshal(buf, &ae)
if err != nil {
return nil, err
}
return nil, ae
case 404:
return nil, ErrNotFound
}
ps := &ProcessStatus{}
err = json.Unmarshal(buf, ps)
if err != nil {
return nil, err
}
return ps, nil
}
// GetPDF gets the PDF from the server. In case of an error, the bytes written to w
// might not contain a valid PDF.
func (p *PublishResponse) GetPDF(w io.Writer) error {
loc := p.endpoint.location + "/pdf/" + p.ID
req, err := http.NewRequest("GET", loc, nil)
if err != nil {
return err
}
req.SetBasicAuth(p.endpoint.password, "")
resp, err := p.endpoint.client.Do(req)
if err != nil {
return err
}
if resp.StatusCode != 200 {
return fmt.Errorf(resp.Status)
}
_, err = io.Copy(w, resp.Body)
return err
}
// Publish sends data to the server.
func (e *Endpoint) Publish(data *PublishRequest) (PublishResponse, error) {
var p PublishResponse
loc := e.location + "/publish?version=" + data.Version
b, err := json.Marshal(data)
if err != nil {
return p, err
}
br := bytes.NewReader(b)
req, err := http.NewRequest("POST", loc, br)
if err != nil {
return p, err
}
req.SetBasicAuth(e.password, "")
req.Header.Add("Content-Type", "application/json")
resp, err := e.client.Do(req)
if err != nil {
return p, err
}
buf, err := ioutil.ReadAll(resp.Body)
if err != nil {
return p, err
}
if resp.StatusCode != 201 {
var ae Error
err = json.Unmarshal(buf, &ae)
if err != nil {
return p, err
}
return p, ae
}
err = json.Unmarshal(buf, &p)
if err != nil {
return p, err
}
p.endpoint = e
return p, nil
}
// NewPublishRequest is the base structure to start a publishing request to the
// endpoint.
func (e *Endpoint) NewPublishRequest() *PublishRequest {
p := &PublishRequest{
endpoint: e,
Version: "latest",
}
return p
}