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
package main
import (
"bytes"
"errors"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
)
func rewriteFormFilesFromMultipart(r *gitRequest, writer *multipart.Writer) (cleanup func(), err error) {
// Create multipart reader
reader, err := r.MultipartReader()
if err != nil {
return nil, err
}
var files []string
cleanup = func() {
for _, file := range files {
os.Remove(file)
}
}
// Execute cleanup in case of failure
defer func() {
if err != nil {
cleanup()
}
}()
for {
p, err := reader.NextPart()
if err == io.EOF {
break
}
name := p.FormName()
if name == "" {
continue
}
// Copy form field
if filename := p.FileName(); filename != "" {
// Create temporary directory where the uploaded file will be stored
if err := os.MkdirAll(r.TempPath, 0700); err != nil {
return cleanup, err
}
// Create temporary file in path returned by Authorization filter
file, err := ioutil.TempFile(r.TempPath, "upload_")
if err != nil {
return cleanup, err
}
defer file.Close()
// Add file entry
writer.WriteField(name+".path", file.Name())
writer.WriteField(name+".name", filename)
files = append(files, file.Name())
_, err = io.Copy(file, p)
file.Close()
if err != nil {
return cleanup, err
}
} else {
np, err := writer.CreatePart(p.Header)
if err != nil {
return cleanup, err
}
_, err = io.Copy(np, p)
if err != nil {
return cleanup, err
}
}
}
return cleanup, nil
}
func handleFileUploads(w http.ResponseWriter, r *gitRequest) {
if r.TempPath == "" {
fail500(w, "handleUploadFile", errors.New("missing temporary path"))
return
}
var body bytes.Buffer
writer := multipart.NewWriter(&body)
defer writer.Close()
// Rewrite multipart form data
cleanup, err := rewriteFormFilesFromMultipart(r, writer)
if err != nil {
if err == http.ErrNotMultipart {
proxyRequest(w, r)
} else {
fail500(w, "Couldn't handle upload request.", err)
}
return
}
if cleanup != nil {
defer cleanup()
}
// Close writer
writer.Close()
// Create request
upstreamRequest, err := r.u.newUpstreamRequest(r.Request, nil, "")
if err != nil {
fail500(w, "Couldn't handle artifacts upload request.", err)
return
}
// Set multipart form data
upstreamRequest.Body = ioutil.NopCloser(&body)
upstreamRequest.ContentLength = int64(body.Len())
upstreamRequest.Header.Set("Content-Type", writer.FormDataContentType())
// Forward request to backend
upstreamResponse, err := r.u.httpClient.Do(upstreamRequest)
if err != nil {
fail500(w, "do upstream request", err)
return
}
defer upstreamResponse.Body.Close()
forwardResponseToClient(w, upstreamResponse)
}