1
1
local cjson = require " cjson.safe"
2
+ local http = require " resty.http"
2
3
3
4
local _M = {}
4
5
@@ -11,6 +12,44 @@ function _M.init()
11
12
npmConfig :set (' npm_upstream_pattern' , pattern )
12
13
end
13
14
15
+ function _M .prefetchRelatedPackages (premature , selfHost , pkg )
16
+ local httpc = http .new ()
17
+ httpc :connect (' 127.0.0.1' , 4873 )
18
+ local distTags = pkg [' dist-tags' ] or {}
19
+ local versions = pkg .versions or {}
20
+ local latestVersion = distTags .latest
21
+ local latest = versions [latestVersion ] or {}
22
+ local deps = latest .dependencies or {}
23
+ local reqs = {}
24
+ -- find any deps that we haven't already seen and queue them for fetching
25
+ for k , v in pairs (deps ) do
26
+ if meta :get (' /' .. k ) == nil then
27
+ table.insert (reqs , {
28
+ path = ' /' .. k ,
29
+ method = ' GET' ,
30
+ headers = {
31
+ [" Host" ] = selfHost ,
32
+ },
33
+ })
34
+ end
35
+ end
36
+ -- extract all the tarball URLs and fetch them to force them to be cached
37
+ for v ,p in pairs (versions ) do
38
+ local scheme , host , port , path , query = unpack (httpc :parse_uri (p .dist .tarball ))
39
+ table.insert (reqs , {
40
+ path = path ,
41
+ method = ' GET' ,
42
+ })
43
+ end
44
+ local responses , err = httpc :request_pipeline (reqs )
45
+ for i ,r in ipairs (responses ) do
46
+ if r .status then
47
+ r :read_body () -- to oblivion!
48
+ end
49
+ end
50
+ httpc :close ()
51
+ end
52
+
14
53
function _M .getPackage ()
15
54
local uri = ngx .var .uri
16
55
local meta = ngx .shared .npmMeta
@@ -27,7 +66,8 @@ function _M.getPackage()
27
66
-- next time
28
67
return ngx .redirect (uri , ngx .HTTP_MOVED_TEMPORARILY )
29
68
end
30
- meta :set (uri , body )
69
+ local succ , err , forcible = meta :set (uri , body )
70
+ ngx .timer .at (0.1 , _M .prefetchRelatedPackages , ngx .var .http_host , pkgJSON )
31
71
end
32
72
ngx .header [" Content-Length" ] = # body
33
73
ngx .print (body )
0 commit comments