UNPKG

3.01 kBMarkdownView Raw
1Web server
2----------
3
4 DOWNLOAD = 'get'
5 UPLOAD = 'put'
6 TOKEN = 'token'
7 REV = 'rev'
8 UNTIL = 'until'
9
10 attachments_proxy = ( our_proxy ) ->
11
12 {secret,hash,timeout} = our_proxy
13
14 cors = Cors()
15
16 hash ?= 'sha256'
17 timeout ?= 3600*1000 # one hour
18
19 signature = (method,pathname,rev,limit) ->
20 strictEqual 'string', typeof method, 'method'
21 strictEqual 'string', typeof pathname, 'pathname'
22 strictEqual 'string', typeof rev, 'rev'
23 strictEqual 'string', typeof limit, 'limit'
24 crypto
25 .createHmac hash, secret
26 .update method
27 .update pathname
28 .update rev
29 .update limit
30 .digest 'hex'
31
32 handler = (req,res,next) ->
33
34 next ?= (msg) ->
35 res.writeHead 404
36 res.end msg
37 return
38
39 proxy = ->
40 {method} = req
41 options = our_proxy.target pathname
42 return next() unless options?.url?
43
44 options.url.searchParams.set 'rev', rev
45 options.url = options.url.toString()
46
47 the_proxy = agent Object.assign {
48 method
49 followRedirects: false
50 maxRedirects: 0
51 headers:
52 Connection: 'close'
53 }, options
54 the_proxy.on 'error', (error) ->
55 console.error 'Proxy', method, options.url, error
56 req.pipe the_proxy
57 the_proxy.pipe res
58 return
59
60 {pathname,searchParams} = new URL req.url, our_proxy.url
61
62 token = searchParams.get TOKEN
63 return next 'Invalid token' unless token?
64
65 rev = searchParams.get REV
66 return next 'Invalid rev' unless rev?
67
68 limit = searchParams.get UNTIL
69 return next "Invalid limit #{JSON.stringify limit}" unless limit?.match(/^\d+$/) and parseInt(limit) > Date.now()
70
71 switch req.method
72 when 'OPTIONS'
73 return cors req, res, next
74
75 when 'PUT'
76 if token is signature UPLOAD, pathname, rev, limit
77 return proxy()
78 else
79 return next "Invalid token"
80
81 when 'GET', 'HEAD'
82 if token is signature DOWNLOAD, pathname, rev, limit
83 return proxy()
84 else
85 return next "Invalid token"
86
87 next()
88 return
89
90 uri_maker = (direction) ->
91 (path,rev) ->
92 url = new URL path, our_proxy.url
93 url.searchParams.set REV, rev
94 limit = Date.now() + timeout
95 url.searchParams.set UNTIL, limit
96 url.searchParams.set TOKEN, signature direction, path, rev, limit.toString()
97 url.toString()
98
99 download_uri = uri_maker DOWNLOAD
100 upload_uri = uri_maker UPLOAD
101
102 {handler,download_uri,upload_uri}
103
104 module.exports = attachments_proxy
105 {URL} = require 'url'
106 crypto = require 'crypto'
107 request = require 'request'
108 agent = request.defaults()
109 Cors = require 'cors'
110 {strictEqual} = assert = require 'assert'