-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrecording-catcher.go
123 lines (110 loc) · 3.24 KB
/
recording-catcher.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
package main
import (
"bytes"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
log "github.com/Sirupsen/logrus"
"github.com/gorilla/pat"
"io/ioutil"
"net/http"
"os"
"time"
)
var (
tropoAWSKey string
tropoAWSSecret string
tropoAWSBucket string
tropoPort string
s3Domain string
s3URL string
)
func init() {
// gets all of the environment variables to be set
tropoAWSKey = setConfig("TROPO_AWS_KEY")
tropoAWSSecret = setConfig("TROPO_AWS_SECRET")
tropoAWSBucket = setConfig("TROPO_AWS_BUCKET")
tropoPort = setConfig("TROPO_PORT")
s3Domain = tropoAWSBucket + ".s3.amazonaws.com"
s3URL = "https://" + s3Domain
}
// sets the config params and exits if one does not exist
func setConfig(name string) string {
value := os.Getenv(name)
if value == "" {
log.Fatal("Environment varialbe " + name + " must be set.")
}
return value
}
func main() {
mux := pat.New()
mux.Post("/recordings/{filename}", http.HandlerFunc(recordingHandler))
mux.Put("/recordings/{filename}", http.HandlerFunc(recordingHandler))
http.Handle("/", mux)
log.Println("Listening on " + tropoPort + "...")
http.ListenAndServe(":"+tropoPort, nil)
}
// handled the requests to post recordings to S3
func recordingHandler(w http.ResponseWriter, r *http.Request) {
body, _ := ioutil.ReadAll(r.Body)
r.Body.Close()
params := r.URL.Query()
filename := params.Get(":filename")
go postToS3(filename, body)
return
}
// posts a the body sent to Amazon S3
func postToS3(filename string, body []byte) {
url := s3URL + "/" + filename
log.WithFields(log.Fields{
"url": url,
}).Info("Posting recording")
client := &http.Client{}
req, _ := http.NewRequest("PUT", url, bytes.NewBuffer(body))
setHeaders(req, filename)
resp, err := client.Do(req)
processResponse(resp, filename, err)
}
// setHeaders sets the required headers for S3
func setHeaders(req *http.Request, filename string) {
date := time.Now().UTC().Format("Mon, _2 Jan 2006 15:04:05 +0000")
signature := generateSignature(filename, date)
req.Header.Add("Host", s3Domain)
req.Header.Add("Date", date)
req.Header.Add("Content-Type", "application/x-compressed-tar")
req.Header.Add("Authorization", "AWS "+tropoAWSKey+":"+signature)
}
// generates the required signature for AWS
func generateSignature(filename string, date string) string {
stringToSign := "PUT\n\napplication/x-compressed-tar\n" + date + "\n" + "/" + tropoAWSBucket + "/" + filename
signature := computeHmac1(stringToSign, tropoAWSSecret)
return signature
}
// computes the sha1 hmac and then base64 encodes
func computeHmac1(message string, secret string) string {
key := []byte(secret)
h := hmac.New(sha1.New, key)
h.Write([]byte(message))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// processes the reponses from AWS
func processResponse(resp *http.Response, filename string, err error) {
if err != nil {
logError(filename, err.Error())
} else {
if resp.StatusCode == 200 {
log.WithFields(log.Fields{
"filename": filename,
}).Info("Successfully uploaded the recording")
} else {
logError(filename, resp.Status)
}
}
}
// logging function for response errors
func logError(filename string, err string) {
log.WithFields(log.Fields{
"filename": filename,
"error": err,
}).Info("Failed to upload a recording")
}