-
-
Notifications
You must be signed in to change notification settings - Fork 19
/
handle_upload.moon
91 lines (71 loc) · 2.15 KB
/
handle_upload.moon
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
FILE_PARAM = "file"
import to_json from require "lapis.util"
import Uploads from require "models"
import validate_signed_url from require "helpers.url"
import parse_content_disposition from require "lapis.util"
config = require("lapis.config").get!
logging = require "lapis.logging"
resty_upload = require "resty.upload"
handle_upload = ->
is_valid = validate_signed_url {
req: {
parsed_url: {
path: ngx.var.uri
}
}
params: ngx.req.get_uri_args!
}
return nil, "invalid signature" unless is_valid
upload = Uploads\find ngx.var.upload_id
return nil, "already uploaded" if upload.ready
full_path = config.user_content_path .. "/" .. upload\path!
dir = full_path\match "^(.+)/[^/]+$"
import shell_escape from require "lapis.cmd.path"
os.execute "mkdir -p '#{shell_escape dir}'" if dir
input, err = resty_upload\new 8192
return nil, err unless input
input\set_timeout 1000 -- 1 sec
current = {}
file = assert io.open full_path, "w"
success, err = pcall ->
while true
t, res, err = input\read!
switch t
when "body"
if current.name == FILE_PARAM
assert(file, "file already closed")\write res
when "header"
name, value = unpack res
if name == "Content-Disposition"
if params = parse_content_disposition value
for tuple in *params
current[tuple[1]] = tuple[2]
else
current[name\lower!] = value
when "part_end"
if current.name == FILE_PARAM
file\close!
file = nil
current = {}
when "eof"
break
else
return nil, err or "failed to read upload"
if file
file\close!
return nil, "failed to upload file: #{err}"
ngx.header["Content-Type"] = "application/json"
ngx.print to_json { success: true }
upload\update ready: true
logging.request {
req: {
cmd_mth: ngx.var.request_method
cmd_url: ngx.var.uri
}
res: { status: 200 }
}
true
success, err = handle_upload!
unless success
ngx.header["Content-Type"] = "application/json"
ngx.print to_json { errors: {err} }