Class: Strelka::App

Inherits:
Mongrel2::Handler
  • Object
show all
Extended by:
Configurability, Loggability, Discovery, MethodUtilities, PluginLoader
Includes:
Constants, ResponseHelpers
Defined in:
lib/strelka/app.rb

Overview

The Strelka HTTP application base class.

Defined Under Namespace

Modules: Auth, Errors, Filters, Negotiation, Parameters, RestResources, Routing, Sessions, Templating

Instance Attribute Summary

Attributes included from PluginLoader

#loaded_plugins, #plugin_path_prefix, #plugins_installed_from

Class Method Summary collapse

Instance Method Summary collapse

Methods included from PluginLoader

application_stack, dump_application_stack, extended, inherited, install_plugins, load_plugin, new, plugins, plugins_installed?, register_plugin

Methods included from MethodUtilities

attr_predicate, attr_predicate_accessor, singleton_attr_accessor, singleton_attr_reader, singleton_attr_writer, singleton_method_alias, singleton_predicate_accessor, singleton_predicate_reader

Methods included from Discovery

add_inherited_class, app_discovery_files, discover_data_dirs, discovered_apps, discovered_classes, inherited, load, load_file, loading_file, loading_file, register_app, register_apps

Methods included from ResponseHelpers

finish_with

Constructor Details

#initializeApp

Dump the application stack when a new instance is created.



114
115
116
117
# File 'lib/strelka/app.rb', line 114

def initialize( * )
	self.class.dump_application_stack
	super
end

Class Method Details

.default_app_instanceObject

Return an instance of the App configured for the handler in the currently-loaded Mongrel2 config that corresponds to the #default_appid.



91
92
93
94
# File 'lib/strelka/app.rb', line 91

def self::default_app_instance
	appid = self.default_appid
	return self.app_instance_for( appid )
end

.default_appidObject

Calculate a default application ID for the class based on either its ID constant or its name and return it.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/strelka/app.rb', line 72

def self::default_appid
	self.log.info "Looking up appid for %p" % [ self.class ]
	appid = nil

	if self.const_defined?( :ID )
		appid = self.const_get( :ID )
		self.log.info "  app has an ID: %p" % [ appid ]
	else
		appid = ( self.name || "anonymous#{self.object_id}" ).downcase
		appid.gsub!( /[^[:alnum:]]+/, '-' )
		self.log.info "  deriving one from the class name: %p" % [ appid ]
	end

	return appid
end

.default_type(newtype = nil) ⇒ Object

Get/set the Content-type of requests that don't set one. Leaving this unset will leave the Content-type unset.



103
104
105
106
# File 'lib/strelka/app.rb', line 103

def self::default_type( newtype=nil )
	@default_type = newtype if newtype
	return @default_type
end

.devmode?Boolean

Returns true if the application has been configured to run in 'developer mode'. Developer mode is mostly informational by default (it just makes logging more verbose), but plugins and such might alter their behavior based on this setting.

Returns:

  • (Boolean)


55
56
57
# File 'lib/strelka/app.rb', line 55

def self::devmode?
	return @devmode
end

.run(appid = nil) ⇒ Object

Overridden from Mongrel2::Handler -- use the value returned from .default_appid if one is not specified.



63
64
65
66
67
# File 'lib/strelka/app.rb', line 63

def self::run( appid=nil )
	appid ||= self.default_appid
	self.log.info "Starting up with appid %p." % [ appid ]
	super( appid )
end

Instance Method Details

#handle(request) ⇒ Object

The main Mongrel2 entrypoint -- accept Strelka::Requests and return Strelka::Responses.



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
# File 'lib/strelka/app.rb', line 135

def handle( request )
	response = nil

	# Dispatch the request after allowing plugins to to their thing
	status_info = catch( :finish ) do
		self.log.debug "Starting dispatch of request %p" % [ request ]

		# Run fixup hooks on the request
		request = self.fixup_request( request )
		self.log.debug "  done with request fixup"
		response = self.handle_request( request )
		self.log.debug "  done with handler"
		response = self.fixup_response( response )
		self.log.debug "  done with response fixup"

		nil # rvalue for the catch
	end

	# Status response
	if status_info
		self.log.debug "Preparing a status response: %p" % [ status_info ]
		return self.prepare_status_response( request, status_info )
	end

	return response
rescue => err
	self.log.error "%s: %s %s" % [ err.class.name, err.message, err.backtrace.first ]
	err.backtrace[ 1..-1 ].each {|frame| self.log.debug('  ' + frame) }

	status_info = { :status => HTTP::SERVER_ERROR, :message => 'internal server error' }
	return self.prepare_status_response( request, status_info )
end

#handle_async_upload_start(request) ⇒ Object

Handle uploads larger than the server's configured limit with a 413: Request Entity Too Large before dropping the connection.



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/strelka/app.rb', line 171

def handle_async_upload_start( request )
	status_info = { :status => HTTP::REQUEST_ENTITY_TOO_LARGE, :message => 'Request too large.' }
	response = self.prepare_status_response( request, status_info )
	response.headers.connection = 'close'
	self.conn.reply( response )

	explanation = <<~END_OF_MESSAGE
	If you wish to handle requests like this, either set your server's
	'limits.content_length' setting to a higher value than %{content_length}, or override
	#handle_async_upload_start.
	END_OF_MESSAGE

	self.log.warn "Async upload from %s dropped." % [ request.remote_ip ]
	self.log.info( explanation % {content_length: request.content_length} )

	self.conn.reply_close( request )

	return nil
end

#runObject

Run the app -- overriden to set the process name to something interesting.



125
126
127
128
129
130
# File 'lib/strelka/app.rb', line 125

def run
	procname = "%s %s: %p %s" % [ RUBY_ENGINE, RUBY_VERSION, self.class, self.conn ]
	$0 = procname

	super
end

#subclassesObject

The Hash of Strelka::App subclasses, keyed by the Pathname of the file they were loaded from, or nil if they weren't loaded via ::load.



49
# File 'lib/strelka/app.rb', line 49

singleton_attr_reader :subclasses