infod 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/infod.rb +2 -3
- data/infod/Es.rb +31 -67
- data/infod/{W/source.rb → Es/code.rb} +6 -10
- data/infod/Es/css.rb +21 -0
- data/infod/{W → Es}/csv.rb +0 -0
- data/infod/Es/du.rb +16 -0
- data/infod/{W → Es}/feed.rb +13 -11
- data/infod/Es/filter.rb +75 -0
- data/infod/Es/find.rb +20 -0
- data/infod/Es/fs.rb +145 -136
- data/infod/Es/glob.rb +22 -0
- data/infod/Es/grep.rb +61 -0
- data/infod/Es/groonga.rb +47 -56
- data/infod/Es/html.rb +271 -0
- data/infod/Es/image.rb +114 -0
- data/infod/Es/in.rb +68 -0
- data/infod/Es/index.rb +183 -0
- data/infod/{W → Es}/json.rb +28 -4
- data/infod/Es/kv.rb +60 -0
- data/infod/Es/ls.rb +58 -0
- data/infod/Es/mail.rb +87 -0
- data/infod/Es/man.rb +112 -0
- data/infod/Es/mime.rb +59 -0
- data/infod/Es/out.rb +52 -0
- data/infod/{W/page.rb → Es/pager.rb} +7 -3
- data/infod/Es/pdf.rb +19 -0
- data/infod/Es/rdf.rb +35 -0
- data/infod/Es/schema.rb +99 -0
- data/infod/Es/search.rb +24 -0
- data/infod/Es/sh.rb +21 -0
- data/infod/{W → Es}/text.rb +26 -14
- data/infod/H.rb +15 -29
- data/infod/H/audio.rb +19 -0
- data/infod/H/blog.rb +15 -0
- data/infod/{W → H}/cal.rb +2 -31
- data/infod/H/edit.rb +88 -0
- data/infod/{W/examine/examine.rb → H/facets.rb} +17 -17
- data/infod/{W → H}/forum.rb +1 -0
- data/infod/{W/examine/sw.rb → H/hf.rb} +12 -12
- data/infod/H/histogram.rb +78 -0
- data/infod/H/mail.rb +92 -0
- data/infod/{W/chat.rb → H/microblog.rb} +21 -16
- data/infod/H/threads.rb +77 -0
- data/infod/H/time.rb +131 -0
- data/infod/H/who.rb +30 -0
- data/infod/{W → H}/wiki.rb +0 -0
- data/infod/K.rb +28 -60
- data/infod/N.rb +151 -74
- data/infod/Rb.rb +3 -3
- data/infod/Th.rb +27 -101
- data/infod/Th/404.rb +29 -36
- data/infod/Th/500.rb +36 -5
- data/infod/Th/GET.rb +48 -118
- data/infod/Th/POST.rb +31 -11
- data/infod/Th/perf.rb +37 -0
- data/infod/Th/util.rb +89 -0
- data/infod/Y.rb +24 -7
- data/infod/infod.rb +2 -3
- metadata +92 -64
- data/infod/Es/redis.rb +0 -3
- data/infod/Es/sqlite.rb +0 -3
- data/infod/Th/local.rb +0 -22
- data/infod/W.rb +0 -34
- data/infod/W/audio.rb +0 -56
- data/infod/W/blog.rb +0 -3
- data/infod/W/color.rb +0 -28
- data/infod/W/core.rb +0 -77
- data/infod/W/css.rb +0 -24
- data/infod/W/du.rb +0 -35
- data/infod/W/edit.rb +0 -8
- data/infod/W/examine/exhibit.rb +0 -34
- data/infod/W/examine/hist.rb +0 -55
- data/infod/W/examine/history.rb +0 -19
- data/infod/W/examine/normal.rb +0 -31
- data/infod/W/examine/protovis.rb +0 -30
- data/infod/W/examine/time/graph.rb +0 -86
- data/infod/W/examine/time/line.rb +0 -24
- data/infod/W/find.rb +0 -24
- data/infod/W/grep.rb +0 -27
- data/infod/W/html.rb +0 -143
- data/infod/W/image.rb +0 -61
- data/infod/W/kv.rb +0 -66
- data/infod/W/ls.rb +0 -50
- data/infod/W/mail.rb +0 -248
- data/infod/W/pdf.rb +0 -16
- data/infod/W/post.rb +0 -9
- data/infod/W/rdf.rb +0 -32
- data/infod/W/schema.rb +0 -172
- data/infod/W/search.rb +0 -33
- data/infod/W/shell.rb +0 -30
- data/infod/W/table.rb +0 -87
- data/infod/W/tree.rb +0 -26
- data/infod/W/vfs.rb +0 -175
data/infod/Rb.rb
CHANGED
@@ -4,7 +4,7 @@ class Array
|
|
4
4
|
def head; self[0] end
|
5
5
|
def tail; self[1..-1] end
|
6
6
|
def snd; self[1] end
|
7
|
-
def
|
7
|
+
def random; self[rand length] end
|
8
8
|
def h; join.h end
|
9
9
|
def intersperse i
|
10
10
|
inject([]){|a,b|a << b << i}[0..-2]
|
@@ -65,7 +65,7 @@ end
|
|
65
65
|
class NilClass
|
66
66
|
def do; nil end
|
67
67
|
def to_ary; [] end
|
68
|
+
def to_hash; {} end
|
68
69
|
def to_s; "" end
|
69
|
-
alias_method
|
70
|
-
def method_missing *a; nil; end
|
70
|
+
%w{html to_str}.map{|m|alias_method m,:to_s}
|
71
71
|
end
|
data/infod/Th.rb
CHANGED
@@ -1,110 +1,36 @@
|
|
1
|
-
|
1
|
+
#watch __FILE__
|
2
2
|
require 'rack'
|
3
|
-
|
4
|
-
class String
|
5
|
-
# parse querystring
|
6
|
-
def qp
|
7
|
-
d={}
|
8
|
-
split(/&/).map{|e|
|
9
|
-
k,v=e.split(/=/,2).map{|x|
|
10
|
-
CGI.unescape x}
|
11
|
-
d[k]=v}
|
12
|
-
d
|
13
|
-
end
|
14
|
-
def hR
|
15
|
-
[200,{'Content-Type'=>'text/html'},[self]]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
module Tb
|
20
|
-
def q
|
21
|
-
@q ||= self.().qp
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
module Th
|
26
|
-
def qs
|
27
|
-
(['GET','HEAD'].member? fn) ? self['QUERY_STRING'] : self['rack.input'].read
|
28
|
-
end
|
29
|
-
# read querystring
|
30
|
-
def q
|
31
|
-
@q ||= (qs||'').qp.do{|q|
|
32
|
-
(q['?']).do{|d|
|
33
|
-
E::F['?'][d].do{|g| # expand aliases
|
34
|
-
g.merge q
|
35
|
-
} || q } || q}
|
36
|
-
end
|
37
|
-
# read Accept header
|
38
|
-
def accept_ k=''
|
39
|
-
d={}
|
40
|
-
self['HTTP_ACCEPT'+k].do{|k|
|
41
|
-
k.split(/,/).map{|e|
|
42
|
-
f,q=e.split(/;/)
|
43
|
-
i=q&&q.split(/=/)[1].to_f||1
|
44
|
-
d[i]||=[]
|
45
|
-
d[i].push f}}
|
46
|
-
d
|
47
|
-
end
|
48
|
-
|
49
|
-
def format
|
50
|
-
@format ||= conneg
|
51
|
-
end
|
52
|
-
|
53
|
-
def conneg
|
54
|
-
# choose a preferred content-type
|
55
|
-
return q['format'] if q['format'] && E::F[E::Render+q['format']]
|
56
|
-
accept.sort.reverse.map{|p|p[1].map{|mime|
|
57
|
-
return mime if E::F[E::Render+mime]
|
58
|
-
}}
|
59
|
-
'text/html'
|
60
|
-
end
|
61
|
-
|
62
|
-
def accept; @accept ||= accept_ end
|
63
|
-
|
64
|
-
def fn
|
65
|
-
# request method (Symbol) getter
|
66
|
-
self['REQUEST_METHOD']
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
class Hash
|
71
|
-
def qs
|
72
|
-
'?'+map{|k,v|k.to_s+'='+(v ? (CGI.escape [*v][0].to_s) : '')}.intersperse("&").join('')
|
73
|
-
end
|
74
|
-
def env r # thread environment through to children
|
75
|
-
@r = r
|
76
|
-
self
|
77
|
-
end
|
78
|
-
end
|
3
|
+
%w{GET HEAD POST PATCH perf uid util 404 500}.map{|i|require_relative 'Th/' + i}
|
79
4
|
|
80
5
|
class E
|
81
6
|
|
82
|
-
F['?'] ||= {}
|
83
|
-
|
84
|
-
# access or update request environment
|
85
|
-
def env r=nil
|
86
|
-
r ? (@r = r
|
87
|
-
self) : @r
|
88
|
-
end
|
89
|
-
|
90
7
|
def E.call e
|
91
|
-
dev
|
92
|
-
e.extend Th
|
93
|
-
e['HTTP_X_FORWARDED_HOST'].do{|h| e['SERVER_NAME'] = h }
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
8
|
+
dev
|
9
|
+
e.extend Th
|
10
|
+
e['HTTP_X_FORWARDED_HOST'].do{|h| e['SERVER_NAME'] = h }
|
11
|
+
p = e['REQUEST_PATH'].force_encoding 'UTF-8'
|
12
|
+
|
13
|
+
uri = CGI.unescape(if (p.index Prefix) == 0
|
14
|
+
p[Prefix.size..-1]
|
15
|
+
else
|
16
|
+
'http://' + e['SERVER_NAME'] + (p.gsub '+','%2B')
|
17
|
+
end).E.env e
|
18
|
+
|
19
|
+
if (uri.node.expand_path.to_s.index FSbase) == 0
|
20
|
+
e['uri'] = uri.uri
|
21
|
+
# response
|
22
|
+
r = nil # request method
|
23
|
+
b = Benchmark.measure{ r = uri.send e.fn }
|
24
|
+
F['log'][r[0],e,b.real]
|
25
|
+
r
|
26
|
+
else
|
27
|
+
[403,{},['Forbidden']]
|
103
28
|
end
|
104
29
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
30
|
+
rescue Exception => x
|
31
|
+
$stderr.puts 500, e['REQUEST_URI'] ,x.message,x.backtrace
|
32
|
+
F['log'][500,e]
|
33
|
+
F['E500'][x,@r]
|
34
|
+
end
|
109
35
|
|
110
36
|
end
|
data/infod/Th/404.rb
CHANGED
@@ -1,55 +1,48 @@
|
|
1
|
+
watch __FILE__
|
1
2
|
class E
|
2
3
|
|
3
|
-
# 404 response URI
|
4
4
|
E404 = 'req/'+HTTP+'404'
|
5
5
|
|
6
|
-
# 404 response function
|
7
6
|
fn E404,->e,r{
|
8
|
-
|
9
|
-
g = {
|
10
|
-
s = g[
|
11
|
-
|
12
|
-
r.map{|k,v| s[k] = [v] }
|
13
|
-
s[Type] = [E[HTTP+'404']]
|
14
|
-
s['uri'] = u
|
15
|
-
s['QUERY'] = [r.q]
|
16
|
-
s['ACCEPT']= [r.accept]
|
17
|
-
s['SERVER_SOFTWARE']=[('//'+r['SERVER_NAME']).E]
|
18
|
-
s['http://buzzword.org.uk/rdf/personal-link-types#edit']=[E[u+'?view=edit&graph=_']]
|
19
|
-
%w{CHARSET LANGUAGE ENCODING}.map{|a|s['ACCEPT_'+a] = [(r.accept_ '_' + a)]}
|
20
|
-
# output
|
21
|
-
r.q.delete 'view' # use 404 view if HTML
|
22
|
-
[404,{'Content-Type'=> r.format},[e.render(r.format,g,r)]]}
|
7
|
+
id = e.uri # response URI
|
8
|
+
g = {id=>{}} # response graph
|
9
|
+
s = g[id] # resource pointer
|
10
|
+
fn = r['REQUEST_METHOD']
|
23
11
|
|
24
|
-
|
25
|
-
|
12
|
+
# request environment -> graph
|
13
|
+
r.map{|k,v| s[Header + k] = k == 'uri' ? v : [v] }
|
14
|
+
%w{CHARSET LANGUAGE ENCODING}.map{|a|
|
15
|
+
s[Header+'ACCEPT_'+a] = [r.accept_('_' + a)]}
|
16
|
+
s[Header+'ACCEPT'] = [r.accept]
|
17
|
+
s[Type] = [E[HTTP+'Response']]
|
18
|
+
s[HTTP+'statusCodeValue'] = [404]
|
19
|
+
s[Header+'HTTP_HOST'] = [E['http://' + s[Header+'HTTP_HOST'][0]]]
|
20
|
+
s[Edit] = [E[r['REQUEST_PATH']+'?view=edit&graph=editable']]
|
21
|
+
s['#query'] = [r.q]
|
22
|
+
s['#seeAlso'] = [e.parent,*e.a('*').glob]
|
23
|
+
r.q['view'] = '404'
|
26
24
|
|
27
|
-
|
28
|
-
|
25
|
+
[404,{'Content-Type'=> r.format},[e.render(r.format,g,r)]]}
|
26
|
+
|
27
|
+
fn 'view/404',->d,e{
|
28
|
+
[H.css('/css/404'),{_: :style, c: "a {background-color:#{E.cs}}"},
|
29
|
+
d.html]}
|
29
30
|
|
30
|
-
#
|
31
|
-
fn '/
|
32
|
-
[
|
33
|
-
|
34
|
-
a {font-size:1.05em;background-color:#1ef;color:#000;text-decoration:none;padding:.1em}
|
35
|
-
td.key {text-align:right}
|
36
|
-
td.key .frag {font-weight:bold;background-color:#0f0;color:#000;padding-left:.2em;border-radius:.38em 0 0 .38em}
|
37
|
-
td.key .abbr {color:#eee;font-size:.92em}
|
38
|
-
td.val {border-style:dotted;border-width:0 0 .1em 0;border-color:#00f;}"]]}
|
31
|
+
# a small non-empty graph
|
32
|
+
fn 'protograph/_',->d,_,m{
|
33
|
+
m[d.uri] = {}
|
34
|
+
rand.to_s.h}
|
39
35
|
|
40
|
-
#
|
36
|
+
# check response-codes for a list of URIs (linebreak-separated *.u files)
|
41
37
|
def checkURIs
|
42
38
|
r = uris.select{|u|u.to_s.match /^http/}.map{|u|
|
43
39
|
c = [`curl -IsA 404? "#{u}"`.lines.to_a[0].match(/\d{3}/)[0].to_i,u] # HEAD
|
44
|
-
#c = [`curl -s -o /dev/null -w %{http_code} "#{u}"`.chomp.to_i,u] # GET
|
45
40
|
puts c.join ' '
|
46
|
-
c # status, uri tuple
|
47
|
-
}
|
41
|
+
c } # status, uri tuple
|
48
42
|
puts "\n\n"
|
49
43
|
r.map{|c|
|
50
44
|
# show anomalies
|
51
|
-
puts c.join(' ') unless c[0] == 200
|
52
|
-
}
|
45
|
+
puts c.join(' ') unless c[0] == 200 }
|
53
46
|
end
|
54
47
|
|
55
48
|
end
|
data/infod/Th/500.rb
CHANGED
@@ -1,10 +1,41 @@
|
|
1
|
-
#watch __FILE__
|
2
1
|
class E
|
3
2
|
|
4
|
-
fn '
|
3
|
+
fn '/css/500.css/GET',->e,r{
|
4
|
+
[200,{'Content-Type'=>'text/css'},["
|
5
|
+
body {margin:0; font-family: sans-serif; background-color:#fff; color:#000}
|
6
|
+
h1 {padding:.2em; background-color:#f00; color:#fff; margin:0}
|
7
|
+
div {display:inline}
|
8
|
+
table {border-spacing:0;margin:0}
|
9
|
+
b {background-color:#eee;color:#500;padding:.1em .3em .1em .3em}
|
10
|
+
.frag {font-weight:bold; color:#000; background-color:#{E.cs}}
|
11
|
+
td.space {background-color:#ddd}
|
12
|
+
td.message {background-color:#009;color:#fff}
|
13
|
+
td.path {text-align:right}
|
14
|
+
td.index {text-align:right;border-color:#000;border-width:0 0 .1em 0;border-style:dotted;background-color:#ddd;color:#000}
|
15
|
+
td.context {border-color:#ddd;border-width:0 0 .1em 0;border-style:dotted;padding:.15em}"]]}
|
16
|
+
|
17
|
+
F['/E/error/GET'] = ->e,r{1/0}
|
18
|
+
|
19
|
+
fn 'E500',->x,r{
|
5
20
|
[500,{'Content-Type'=>'text/html'},
|
6
|
-
[
|
7
|
-
|
8
|
-
|
21
|
+
[H[{_: :html,
|
22
|
+
c: [{_: :head,
|
23
|
+
c: [{_: :title, c: 500},(H.css '/css/500')]},
|
24
|
+
{_: :body,
|
25
|
+
c: [{_: :h1, c: 500},
|
26
|
+
{_: :table,
|
27
|
+
c: [{_: :tr,
|
28
|
+
c: [{_: :td, c: {_: :b, c: x.class}},
|
29
|
+
{_: :td, class: :space},
|
30
|
+
{_: :td, class: :message, c: x.message.hrefs}
|
31
|
+
]},
|
32
|
+
x.backtrace.map{|p|
|
33
|
+
p = p.split /:/, 3
|
34
|
+
{_: :tr,
|
35
|
+
c: [{_: :td, class: :path, c: F['abbrURI'][p[0]]},
|
36
|
+
{_: :td, class: :index, c: p[1]},
|
37
|
+
{_: :td, class: :context, c: (p[2]||'').hrefs}].cr}}.cr]}]}]}]]]}
|
9
38
|
|
39
|
+
F['/500/GET'] = ->e,r{H([Errors.sort_by{|u,r|r[:time]}.reverse.html,H.css('/css/500')]).hR}
|
40
|
+
|
10
41
|
end
|
data/infod/Th/GET.rb
CHANGED
@@ -1,132 +1,62 @@
|
|
1
1
|
class E
|
2
2
|
|
3
3
|
def GET
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
def maybeSend m,b,lH=false
|
19
|
-
send? ? # agent already has this version?
|
20
|
-
b.().do{|b| # continue
|
21
|
-
h = {'Content-Type'=> m, 'ETag'=> @r['ETag']} # response header
|
22
|
-
m.match(/^(audio|image|video)/) && # media MIME-type?
|
23
|
-
h.update({'Cache-Control' => 'no-transform'}) # no further compression
|
24
|
-
h.update({'MS-Author-Via' => 'DAV, SPARQL'}) # authoring
|
25
|
-
lH && h.update({'Link' => '<' + (URI.escape uri) + '?format=text/n3>; rel=meta'}) # Link Header - full URI variant
|
26
|
-
b.class == E ? (Nginx ? # nginx env-var
|
27
|
-
[200,h.update({'X-Accel-Redirect' => '/fs' + b.path}),[]] : # Nginx file-handler
|
28
|
-
Apache ? # Apache env-var
|
29
|
-
[200,h.update({'X-Sendfile' => b.d}),[]] : # Apache file-handler
|
30
|
-
(r = Rack::File.new nil # create Rack file-handler
|
31
|
-
r.instance_variable_set '@path',b.d # set path
|
32
|
-
r.serving(@r).do{|s,m,b|[s,m.update(h),b]}) # Rack file-handler
|
33
|
-
) :
|
34
|
-
[200, h, b]} : # response triple
|
35
|
-
[304,{},[]] # not modified
|
4
|
+
# bespoke handler ||
|
5
|
+
# raw file ||
|
6
|
+
# resource
|
7
|
+
if reqFn = F['req/'+@r.q['y']]
|
8
|
+
reqFn[self,@r]
|
9
|
+
elsif file = [self,pathSegment].compact.find(&:f)
|
10
|
+
a = @r.accept.values.flatten
|
11
|
+
accepted = a.empty? || (a.member? file.mimeP) || (a.member? '*/*')
|
12
|
+
(@r.q.has_any_key(%w{format view}) ||
|
13
|
+
MIMEcook[file.mimeP] || !accepted) ? resource : (file.env @r).getFile
|
14
|
+
else
|
15
|
+
resource
|
16
|
+
end
|
36
17
|
end
|
37
18
|
|
38
|
-
def
|
39
|
-
!((m=@r['HTTP_IF_NONE_MATCH']) && m.strip.split(/\s*,\s*/).include?(@r['ETag']))
|
40
|
-
end
|
41
|
-
|
42
|
-
def GET_file
|
19
|
+
def getFile
|
43
20
|
@r['ETag'] = [m,size].h
|
44
|
-
maybeSend
|
21
|
+
maybeSend mimeP,->{self},:link
|
45
22
|
end
|
46
23
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
).do{|y|y.(self,@r)} || # custom handler
|
56
|
-
as('index.html').do{|i| # HTML index
|
57
|
-
i.e && # exists?
|
58
|
-
((uri[-1]=='/') ? i.env(@r).GET_file : # are we inside dir?
|
59
|
-
[301, {Location: uri.t}] )} || # rebase to index dir
|
24
|
+
def resource
|
25
|
+
# bubble up site then global tree until handled (false return-value to pass)
|
26
|
+
pathSegment.do{|path|
|
27
|
+
lambdas = path.cascade.map{|p| p.uri.t + 'GET' }
|
28
|
+
['http://'+@r['SERVER_NAME'],""].map{|h| lambdas.map{|p|
|
29
|
+
F[h + p].do{|fn| fn[self,@r].do{|r| return r}}}}}
|
30
|
+
|
31
|
+
# default handler
|
60
32
|
response
|
61
33
|
end
|
62
34
|
|
63
|
-
|
64
|
-
|
65
|
-
F['set/' + q['set']][e, q, m]. # doc set
|
66
|
-
map{|u|m[u.uri] ||= u}}
|
67
|
-
|
68
|
-
# document set constructor
|
69
|
-
fn 'set/',->d,e,m{d.docs}
|
70
|
-
|
71
|
-
# construct HTTP response
|
72
|
-
def response
|
73
|
-
|
74
|
-
# request arguments
|
75
|
-
q = @r.q # query-string
|
76
|
-
g = q['graph'] # graph-generation function selector
|
77
|
-
|
78
|
-
# request graph
|
79
|
-
m = {}
|
80
|
-
|
81
|
-
# add resources to request graph
|
82
|
-
F['graph/' + g][self,q,m]
|
83
|
-
|
84
|
-
# empty graph -> 404
|
85
|
-
return F[E404][self,@r] if m.empty?
|
86
|
-
|
87
|
-
# inspect request-graph
|
88
|
-
if q.has_key? 'debug'
|
89
|
-
puts "docs #{m.keys.join ' '}"
|
90
|
-
puts "resources #{m['frag']['res']}" if m['frag']
|
91
|
-
end
|
92
|
-
|
93
|
-
# request-graph identifier
|
94
|
-
s = (q.has_key?('nocache') ? rand.to_s : # random identifier
|
95
|
-
m.sort.map{|u,r|[u, r.respond_to?(:m) && r.m]}).h # canonicalized set signature
|
96
|
-
|
97
|
-
# response identifier
|
98
|
-
@r['ETag'] ||= [s, q, @r.format].h
|
99
|
-
|
100
|
-
# check if client has response
|
101
|
-
maybeSend @r.format, ->{
|
102
|
-
|
103
|
-
# cached response identifier
|
104
|
-
r = E'/E/req/' + @r['ETag'].dive
|
105
|
-
|
106
|
-
if r.e # response already generated
|
107
|
-
r # cached response
|
108
|
-
else
|
109
|
-
|
110
|
-
# cached graph identifier
|
111
|
-
c = E '/E/graph/' + s.dive
|
112
|
-
|
113
|
-
if c.e # cached graph exists
|
114
|
-
m.merge! c.r true # read cache
|
115
|
-
else
|
116
|
-
# construct response graph
|
117
|
-
m.values.map{|r|
|
118
|
-
r.env(@r).graphFromFile m}
|
119
|
-
|
120
|
-
# cache response graph
|
121
|
-
c.w m,true
|
122
|
-
end
|
123
|
-
|
124
|
-
# response graph sorting/filtering
|
125
|
-
E.filter q, m, self
|
126
|
-
|
127
|
-
# response body
|
128
|
-
r.w render @r.format, m, @r
|
129
|
-
end }
|
35
|
+
def send?
|
36
|
+
!((m=@r['HTTP_IF_NONE_MATCH']) && m.strip.split(/\s*,\s*/).include?(@r['ETag']))
|
130
37
|
end
|
131
38
|
|
39
|
+
def maybeSend m,b,lH=false
|
40
|
+
# agent need this version?
|
41
|
+
send? ?
|
42
|
+
# continue
|
43
|
+
b[].do{|b|
|
44
|
+
# response metadata
|
45
|
+
h = {'Content-Type'=> m,
|
46
|
+
'ETag'=> @r['ETag']}
|
47
|
+
h.update({'Cache-Control' => 'no-transform'}) if m.match /^(audio|image|video)/
|
48
|
+
h.update({'Link' => '<' + @r['uri'] + '?view=base>; rel=meta'}) if lH
|
49
|
+
|
50
|
+
b.class == E ? (Nginx ? # nginx enabled
|
51
|
+
[200,h.update({'X-Accel-Redirect' => '/fs' + b.path}),[]] : # Nginx file-handler
|
52
|
+
Apache ? # Apache enabled
|
53
|
+
[200,h.update({'X-Sendfile' => b.d}),[]] : # Apache file-handler
|
54
|
+
(r = Rack::File.new nil # Rack file-handler
|
55
|
+
r.instance_variable_set '@path',b.d
|
56
|
+
r.serving(@r).do{|s,m,b|[s,m.update(h),b]})
|
57
|
+
) :
|
58
|
+
[200, h, b]} : # normal (unaccelerated) response
|
59
|
+
[304,{},[]] # client has response version
|
60
|
+
end
|
61
|
+
|
132
62
|
end
|