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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
# Rack Application class
require 'gorg/cgi'
module Gorg
class Application
# TODO: should be a class instance
include Gorg
def call(environment)
request = Rack::Request.new(environment)
response = Rack::Response.new
hit = "#{$Config["root"]}#{request.path}"
cacheName = request.path
if FileTest.directory?(hit) and FileTest.exist?(hit+"/index.xml") then
# Use $URI/index.xml for directories that have an index.xml file
hit << "/index.xml"
cacheName << "/index.xml"
end
hit.squeeze!('/')
cacheName.squeeze!('/')
if FileTest.directory?(hit) then
return Rack::Directory.new($Config['root']).call(environment)
else
if hit !~ /\.(xml)|(rdf)|(rss)$/ then
puts "Try to server a file for #{hit}"
return Rack::File.new($Config['root']).call(environment)
else
if not FileTest.exist?(hit) then
return Rack::File.new($Config['root']).call(environment)
else
# Parse If-None-Match and If-Modified-Since request header fields if any
ims=inm=nil
begin
ims = Time.parse(req['if-modified-since']) if req['if-modified-since']
inm = split_header_etags(req['if-none-match']) if req['if-none-match']
rescue
# Just ignore ill-formated data
nil
end
begin
response['Charset'] = 'UTF-8'
# Process xml file or return xml file if passthru=1
if $Config['passthru'] && request.params && request.params["passthru"] && request.params["passthru"] != "0" then
# passthru allowed by config and requested by visitor, return file as text/plain
mstat = File.stat(hit)
raise Gorg::Status::NotModified.new(mstat) if notModified?(mstat, inm, ims)
debug("Passthru granted for #{hit}")
body = IO.read(hit)
# If client accepts gzip encoding and we support it, return gzipped file
if $Config["zipLevel"] > 0 and (req.accept_encoding.include?("gzip") or req.accept_encoding.include?("x-gzip")) then
res.body = gzip(body, $Config["zipLevel"])
response['Content-Encoding'] = "gzip"
response['Vary'] = "Accept-Encoding"
else
res.body = body
end
response['Content-Type'] = 'text/plain'
else
query_params = request.params.dup
# Get cookies and add them to the parameters
if $Config["acceptCookies"] then
# We need CGI:Cookie objects to be compatible with our cgi modules (stupid WEBrick)
puts "PENDING: raw header access for Cookie"
# ck = req.raw_header.find{|l| l =~ /^cookie: /i}
ck = false
if ck then
query_params.merge!(cookies_to_params(CGI::Cookie.parse($'.strip)))
debug "query params are " + query_params.inspect
end
end
if $Config["httphost"] then
# Add HTTP_HOST to stylesheet params
query_params["httphost"] = if $Config["httphost"][0] == '*' then
request.host||""
elsif $Config["httphost"].include?('*') then
$Config["httphost"][0]
elsif $Config["httphost"].include?(request.host) then
$Config["httphost"][0]
else
request.host||""
end
end
bodyZ = nil
body, mstat, extrameta = Gorg::Cache.hit(cacheName, query_params, inm, ims)
if body.nil? then
xml_query = query_params.dup
if $Config["linkParam"] then
xml_query[$Config["linkParam"]] = request.path
end
# Cache miss, process file and cache result
puts xml_query.inspect
err, body, filelist, extrameta = xproc(hit, xml_query, true)
puts err.inspect, extrameta.inspect
warn("#{err.collect{|e|e.join(':')}.join('; ')}") if err["xmlErrLevel"] == 1
error("#{err.collect{|e|e.join(':')}.join('; ')}") if err["xmlErrLevel"] > 1
# Display error message if any, just like the cgi/fcgi versions
raise ("#{err.collect{|e|e.join(':')}.join('<br/>')}") if err["xmlErrLevel"] > 0
# Cache output
mstat, bodyZ = Gorg::Cache.store(body, cacheName, query_params, filelist, extrameta)
else
if $Config["zipLevel"] > 0 then
bodyZ = body
body = nil
end
end
# If client accepts gzip encoding and we support it, return gzipped file
if bodyZ and $Config["zipLevel"] > 0 and (request.accept_encoding.include?("gzip") or request.accept_encoding.include?("x-gzip")) then
res.body = bodyZ
response['Content-Encoding'] = "gzip"
response['Vary'] = "Accept-Encoding"
else
if body then
response.write(body)
else
# We need to unzip bodyZ into body, i.e. we cached zipped data but client does not support gzip
response.write(gunzip(bodyZ))
end
end
# Add cookies to http header
cookies = makeCookies(extrameta)
if cookies then
cookies.each{|c| res.cookies << c.to_s}
end
# Add Content-Type to header based on actual content.
ct = setContentType(body)
if ct then
# Turn application/xhtml+xml into text/html if browser does not accept it
if request['HTTP_ACCEPT'].to_s !~ /application\/xhtml\+xml/ and ct =~ /application\/xhtml\+xml(.*)$/ then
response['Content-Type'] = "text/html#{$1}"
else
response['Content-Type'] = ct
end
else
response['Content-Type'] = 'text/plain'
end
end
if mstat then
response['ETag'] = makeETag(mstat)
response['Last-Modified'] = mstat.mtime.httpdate
end
rescue => ex
if ex.respond_to?(:errCode) then
# One of ours (Gorg::Status::HTTPStatus)
res.body = ex.html
res.status = ex.errCode
ex.header.each {|k,v| response[k]=v unless k =~ /status|cookie/i}
else
raise
# Some ruby exceptions occurred, make it a syserr
syserr = Gorg::Status::SysError.new
response.write(syserr.html(ex))
response.status = syserr.errCode
end
end
end
end
end
response.finish
end
end
end
|