1
1
local cjson = require " cjson.safe"
2
+ local http = require " resty.http"
2
3
local utils = require " ephemeral-utils"
3
4
4
5
local _M = {}
@@ -14,6 +15,45 @@ function _M.init()
14
15
npmConfig :set (' MAXAGE' , _M .MAXAGE )
15
16
end
16
17
18
+ function _M .prefetchRelatedPackages (premature , selfHost , pkg )
19
+ local httpc = http .new ()
20
+ local meta = ngx .shared .npmMeta
21
+ httpc :connect (' 127.0.0.1' , 4873 )
22
+ local distTags = pkg [' dist-tags' ] or {}
23
+ local versions = pkg .versions or {}
24
+ local latestVersion = distTags .latest
25
+ local latest = versions [latestVersion ] or {}
26
+ local deps = latest .dependencies or {}
27
+ local reqs = {}
28
+ -- find any deps that we haven't already seen and queue them for fetching
29
+ for k , v in pairs (deps ) do
30
+ if meta :get (' /' .. k ) == nil then
31
+ table.insert (reqs , {
32
+ path = ' /' .. k ,
33
+ method = ' GET' ,
34
+ headers = {
35
+ [" Host" ] = selfHost ,
36
+ },
37
+ })
38
+ end
39
+ end
40
+ -- extract all the tarball URLs and fetch them to force them to be cached
41
+ for v ,p in pairs (versions ) do
42
+ local scheme , host , port , path , query = unpack (httpc :parse_uri (p .dist .tarball ))
43
+ table.insert (reqs , {
44
+ path = path ,
45
+ method = ' GET' ,
46
+ })
47
+ end
48
+ local responses , err = httpc :request_pipeline (reqs )
49
+ for i ,r in ipairs (responses ) do
50
+ if r .status then
51
+ r :read_body () -- to oblivion!
52
+ end
53
+ end
54
+ httpc :close ()
55
+ end
56
+
17
57
function _M .getPackage ()
18
58
local uri = ngx .var .uri
19
59
local meta = ngx .shared .npmMeta
@@ -34,10 +74,14 @@ function _M.getPackage()
34
74
return ngx .redirect (uri , ngx .HTTP_MOVED_TEMPORARILY )
35
75
end
36
76
meta :set (uri , body , _M .MAXAGE )
77
+ -- We rewrite the URLs AFTER caching so that we can be accessed by
78
+ -- any hostname that is pointed at us.
79
+ body = string.gsub (body , _M .hostPattern , base )
80
+ ngx .timer .at (0.1 , _M .prefetchRelatedPackages , ngx .var .http_host , pkgJSON )
37
81
else
82
+ body = string.gsub (body , _M .hostPattern , base )
38
83
ngx .var .ephemeralCacheStatus = ' HIT'
39
84
end
40
- body = string.gsub (body , _M .hostPattern , base )
41
85
ngx .header [" Content-Length" ] = # body
42
86
ngx .print (body )
43
87
ngx .eof ()
0 commit comments