Module: Spider::ControllerMixins::HTTPMixin

Included in:
StaticContent
Defined in:
lib/spiderfw/controller/mixins/http_mixin.rb

Defined Under Namespace

Modules: ClassMethods Classes: HTTPStatus

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.base_urlString

Returns the base URL to which the installation responds.

Returns:

  • (String)

    the base URL to which the installation responds



119
120
121
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 119

def self.base_url
    HTTPMixin.reverse_proxy_mapping("")
end

.included(klass) ⇒ Object



11
12
13
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 11

def self.included(klass)
    klass.extend(ClassMethods)
end

.output_charset(val = nil) ⇒ String

Sets or returns the charset for the controller

Parameters:

  • The (String|nil)

    charset

Returns:

  • (String)

    The charset in use



76
77
78
79
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 76

def self.output_charset(val=nil)
    @output_charset = val if val
    @output_charset || Spider.conf.get('http.charset')
end

.reverse_proxy_mapping(url_path) ⇒ String

Takes a url path that the framework would accept, and transforms it into the url path the webserver would send, given the settings in http.proxy_mapping

Parameters:

  • url_path (Strint)

Returns:

  • (String)

    The transformed url path



34
35
36
37
38
39
40
41
42
43
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 34

def self.reverse_proxy_mapping(url_path)
    return '' unless url_path
    if (maps = Spider.conf.get('http.proxy_mapping'))
        maps.each do |proxy, spider|
            spider ||= ''
            return proxy + url_path[spider.length..-1] if (spider == "" || url_path[0..spider.length-1] == spider)
        end
    end
    return url_path
end

Instance Method Details

#base_urlString

Returns the base URL to which the installation responds.

Returns:

  • (String)

    the base URL to which the installation responds



124
125
126
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 124

def base_url
    HTTPMixin.base_url
end

#before(action = '', *arguments) ⇒ Object

Parameters:



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 102

def before(action='', *arguments)
    return super if self.is_a?(Spider::Widget)
     # FIXME: the Spider::Widget check
    # is needed because with _wt the widget executes without action
    # Redirect to url + slash if controller is called without action
    dest = HTTPMixin.reverse_proxy_mapping(@request.env['PATH_INFO'])
    if (action == '' && dest[-1].chr != '/' && !self.is_a?(Spider::Widget))
        dest = dest += '/'
        if (@request.env['QUERY_STRING'] && !@request.env['QUERY_STRING'].empty?)
            dest += '?'+@request.env['QUERY_STRING']
        end
        redirect(dest)
    end
    super
end

#challenge_basic_authObject



153
154
155
156
157
158
159
160
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 153

def challenge_basic_auth()
    realm ||= http_auth_realm
    realm ||= 'Secure Area'
    @response.headers["WWW-Authenticate"] = "Basic realm=\"#{realm}\""
    @response.status = Spider::HTTP::UNAUTHORIZED
    render('errors/unauthorized') if self.is_a?(Visual)
    done
end

#challenge_digest_auth(realm = nil) ⇒ Object



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 170

def challenge_digest_auth(realm=nil)
    realm ||= http_auth_realm
    realm ||= 'Secure Area'
    
    # nonce
    now = "%012d" % @request.request_time
    pk  = Digest::MD5.hexdigest("#{now}:#{digest_instance_key}")[0,32]
    nonce = [now + ":" + pk].pack("m*").chop # it has 60 length of chars.
    
    opaque = [UUIDTools::UUID.random_create.to_s].pack("m*").chop
    header = "Digest realm=\"#{realm}\", qop=\"auth\", nonce=\"#{nonce}\", opaque=\"#{opaque}\""
    @response.headers['WWW-Authenticate'] = header
    @response.status = Spider::HTTP::UNAUTHORIZED
    done
end

#check_basic_auth(authenticator) ⇒ Object



162
163
164
165
166
167
168
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 162

def check_basic_auth(authenticator)
    if (@request.env['HTTP_AUTHORIZATION'] =~ /Basic (.+)/)
        pair = Base64.decode64($1)
        user, pass = pair.split(':')
        return authenticator.authenticate(:login, {:username => user, :password => pass})
    end
end

#check_digest_auth(authenticator) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 186

def check_digest_auth(authenticator)
    # TODO: implement opaque, auth-int
    if (@request.env['HTTP_AUTHORIZATION'] =~ /Digest (.+)/)
        parts = $1.split(',')
        params = {}
        parts.each do |p|
            k, v = p.strip.split('=')
            v = v.sub(/^"+/, '').sub(/"+$/, '')
            params[k.downcase] = v
        end
        ['username', 'realm', 'nonce', 'uri', 'cnonce', 'qop', 'nc', 'response', 'opaque'].each{ |k| return unless params[k] }
        user = params['username']
        user = $1 if params['username'] =~ /.+\\(.+)/ # FIXME: Temp fix for windows sending DOMAIN/User
        pub_time, pk = params['nonce'].unpack("m*")[0].split(":", 2)
        return unless pub_time && pk
        return unless Digest::MD5.hexdigest("#{pub_time}:#{digest_instance_key}")[0,32] == pk
        diff_time = @request.request_time.to_i - pub_time.to_i
        return if diff_time < 0
        return if diff_time > Spider.conf.get('http.nonce_life')
        user = authenticator.load(:username => user, :realm => params['realm'])
        return unless user
        ha1 = user.ha1
        return unless ha1
        ha2 = Digest::MD5.hexdigest("#{@request.env['REQUEST_METHOD']}:#{params['uri']}")
        if (params['qop'] == "auth" || params['qop'] == "auth-int")
            param2 = ['nonce', 'nc', 'cnonce', 'qop'].map{|key| params[key] }.join(':')
            response = Digest::MD5.hexdigest([ha1, param2, ha2].join(':'))
        else
            response = Digest::MD5.hexdigest([ha1, params['nonce'], ha2].join(':'))
        end
        # FIXME: temporaneamente disabilitato controllo perché con il login DOMINIO/Utente non corrisponde
        #return unless response == params['response']
        return user
    end
