card-mod-machines 0.11.5 → 0.11.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/vendor/jquery_file_upload/CONTRIBUTING.md +15 -0
- data/vendor/jquery_file_upload/LICENSE.txt +21 -0
- data/vendor/jquery_file_upload/README.md +107 -0
- data/vendor/jquery_file_upload/angularjs.html +211 -0
- data/vendor/jquery_file_upload/basic-plus.html +226 -0
- data/vendor/jquery_file_upload/basic.html +136 -0
- data/vendor/jquery_file_upload/bower-version-update.js +16 -0
- data/vendor/jquery_file_upload/bower.json +64 -0
- data/vendor/jquery_file_upload/cors/postmessage.html +75 -0
- data/vendor/jquery_file_upload/cors/result.html +24 -0
- data/vendor/jquery_file_upload/css/jquery-ui-demo-ie8.css +21 -0
- data/vendor/jquery_file_upload/css/jquery-ui-demo.css +67 -0
- data/vendor/jquery_file_upload/css/jquery.fileupload-noscript.css +22 -0
- data/vendor/jquery_file_upload/css/jquery.fileupload-ui-noscript.css +17 -0
- data/vendor/jquery_file_upload/css/jquery.fileupload-ui.css +57 -0
- data/vendor/jquery_file_upload/css/jquery.fileupload.css +37 -0
- data/vendor/jquery_file_upload/css/style.css +15 -0
- data/vendor/jquery_file_upload/img/loading.gif +0 -0
- data/vendor/jquery_file_upload/img/progressbar.gif +0 -0
- data/vendor/jquery_file_upload/index.html +255 -0
- data/vendor/jquery_file_upload/jquery-ui.html +252 -0
- data/vendor/jquery_file_upload/js/app.js +101 -0
- data/vendor/jquery_file_upload/js/cors/jquery.postmessage-transport.js +126 -0
- data/vendor/jquery_file_upload/js/cors/jquery.xdr-transport.js +89 -0
- data/vendor/jquery_file_upload/js/jquery.fileupload-angular.js +437 -0
- data/vendor/jquery_file_upload/js/jquery.fileupload-audio.js +113 -0
- data/vendor/jquery_file_upload/js/jquery.fileupload-image.js +326 -0
- data/vendor/jquery_file_upload/js/jquery.fileupload-jquery-ui.js +161 -0
- data/vendor/jquery_file_upload/js/jquery.fileupload-process.js +178 -0
- data/vendor/jquery_file_upload/js/jquery.fileupload-ui.js +714 -0
- data/vendor/jquery_file_upload/js/jquery.fileupload-validate.js +125 -0
- data/vendor/jquery_file_upload/js/jquery.fileupload-video.js +113 -0
- data/vendor/jquery_file_upload/js/jquery.fileupload.js +1486 -0
- data/vendor/jquery_file_upload/js/jquery.iframe-transport.js +224 -0
- data/vendor/jquery_file_upload/js/main.js +75 -0
- data/vendor/jquery_file_upload/js/vendor/jquery.ui.widget.js +748 -0
- data/vendor/jquery_file_upload/package.json +55 -0
- data/vendor/jquery_file_upload/server/gae-go/app.yaml +12 -0
- data/vendor/jquery_file_upload/server/gae-go/app/main.go +361 -0
- data/vendor/jquery_file_upload/server/gae-go/static/favicon.ico +0 -0
- data/vendor/jquery_file_upload/server/gae-go/static/robots.txt +2 -0
- data/vendor/jquery_file_upload/server/gae-python/app.yaml +17 -0
- data/vendor/jquery_file_upload/server/gae-python/main.py +204 -0
- data/vendor/jquery_file_upload/server/gae-python/static/favicon.ico +0 -0
- data/vendor/jquery_file_upload/server/gae-python/static/robots.txt +2 -0
- data/vendor/jquery_file_upload/server/php/Dockerfile +38 -0
- data/vendor/jquery_file_upload/server/php/UploadHandler.php +1411 -0
- data/vendor/jquery_file_upload/server/php/docker-compose.yml +9 -0
- data/vendor/jquery_file_upload/server/php/index.php +15 -0
- data/vendor/jquery_file_upload/test/index.html +172 -0
- data/vendor/jquery_file_upload/test/test.js +1292 -0
- data/vendor/jquery_rails/CHANGELOG.md +359 -0
- data/vendor/jquery_rails/CONTRIBUTING.md +132 -0
- data/vendor/jquery_rails/Gemfile +22 -0
- data/vendor/jquery_rails/MIT-LICENSE +21 -0
- data/vendor/jquery_rails/README.md +75 -0
- data/vendor/jquery_rails/Rakefile +59 -0
- data/vendor/jquery_rails/VERSIONS.md +62 -0
- data/vendor/jquery_rails/jquery-rails.gemspec +26 -0
- data/vendor/jquery_rails/lib/jquery-rails.rb +1 -0
- data/vendor/jquery_rails/lib/jquery/assert_select.rb +149 -0
- data/vendor/jquery_rails/lib/jquery/rails.rb +8 -0
- data/vendor/jquery_rails/lib/jquery/rails/engine.rb +6 -0
- data/vendor/jquery_rails/lib/jquery/rails/version.rb +9 -0
- data/vendor/jquery_rails/test/assert_select_jquery_test.rb +85 -0
- data/vendor/jquery_rails/test/test_helper.rb +6 -0
- data/vendor/jquery_rails/vendor/assets/javascripts/jquery.js +11008 -0
- data/vendor/jquery_rails/vendor/assets/javascripts/jquery.min.js +5 -0
- data/vendor/jquery_rails/vendor/assets/javascripts/jquery.min.map +1 -0
- data/vendor/jquery_rails/vendor/assets/javascripts/jquery2.js +9814 -0
- data/vendor/jquery_rails/vendor/assets/javascripts/jquery2.min.js +4 -0
- data/vendor/jquery_rails/vendor/assets/javascripts/jquery2.min.map +1 -0
- data/vendor/jquery_rails/vendor/assets/javascripts/jquery3.js +10364 -0
- data/vendor/jquery_rails/vendor/assets/javascripts/jquery3.min.js +2 -0
- data/vendor/jquery_rails/vendor/assets/javascripts/jquery3.min.map +1 -0
- data/vendor/jquery_rails/vendor/assets/javascripts/jquery_ujs.js +555 -0
- metadata +108 -12
@@ -0,0 +1,55 @@
|
|
1
|
+
{
|
2
|
+
"name": "blueimp-file-upload",
|
3
|
+
"version": "9.21.0",
|
4
|
+
"title": "jQuery File Upload",
|
5
|
+
"description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
|
6
|
+
"keywords": [
|
7
|
+
"jquery",
|
8
|
+
"file",
|
9
|
+
"upload",
|
10
|
+
"widget",
|
11
|
+
"multiple",
|
12
|
+
"selection",
|
13
|
+
"drag",
|
14
|
+
"drop",
|
15
|
+
"progress",
|
16
|
+
"preview",
|
17
|
+
"cross-domain",
|
18
|
+
"cross-site",
|
19
|
+
"chunk",
|
20
|
+
"resume",
|
21
|
+
"gae",
|
22
|
+
"go",
|
23
|
+
"python",
|
24
|
+
"php",
|
25
|
+
"bootstrap"
|
26
|
+
],
|
27
|
+
"homepage": "https://github.com/blueimp/jQuery-File-Upload",
|
28
|
+
"author": {
|
29
|
+
"name": "Sebastian Tschan",
|
30
|
+
"url": "https://blueimp.net"
|
31
|
+
},
|
32
|
+
"repository": {
|
33
|
+
"type": "git",
|
34
|
+
"url": "git://github.com/blueimp/jQuery-File-Upload.git"
|
35
|
+
},
|
36
|
+
"license": "MIT",
|
37
|
+
"optionalDependencies": {
|
38
|
+
"blueimp-canvas-to-blob": "3.5.0",
|
39
|
+
"blueimp-load-image": "2.12.2",
|
40
|
+
"blueimp-tmpl": "3.6.0"
|
41
|
+
},
|
42
|
+
"devDependencies": {
|
43
|
+
"bower-json": "0.8.1",
|
44
|
+
"jshint": "2.9.3"
|
45
|
+
},
|
46
|
+
"scripts": {
|
47
|
+
"bower-version-update": "./bower-version-update.js",
|
48
|
+
"lint": "jshint *.js js/*.js js/cors/*.js",
|
49
|
+
"test": "npm run lint",
|
50
|
+
"preversion": "npm test",
|
51
|
+
"version": "npm run bower-version-update && git add bower.json",
|
52
|
+
"postversion": "git push --tags origin master && npm publish"
|
53
|
+
},
|
54
|
+
"main": "js/jquery.fileupload.js"
|
55
|
+
}
|
@@ -0,0 +1,361 @@
|
|
1
|
+
/*
|
2
|
+
* jQuery File Upload Plugin GAE Go Example
|
3
|
+
* https://github.com/blueimp/jQuery-File-Upload
|
4
|
+
*
|
5
|
+
* Copyright 2011, Sebastian Tschan
|
6
|
+
* https://blueimp.net
|
7
|
+
*
|
8
|
+
* Licensed under the MIT license:
|
9
|
+
* https://opensource.org/licenses/MIT
|
10
|
+
*/
|
11
|
+
|
12
|
+
package app
|
13
|
+
|
14
|
+
import (
|
15
|
+
"bufio"
|
16
|
+
"bytes"
|
17
|
+
"encoding/json"
|
18
|
+
"fmt"
|
19
|
+
"github.com/disintegration/gift"
|
20
|
+
"golang.org/x/net/context"
|
21
|
+
"google.golang.org/appengine"
|
22
|
+
"google.golang.org/appengine/memcache"
|
23
|
+
"hash/crc32"
|
24
|
+
"image"
|
25
|
+
"image/gif"
|
26
|
+
"image/jpeg"
|
27
|
+
"image/png"
|
28
|
+
"io"
|
29
|
+
"log"
|
30
|
+
"mime/multipart"
|
31
|
+
"net/http"
|
32
|
+
"net/url"
|
33
|
+
"path/filepath"
|
34
|
+
"regexp"
|
35
|
+
"strings"
|
36
|
+
)
|
37
|
+
|
38
|
+
const (
|
39
|
+
WEBSITE = "https://blueimp.github.io/jQuery-File-Upload/"
|
40
|
+
MIN_FILE_SIZE = 1 // bytes
|
41
|
+
// Max file size is memcache limit (1MB) minus key size minus overhead:
|
42
|
+
MAX_FILE_SIZE = 999000 // bytes
|
43
|
+
IMAGE_TYPES = "image/(gif|p?jpeg|(x-)?png)"
|
44
|
+
ACCEPT_FILE_TYPES = IMAGE_TYPES
|
45
|
+
THUMB_MAX_WIDTH = 80
|
46
|
+
THUMB_MAX_HEIGHT = 80
|
47
|
+
EXPIRATION_TIME = 300 // seconds
|
48
|
+
// If empty, only allow redirects to the referer protocol+host.
|
49
|
+
// Set to a regexp string for custom pattern matching:
|
50
|
+
REDIRECT_ALLOW_TARGET = ""
|
51
|
+
)
|
52
|
+
|
53
|
+
var (
|
54
|
+
imageTypes = regexp.MustCompile(IMAGE_TYPES)
|
55
|
+
acceptFileTypes = regexp.MustCompile(ACCEPT_FILE_TYPES)
|
56
|
+
thumbSuffix = "." + fmt.Sprint(THUMB_MAX_WIDTH) + "x" +
|
57
|
+
fmt.Sprint(THUMB_MAX_HEIGHT)
|
58
|
+
)
|
59
|
+
|
60
|
+
func escape(s string) string {
|
61
|
+
return strings.Replace(url.QueryEscape(s), "+", "%20", -1)
|
62
|
+
}
|
63
|
+
|
64
|
+
func extractKey(r *http.Request) string {
|
65
|
+
// Use RequestURI instead of r.URL.Path, as we need the encoded form:
|
66
|
+
path := strings.Split(r.RequestURI, "?")[0]
|
67
|
+
// Also adjust double encoded slashes:
|
68
|
+
return strings.Replace(path[1:], "%252F", "%2F", -1)
|
69
|
+
}
|
70
|
+
|
71
|
+
func check(err error) {
|
72
|
+
if err != nil {
|
73
|
+
panic(err)
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
type FileInfo struct {
|
78
|
+
Key string `json:"-"`
|
79
|
+
ThumbnailKey string `json:"-"`
|
80
|
+
Url string `json:"url,omitempty"`
|
81
|
+
ThumbnailUrl string `json:"thumbnailUrl,omitempty"`
|
82
|
+
Name string `json:"name"`
|
83
|
+
Type string `json:"type"`
|
84
|
+
Size int64 `json:"size"`
|
85
|
+
Error string `json:"error,omitempty"`
|
86
|
+
DeleteUrl string `json:"deleteUrl,omitempty"`
|
87
|
+
DeleteType string `json:"deleteType,omitempty"`
|
88
|
+
}
|
89
|
+
|
90
|
+
func (fi *FileInfo) ValidateType() (valid bool) {
|
91
|
+
if acceptFileTypes.MatchString(fi.Type) {
|
92
|
+
return true
|
93
|
+
}
|
94
|
+
fi.Error = "Filetype not allowed"
|
95
|
+
return false
|
96
|
+
}
|
97
|
+
|
98
|
+
func (fi *FileInfo) ValidateSize() (valid bool) {
|
99
|
+
if fi.Size < MIN_FILE_SIZE {
|
100
|
+
fi.Error = "File is too small"
|
101
|
+
} else if fi.Size > MAX_FILE_SIZE {
|
102
|
+
fi.Error = "File is too big"
|
103
|
+
} else {
|
104
|
+
return true
|
105
|
+
}
|
106
|
+
return false
|
107
|
+
}
|
108
|
+
|
109
|
+
func (fi *FileInfo) CreateUrls(r *http.Request, c context.Context) {
|
110
|
+
u := &url.URL{
|
111
|
+
Scheme: r.URL.Scheme,
|
112
|
+
Host: appengine.DefaultVersionHostname(c),
|
113
|
+
Path: "/",
|
114
|
+
}
|
115
|
+
uString := u.String()
|
116
|
+
fi.Url = uString + fi.Key
|
117
|
+
fi.DeleteUrl = fi.Url
|
118
|
+
fi.DeleteType = "DELETE"
|
119
|
+
if fi.ThumbnailKey != "" {
|
120
|
+
fi.ThumbnailUrl = uString + fi.ThumbnailKey
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
func (fi *FileInfo) SetKey(checksum uint32) {
|
125
|
+
fi.Key = escape(string(fi.Type)) + "/" +
|
126
|
+
escape(fmt.Sprint(checksum)) + "/" +
|
127
|
+
escape(string(fi.Name))
|
128
|
+
}
|
129
|
+
|
130
|
+
func (fi *FileInfo) createThumb(buffer *bytes.Buffer, c context.Context) {
|
131
|
+
if imageTypes.MatchString(fi.Type) {
|
132
|
+
src, _, err := image.Decode(bytes.NewReader(buffer.Bytes()))
|
133
|
+
check(err)
|
134
|
+
filter := gift.New(gift.ResizeToFit(
|
135
|
+
THUMB_MAX_WIDTH,
|
136
|
+
THUMB_MAX_HEIGHT,
|
137
|
+
gift.LanczosResampling,
|
138
|
+
))
|
139
|
+
dst := image.NewNRGBA(filter.Bounds(src.Bounds()))
|
140
|
+
filter.Draw(dst, src)
|
141
|
+
buffer.Reset()
|
142
|
+
bWriter := bufio.NewWriter(buffer)
|
143
|
+
switch fi.Type {
|
144
|
+
case "image/jpeg", "image/pjpeg":
|
145
|
+
err = jpeg.Encode(bWriter, dst, nil)
|
146
|
+
case "image/gif":
|
147
|
+
err = gif.Encode(bWriter, dst, nil)
|
148
|
+
default:
|
149
|
+
err = png.Encode(bWriter, dst)
|
150
|
+
}
|
151
|
+
check(err)
|
152
|
+
bWriter.Flush()
|
153
|
+
thumbnailKey := fi.Key + thumbSuffix + filepath.Ext(fi.Name)
|
154
|
+
item := &memcache.Item{
|
155
|
+
Key: thumbnailKey,
|
156
|
+
Value: buffer.Bytes(),
|
157
|
+
}
|
158
|
+
err = memcache.Set(c, item)
|
159
|
+
check(err)
|
160
|
+
fi.ThumbnailKey = thumbnailKey
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
func handleUpload(r *http.Request, p *multipart.Part) (fi *FileInfo) {
|
165
|
+
fi = &FileInfo{
|
166
|
+
Name: p.FileName(),
|
167
|
+
Type: p.Header.Get("Content-Type"),
|
168
|
+
}
|
169
|
+
if !fi.ValidateType() {
|
170
|
+
return
|
171
|
+
}
|
172
|
+
defer func() {
|
173
|
+
if rec := recover(); rec != nil {
|
174
|
+
log.Println(rec)
|
175
|
+
fi.Error = rec.(error).Error()
|
176
|
+
}
|
177
|
+
}()
|
178
|
+
var buffer bytes.Buffer
|
179
|
+
hash := crc32.NewIEEE()
|
180
|
+
mw := io.MultiWriter(&buffer, hash)
|
181
|
+
lr := &io.LimitedReader{R: p, N: MAX_FILE_SIZE + 1}
|
182
|
+
_, err := io.Copy(mw, lr)
|
183
|
+
check(err)
|
184
|
+
fi.Size = MAX_FILE_SIZE + 1 - lr.N
|
185
|
+
if !fi.ValidateSize() {
|
186
|
+
return
|
187
|
+
}
|
188
|
+
fi.SetKey(hash.Sum32())
|
189
|
+
item := &memcache.Item{
|
190
|
+
Key: fi.Key,
|
191
|
+
Value: buffer.Bytes(),
|
192
|
+
}
|
193
|
+
context := appengine.NewContext(r)
|
194
|
+
err = memcache.Set(context, item)
|
195
|
+
check(err)
|
196
|
+
fi.createThumb(&buffer, context)
|
197
|
+
fi.CreateUrls(r, context)
|
198
|
+
return
|
199
|
+
}
|
200
|
+
|
201
|
+
func getFormValue(p *multipart.Part) string {
|
202
|
+
var b bytes.Buffer
|
203
|
+
io.CopyN(&b, p, int64(1<<20)) // Copy max: 1 MiB
|
204
|
+
return b.String()
|
205
|
+
}
|
206
|
+
|
207
|
+
func handleUploads(r *http.Request) (fileInfos []*FileInfo) {
|
208
|
+
fileInfos = make([]*FileInfo, 0)
|
209
|
+
mr, err := r.MultipartReader()
|
210
|
+
check(err)
|
211
|
+
r.Form, err = url.ParseQuery(r.URL.RawQuery)
|
212
|
+
check(err)
|
213
|
+
part, err := mr.NextPart()
|
214
|
+
for err == nil {
|
215
|
+
if name := part.FormName(); name != "" {
|
216
|
+
if part.FileName() != "" {
|
217
|
+
fileInfos = append(fileInfos, handleUpload(r, part))
|
218
|
+
} else {
|
219
|
+
r.Form[name] = append(r.Form[name], getFormValue(part))
|
220
|
+
}
|
221
|
+
}
|
222
|
+
part, err = mr.NextPart()
|
223
|
+
}
|
224
|
+
return
|
225
|
+
}
|
226
|
+
|
227
|
+
func validateRedirect(r *http.Request, redirect string) bool {
|
228
|
+
if redirect != "" {
|
229
|
+
var redirectAllowTarget *regexp.Regexp
|
230
|
+
if REDIRECT_ALLOW_TARGET != "" {
|
231
|
+
redirectAllowTarget = regexp.MustCompile(REDIRECT_ALLOW_TARGET)
|
232
|
+
} else {
|
233
|
+
referer := r.Referer()
|
234
|
+
if referer == "" {
|
235
|
+
return false
|
236
|
+
}
|
237
|
+
refererUrl, err := url.Parse(referer)
|
238
|
+
if err != nil {
|
239
|
+
return false
|
240
|
+
}
|
241
|
+
redirectAllowTarget = regexp.MustCompile("^" + regexp.QuoteMeta(
|
242
|
+
refererUrl.Scheme+"://"+refererUrl.Host+"/",
|
243
|
+
))
|
244
|
+
}
|
245
|
+
return redirectAllowTarget.MatchString(redirect)
|
246
|
+
}
|
247
|
+
return false
|
248
|
+
}
|
249
|
+
|
250
|
+
func get(w http.ResponseWriter, r *http.Request) {
|
251
|
+
if r.URL.Path == "/" {
|
252
|
+
http.Redirect(w, r, WEBSITE, http.StatusFound)
|
253
|
+
return
|
254
|
+
}
|
255
|
+
// Use RequestURI instead of r.URL.Path, as we need the encoded form:
|
256
|
+
key := extractKey(r)
|
257
|
+
parts := strings.Split(key, "/")
|
258
|
+
if len(parts) == 3 {
|
259
|
+
context := appengine.NewContext(r)
|
260
|
+
item, err := memcache.Get(context, key)
|
261
|
+
if err == nil {
|
262
|
+
w.Header().Add("X-Content-Type-Options", "nosniff")
|
263
|
+
contentType, _ := url.QueryUnescape(parts[0])
|
264
|
+
if !imageTypes.MatchString(contentType) {
|
265
|
+
contentType = "application/octet-stream"
|
266
|
+
}
|
267
|
+
w.Header().Add("Content-Type", contentType)
|
268
|
+
w.Header().Add(
|
269
|
+
"Cache-Control",
|
270
|
+
fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME),
|
271
|
+
)
|
272
|
+
w.Write(item.Value)
|
273
|
+
return
|
274
|
+
}
|
275
|
+
}
|
276
|
+
http.Error(w, "404 Not Found", http.StatusNotFound)
|
277
|
+
}
|
278
|
+
|
279
|
+
func post(w http.ResponseWriter, r *http.Request) {
|
280
|
+
result := make(map[string][]*FileInfo, 1)
|
281
|
+
result["files"] = handleUploads(r)
|
282
|
+
b, err := json.Marshal(result)
|
283
|
+
check(err)
|
284
|
+
if redirect := r.FormValue("redirect"); validateRedirect(r, redirect) {
|
285
|
+
if strings.Contains(redirect, "%s") {
|
286
|
+
redirect = fmt.Sprintf(
|
287
|
+
redirect,
|
288
|
+
escape(string(b)),
|
289
|
+
)
|
290
|
+
}
|
291
|
+
http.Redirect(w, r, redirect, http.StatusFound)
|
292
|
+
return
|
293
|
+
}
|
294
|
+
w.Header().Set("Cache-Control", "no-cache")
|
295
|
+
jsonType := "application/json"
|
296
|
+
if strings.Index(r.Header.Get("Accept"), jsonType) != -1 {
|
297
|
+
w.Header().Set("Content-Type", jsonType)
|
298
|
+
}
|
299
|
+
fmt.Fprintln(w, string(b))
|
300
|
+
}
|
301
|
+
|
302
|
+
func delete(w http.ResponseWriter, r *http.Request) {
|
303
|
+
key := extractKey(r)
|
304
|
+
parts := strings.Split(key, "/")
|
305
|
+
if len(parts) == 3 {
|
306
|
+
result := make(map[string]bool, 1)
|
307
|
+
context := appengine.NewContext(r)
|
308
|
+
err := memcache.Delete(context, key)
|
309
|
+
if err == nil {
|
310
|
+
result[key] = true
|
311
|
+
contentType, _ := url.QueryUnescape(parts[0])
|
312
|
+
if imageTypes.MatchString(contentType) {
|
313
|
+
thumbnailKey := key + thumbSuffix + filepath.Ext(parts[2])
|
314
|
+
err := memcache.Delete(context, thumbnailKey)
|
315
|
+
if err == nil {
|
316
|
+
result[thumbnailKey] = true
|
317
|
+
}
|
318
|
+
}
|
319
|
+
}
|
320
|
+
w.Header().Set("Content-Type", "application/json")
|
321
|
+
b, err := json.Marshal(result)
|
322
|
+
check(err)
|
323
|
+
fmt.Fprintln(w, string(b))
|
324
|
+
} else {
|
325
|
+
http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed)
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
func handle(w http.ResponseWriter, r *http.Request) {
|
330
|
+
params, err := url.ParseQuery(r.URL.RawQuery)
|
331
|
+
check(err)
|
332
|
+
w.Header().Add("Access-Control-Allow-Origin", "*")
|
333
|
+
w.Header().Add(
|
334
|
+
"Access-Control-Allow-Methods",
|
335
|
+
"OPTIONS, HEAD, GET, POST, DELETE",
|
336
|
+
)
|
337
|
+
w.Header().Add(
|
338
|
+
"Access-Control-Allow-Headers",
|
339
|
+
"Content-Type, Content-Range, Content-Disposition",
|
340
|
+
)
|
341
|
+
switch r.Method {
|
342
|
+
case "OPTIONS", "HEAD":
|
343
|
+
return
|
344
|
+
case "GET":
|
345
|
+
get(w, r)
|
346
|
+
case "POST":
|
347
|
+
if len(params["_method"]) > 0 && params["_method"][0] == "DELETE" {
|
348
|
+
delete(w, r)
|
349
|
+
} else {
|
350
|
+
post(w, r)
|
351
|
+
}
|
352
|
+
case "DELETE":
|
353
|
+
delete(w, r)
|
354
|
+
default:
|
355
|
+
http.Error(w, "501 Not Implemented", http.StatusNotImplemented)
|
356
|
+
}
|
357
|
+
}
|
358
|
+
|
359
|
+
func init() {
|
360
|
+
http.HandleFunc("/", handle)
|
361
|
+
}
|
Binary file
|
@@ -0,0 +1,17 @@
|
|
1
|
+
application: jquery-file-upload
|
2
|
+
version: 1
|
3
|
+
runtime: python27
|
4
|
+
api_version: 1
|
5
|
+
threadsafe: true
|
6
|
+
|
7
|
+
libraries:
|
8
|
+
- name: PIL
|
9
|
+
version: latest
|
10
|
+
|
11
|
+
handlers:
|
12
|
+
- url: /(favicon\.ico|robots\.txt)
|
13
|
+
static_files: static/\1
|
14
|
+
upload: static/(.*)
|
15
|
+
expiration: '1d'
|
16
|
+
- url: /.*
|
17
|
+
script: main.app
|