-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtinify.go
157 lines (124 loc) · 3.91 KB
/
tinify.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
package main
import (
"bufio"
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"io"
"net/http"
"os"
"strconv"
)
const TINIFY_API_URL = "https://api.tinify.com"
type TinifyClient struct {
ApiKey string
}
type TinifyResponse struct {
Headers TinifyHeadersResponse
Input TinifyImageResponse `json:"input,omitempty"`
Output TinifyImageResponse `json:"output,omitempty"`
}
type TinifyImageResponse struct {
Size int `json:"size,omitempty"`
Type string `json:"type,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Ratio float32 `json:"ratio,omitempty"`
Url string `json:"url,omitempty"`
}
type TinifyHeadersResponse struct {
CompressionCount int
Location string
ContentType string
}
type TinifyPreserveBody struct {
Preserve []string `json:"preserve,omitempty"`
}
func (t *TinifyClient) SetAPIKey(apiKey string) error {
if apiKey == "" {
return errors.New("cannot set an empty API key")
}
t.ApiKey = apiKey
return nil
}
func (t *TinifyClient) setAuthHeader(req *http.Request) error {
if t.ApiKey == "" {
return errors.New("cannot set Auth header without an API key")
}
authString := "api:" + t.ApiKey
b64Auth := base64.StdEncoding.EncodeToString([]byte(authString))
req.Header.Set("Authorization", "Basic "+b64Auth)
return nil
}
func (t *TinifyClient) MakeRequest(path string, inputFilename string) (TinifyResponse, error) {
if t.ApiKey == "" {
return TinifyResponse{}, errors.New("cannot make request without an API key")
}
inputFile, err := os.Open(inputFilename)
if err != nil {
return TinifyResponse{}, errors.New("couldnt open the input file")
}
defer inputFile.Close()
reqBody := bufio.NewReader(inputFile)
req, err := http.NewRequest(http.MethodPost, TINIFY_API_URL+path, reqBody)
if err != nil {
return TinifyResponse{}, errors.New("couldnt create a new request: " + err.Error())
}
t.setAuthHeader(req)
res, err := http.DefaultClient.Do(req)
if err != nil {
return TinifyResponse{}, errors.New("error making a POST request to tinify API: " + err.Error())
}
defer res.Body.Close()
bodyBytes, err := io.ReadAll(res.Body)
if res.StatusCode < 200 || res.StatusCode > 299 {
return TinifyResponse{}, errors.New("tinify API response failed with code " + res.Status + ": " + string(bodyBytes))
}
if err != nil {
return TinifyResponse{}, errors.New("Error reading response body: " + err.Error())
}
var jsonRes TinifyResponse
json.Unmarshal(bodyBytes, &jsonRes)
headerCompressionCount, _ := strconv.Atoi(res.Header.Get("Compression-Count"))
jsonRes.Headers.CompressionCount = headerCompressionCount
jsonRes.Headers.Location = res.Header.Get("Location")
jsonRes.Headers.ContentType = res.Header.Get("Content-Type")
return jsonRes, nil
}
func (t *TinifyClient) DownloadWithMetadata(locationPath string, outputFilepath string) error {
if locationPath == "" {
return errors.New("path to location of resulting image cannot be empty")
}
if outputFilepath == "" {
return errors.New("output file path cannot be empty")
}
reqStruct := &TinifyPreserveBody{
Preserve: []string{"copyright", "creation", "location"},
}
jsonData, err := json.Marshal(reqStruct)
if err != nil {
return errors.New("couldnt marshal JSON post data")
}
req, err := http.NewRequest(http.MethodPost, locationPath, bytes.NewBuffer(jsonData))
if err != nil {
return errors.New("couldnt create a new request: " + err.Error())
}
t.setAuthHeader(req)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
return errors.New("error making a POST request to tinify API: " + err.Error())
}
defer res.Body.Close()
file, err := os.Create(outputFilepath)
if err != nil {
return errors.New("error creating output file: " + err.Error())
}
defer file.Close()
_, err = io.Copy(file, res.Body)
if err != nil {
return errors.New("error writing to output file: " + err.Error())
}
return nil
}