end

#content_type(ct) ⇒ String

Sets a Content type

Parameters:

  • Content (String|Symbol)

    type, or a symbol representing it (Can be :text, :json, :js, :javascript, :html, :xml)

Returns:

  • (String)

    The value of the “Content-Type” header



85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 85

def content_type(ct)
    if ct.is_a?(Symbol)
        ct = {
            :text       => 'text/plain',
            :json       => 'application/json',
            :js         => 'application/x-javascript',
            :javascript => 'application/x-javascript',
            :html       => 'text/html',
            :xml        => 'text/xml'
        }[ct]
    end
    @response.headers["Content-Type"] = "#{ct};charset=utf-8"
end

#digest_instance_keyObject



222
223
224
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 222

def digest_instance_key
    Digest::MD5.hexdigest("#{Mac.addr}:plaw15x857m4p671")
end

#http_auth_realmObject



232
233
234
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 232

def http_auth_realm
    @http_auth_realm || self.class.http_auth_realm
end

#http_auth_realm=(val) ⇒ Object



228
229
230
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 228

def http_auth_realm=(val)
    @http_auth_realm = val
end

#prepare_scene(scene) ⇒ Object



129
130
131
132
133
134
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 129

def prepare_scene(scene)
    scene = super
    scene.base_url = base_url
    scene.controller[:request_url] = request_url
    return scene
end

#redirect(url, code = Spider::HTTP::SEE_OTHER) ⇒ Object

Sets the headers to redirect the browser to the given url, and calls Spider::Controller#done to terminate the execution of the Controller chain

Parameters:

  • url (String)
  • code (Fixnum) (defaults to: Spider::HTTP::SEE_OTHER)

    HTTP status to send

Returns:

  • void



20
21
22
23
24
25
26
27
28
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 20

def redirect(url, code=Spider::HTTP::SEE_OTHER)
    debug "REDIRECTING TO #{url}"
    @request.session.persist if @request.session # It might be too late afterwards
    @response.status = code
    @response.headers["Location"] = url
    @response.headers.delete("Content-Type")
    @response.headers.delete("Set-Cookie")
    done
end

#request_full_urlString

Returns the request_url with query params, if any.

Returns:

  • (String)

    the request_url with query params, if any



65
66
67
68
69
70
71
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 65

def request_full_url
    url = request_url
    if (@request.env['QUERY_STRING'] && !@request.env['QUERY_STRING'].empty?)
        url += '?'+@request.env['QUERY_STRING']
    end
    return url
end

#request_pathString

 Returns the http path used to call the current controller & action. Reverses any proxy mappings to the Controller#request_path.

Returns:



48
49
50
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 48

def request_path
    HTTPMixin.reverse_proxy_mapping(super)
end

#request_urlString

Returns the request_path prefixed with http:// and the current host.

Returns:

  • (String)

    the request_path prefixed with http:// and the current host.



53
54
55
56
57
58
59
60
61
62
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 53

def request_url
    return request_path unless @request.env['HTTP_HOST']
    #'http://'[email protected]['HTTP_HOST']+request_path  vecchia versione con problemi con https
    if @request.env["HTTPS"] == "on" || @request.env['HTTP_X_FORWARDED_PROTO'] == 'https' # uso anche il parametro HTTP_X_FORWARDED_PROTO per reverse_proxy con ssl_offloading
        u = "https://#{@request.env['HTTP_HOST']}#{request_path}"
    else
        u = "http://#{@request.env['HTTP_HOST']}#{request_path}"
    end
    u
end

#try_rescue(exc) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/spiderfw/controller/mixins/http_mixin.rb', line 136

def try_rescue(exc)
    if (exc.is_a?(Spider::Controller::NotFound))
        @response.status = Spider::HTTP::NOT_FOUND
    elsif (exc.is_a?(Spider::Controller::BadRequest))
        @response.status = Spider::HTTP::BAD_REQUEST
    elsif (exc.is_a?(Spider::Controller::Forbidden))
        @response.status = Spider::HTTP::FORBIDDEN
    elsif (exc.is_a?(HTTPStatus))
        @response.status = exc.code
        Spider::Logger.debug("Sending HTTP status #{exc.code}")
        return
    else
        @response.status = Spider::HTTP::INTERNAL_SERVER_ERROR
    end
    super
end