passenger 5.0.21 → 5.0.22
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/CHANGELOG +38 -2
- data/CONTRIBUTORS +3 -0
- data/README.md +5 -1
- data/bin/passenger-status +2 -7
- data/build/agent.rb +2 -0
- data/build/cxx_dependency_map.rb +1464 -162
- data/build/node_tests.rb +1 -1
- data/build/packaging.rb +1 -1
- data/dev/ci/run_travis.sh +1 -1
- data/dev/vagrant/provision.sh +1 -1
- data/npm-shrinkwrap.json +635 -125
- data/package.json +1 -1
- data/resources/templates/standalone/config.erb +33 -161
- data/resources/templates/standalone/global.erb +15 -0
- data/resources/templates/standalone/http.erb +40 -0
- data/resources/templates/standalone/mass_deployment_default_server.erb +11 -0
- data/resources/templates/standalone/rails_asset_pipeline.erb +22 -0
- data/resources/templates/standalone/server.erb +58 -0
- data/src/agent/Core/ApiServer.h +37 -32
- data/src/agent/Core/ApplicationPool/BasicGroupInfo.h +1 -1
- data/src/agent/Core/ApplicationPool/BasicProcessInfo.h +6 -0
- data/src/agent/Core/ApplicationPool/Common.h +1 -1
- data/src/agent/Core/ApplicationPool/Group/OutOfBandWork.cpp +1 -1
- data/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +4 -0
- data/src/agent/Core/ApplicationPool/Implementation.cpp +2 -2
- data/src/agent/Core/ApplicationPool/Options.h +18 -1
- data/src/agent/Core/ApplicationPool/Pool.h +1 -1
- data/src/agent/Core/ApplicationPool/Pool/AnalyticsCollection.cpp +6 -6
- data/src/agent/Core/ApplicationPool/Pool/GeneralUtils.cpp +3 -3
- data/src/agent/Core/ApplicationPool/Pool/InitializationAndShutdown.cpp +1 -1
- data/src/agent/Core/ApplicationPool/Pool/Miscellaneous.cpp +6 -0
- data/src/agent/Core/ApplicationPool/Process.h +6 -1
- data/src/agent/Core/ApplicationPool/Socket.h +9 -12
- data/src/agent/Core/Controller.h +422 -0
- data/src/agent/Core/{RequestHandler → Controller}/AppResponse.h +2 -0
- data/src/agent/Core/{RequestHandler → Controller}/BufferBody.cpp +27 -5
- data/src/agent/Core/{RequestHandler → Controller}/CheckoutSession.cpp +61 -31
- data/src/agent/Core/{RequestHandler → Controller}/Client.h +5 -2
- data/src/agent/Core/{RequestHandler → Controller}/ForwardResponse.cpp +93 -42
- data/src/agent/Core/{RequestHandler → Controller}/Hooks.cpp +107 -60
- data/src/agent/Core/Controller/Implementation.cpp +38 -0
- data/src/agent/Core/{RequestHandler → Controller}/InitRequest.cpp +134 -80
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +165 -0
- data/src/agent/Core/{RequestHandler/Utils.cpp → Controller/InternalUtils.cpp} +49 -32
- data/src/agent/Core/Controller/Miscellaneous.cpp +116 -0
- data/src/agent/Core/{RequestHandler → Controller}/Request.h +6 -4
- data/src/agent/Core/{RequestHandler → Controller}/SendRequest.cpp +205 -130
- data/src/agent/Core/Controller/StateInspectionAndConfiguration.cpp +161 -0
- data/src/agent/Core/{RequestHandler → Controller}/TurboCaching.h +3 -0
- data/src/agent/Core/CoreMain.cpp +62 -51
- data/src/agent/Core/OptionParser.h +24 -0
- data/src/agent/Core/ResponseCache.h +5 -5
- data/src/agent/Core/SpawningKit/Config.h +2 -2
- data/src/agent/Core/SpawningKit/SmartSpawner.h +1 -1
- data/src/agent/Core/UnionStation/{Core.h → Context.h} +14 -18
- data/src/agent/Core/UnionStation/StopwatchLog.h +3 -2
- data/src/agent/Core/UnionStation/Transaction.h +7 -7
- data/src/agent/Shared/ApiServerUtils.h +9 -1
- data/src/agent/UstRouter/ApiServer.h +5 -2
- data/src/agent/UstRouter/Controller.h +27 -9
- data/src/agent/UstRouter/UstRouterMain.cpp +1 -0
- data/src/agent/Watchdog/ApiServer.h +5 -2
- data/src/apache2_module/ConfigurationCommands.cpp +7 -0
- data/src/apache2_module/ConfigurationFields.hpp +2 -0
- data/src/apache2_module/ConfigurationSetters.cpp +24 -0
- data/src/apache2_module/CreateDirConfig.cpp +1 -0
- data/src/apache2_module/Hooks.cpp +6 -5
- data/src/apache2_module/MergeDirConfig.cpp +7 -0
- data/src/apache2_module/SetHeaders.cpp +5 -0
- data/src/cxx_supportlib/Constants.h +5 -3
- data/src/cxx_supportlib/SafeLibev.h +2 -1
- data/src/cxx_supportlib/UnionStationFilterSupport.h +2 -1
- data/src/cxx_supportlib/Utils/ReleaseableScopedPointer.h +70 -0
- data/src/cxx_supportlib/vendor-modified/boost/libs/regex/src/regex_raw_buffer.cpp +6 -6
- data/src/helper-scripts/node-loader.js +59 -0
- data/src/nginx_module/CacheLocationConfig.c +48 -0
- data/src/nginx_module/ConfigurationCommands.c +20 -0
- data/src/nginx_module/ConfigurationFields.h +4 -0
- data/src/nginx_module/CreateLocationConfig.c +8 -0
- data/src/nginx_module/MergeLocationConfig.c +12 -0
- data/src/nodejs_supportlib/phusion_passenger/log_express.js +106 -0
- data/src/nodejs_supportlib/phusion_passenger/log_mongodb.js +203 -0
- data/src/nodejs_supportlib/phusion_passenger/ustreporter.js +227 -0
- data/src/nodejs_supportlib/phusion_passenger/ustrouter_connector.js +446 -0
- data/src/nodejs_supportlib/vendor-copy/codify/codify.js +44 -0
- data/src/nodejs_supportlib/vendor-copy/codify/package.json +29 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/context.js +200 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/glue.js +488 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/index.js +407 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/node_modules/shimmer/index.js +90 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/node_modules/shimmer/package.json +40 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/package.json +54 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/listener.js +160 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/node_modules/shimmer/index.js +90 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/node_modules/shimmer/package.json +40 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/package.json +46 -0
- data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/package.json +56 -0
- data/src/nodejs_supportlib/vendor-copy/network-byte-order/lib/index.js +102 -0
- data/src/nodejs_supportlib/vendor-copy/network-byte-order/package.json +51 -0
- data/src/nodejs_supportlib/vendor-copy/winston/LICENSE +19 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston.js +165 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/common.js +483 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config.js +62 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config/cli-config.js +35 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config/npm-config.js +27 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config/syslog-config.js +31 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/container.js +127 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/exception.js +56 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/logger.js +701 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports.js +34 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/console.js +128 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/daily-rotate-file.js +601 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/file.js +675 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/http.js +232 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/memory.js +89 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/transport.js +135 -0
- data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/webhook.js +146 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/LICENSE +19 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/lib/async.js +1283 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/package.json +66 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/support/sync-package-managers.js +53 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/MIT-LICENSE.txt +23 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/colors.js +176 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/custom/trap.js +45 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/custom/zalgo.js +104 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/extendStringPrototype.js +118 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/index.js +12 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/america.js +12 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/rainbow.js +13 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/random.js +8 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/zebra.js +5 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/styles.js +77 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/system/supports-colors.js +61 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/package.json +35 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/safe.js +9 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/themes/generic-logging.js +12 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/cycle/cycle.js +170 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/cycle/package.json +30 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/eyes/LICENSE +20 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/eyes/lib/eyes.js +236 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/eyes/package.json +42 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/isstream/LICENSE.md +11 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/isstream/isstream.js +27 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/isstream/package.json +42 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/pkginfo/LICENSE +19 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/pkginfo/lib/pkginfo.js +136 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/pkginfo/package.json +56 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/stack-trace/License +19 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/stack-trace/lib/stack-trace.js +111 -0
- data/src/nodejs_supportlib/vendor-copy/winston/node_modules/stack-trace/package.json +33 -0
- data/src/nodejs_supportlib/vendor-copy/winston/package.json +87 -0
- data/src/ruby_supportlib/phusion_passenger.rb +3 -4
- data/src/ruby_supportlib/phusion_passenger/admin_tools/instance.rb +19 -2
- data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +8 -0
- data/src/ruby_supportlib/phusion_passenger/config/list_instances_command.rb +2 -6
- data/src/ruby_supportlib/phusion_passenger/config/reopen_logs_command.rb +13 -0
- data/src/ruby_supportlib/phusion_passenger/config/restart_app_command.rb +3 -0
- data/src/ruby_supportlib/phusion_passenger/config/utils.rb +9 -7
- data/src/ruby_supportlib/phusion_passenger/config/validate_install_command.rb +8 -1
- data/src/ruby_supportlib/phusion_passenger/constants.rb +3 -1
- data/src/ruby_supportlib/phusion_passenger/native_support.rb +20 -4
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +8 -0
- data/src/ruby_supportlib/phusion_passenger/packaging.rb +1 -0
- data/src/ruby_supportlib/phusion_passenger/platform_info/apache_detector.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/platform_info/operating_system.rb +11 -4
- data/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +647 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/config_utils.rb +229 -15
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +35 -323
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +36 -12
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb +123 -14
- data/src/ruby_supportlib/phusion_passenger/standalone/status_command.rb +32 -17
- data/src/ruby_supportlib/phusion_passenger/standalone/stop_command.rb +32 -21
- data/src/ruby_supportlib/phusion_passenger/standalone/version_command.rb +5 -5
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/README.md +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/Rakefile +5 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core.rb +68 -24
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/api.rb +9 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/context.rb +9 -7
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter.rb +3 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter/basics.rb +8 -5
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/simple_json.rb +395 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/transaction.rb +10 -7
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/utils.rb +14 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/version_data.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml +4 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.example +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis-with-sudo +16 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/Gemfile +1 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/Gemfile.lock +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/README.md +1 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails.rb +44 -17
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/active_support_cache_subscriber.rb +16 -7
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/version_data.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/union_station_hooks_rails.gemspec +1 -1
- metadata +99 -16
- metadata.gz.asc +7 -7
- data/resources/oss-binaries.phusionpassenger.com.crt +0 -248
- data/src/agent/Core/RequestHandler.h +0 -471
@@ -1,5 +1,5 @@
|
|
1
1
|
# Phusion Passenger - https://www.phusionpassenger.com/
|
2
|
-
# Copyright (c) 2010-
|
2
|
+
# Copyright (c) 2010-2015 Phusion Holding B.V.
|
3
3
|
#
|
4
4
|
# "Passenger", "Phusion Passenger" and "Union Station" are registered
|
5
5
|
# trademarks of Phusion Holding B.V.
|
@@ -21,17 +21,17 @@
|
|
21
21
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
22
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
23
|
# THE SOFTWARE.
|
24
|
+
|
24
25
|
PhusionPassenger.require_passenger_lib 'standalone/command'
|
26
|
+
PhusionPassenger.require_passenger_lib 'config/about_command'
|
25
27
|
|
26
28
|
module PhusionPassenger
|
27
29
|
module Standalone
|
28
30
|
|
29
31
|
class VersionCommand < Command
|
30
32
|
def run
|
31
|
-
|
32
|
-
|
33
|
-
puts '"Passenger", "Phusion Passenger" and "Union Station" ' \
|
34
|
-
'are registered trademarks of Phusion Holding B.V.'
|
33
|
+
command = PhusionPassenger::Config::AboutCommand.new(['version'])
|
34
|
+
command.run
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -100,11 +100,11 @@ Please refer to [the API documentation website](http://www.rubydoc.info/github/p
|
|
100
100
|
|
101
101
|
## Legacy code
|
102
102
|
|
103
|
-
Before Passenger
|
103
|
+
Before Passenger 5.0.20, the Union Station setup instructions used to tell you to create a `config/initializers/passenger.rb` in which you call the following code:
|
104
104
|
|
105
105
|
PhusionPassenger.install_framework_extensions! if defined?(PhusionPassenger)
|
106
106
|
|
107
|
-
Since Passenger
|
107
|
+
Since Passenger 5.0.20, `PhusionPassenger.install_framework_extensions!` has become an alias for `UnionStationHooks.initialize!`, but the former is considered deprecated. Please replace the above code with:
|
108
108
|
|
109
109
|
if defined?(UnionStationHooks)
|
110
110
|
UnionStationHooks.initialize!
|
@@ -42,7 +42,11 @@ task "spec:travis" do
|
|
42
42
|
if !ENV['PASSENGER_CONFIG']
|
43
43
|
Rake::Task['travis:install_passenger'].invoke
|
44
44
|
end
|
45
|
-
|
45
|
+
if ENV['TRAVIS_WITH_SUDO']
|
46
|
+
sh 'cp ruby_versions.yml.travis-with-sudo ruby_versions.yml'
|
47
|
+
else
|
48
|
+
sh 'cp ruby_versions.yml.travis ruby_versions.yml'
|
49
|
+
end
|
46
50
|
Rake::Task['spec'].invoke
|
47
51
|
end
|
48
52
|
|
@@ -81,6 +81,7 @@ end
|
|
81
81
|
# # object, you can log to Union Station information about the current
|
82
82
|
# # request.
|
83
83
|
# reporter = env['union_station_hooks']
|
84
|
+
# # -OR- (if you don't have access to the Rack env):
|
84
85
|
# reporter = Thread.current[:union_station_hooks]
|
85
86
|
#
|
86
87
|
# # The reporter object may be nil because of various error conditions,
|
@@ -272,34 +273,35 @@ module UnionStationHooks
|
|
272
273
|
|
273
274
|
# Called by Passenger after loading the application, to check whether or
|
274
275
|
# not the application developer forgot to call
|
275
|
-
# {UnionStationHooks.initialize!}
|
276
|
+
# {UnionStationHooks.initialize!}. If so, it logs the problem and
|
277
|
+
# initializes now.
|
276
278
|
#
|
277
279
|
# @private
|
278
|
-
# @raise RuntimeError
|
279
280
|
def check_initialized
|
280
|
-
if should_initialize?
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
" if defined?(UnionStationHooks)\n" \
|
299
|
-
" UnionStationHooks.initialize!\n" \
|
300
|
-
" end\n\n"
|
301
|
-
end
|
281
|
+
return if !should_initialize? || initialized?
|
282
|
+
return if !config.fetch(:check_initialized, true)
|
283
|
+
|
284
|
+
if defined?(::Rails)
|
285
|
+
message = 'The Union Station hooks are not initialized. Please ensure ' \
|
286
|
+
'that you have an initializer file ' \
|
287
|
+
'`config/initializers/union_station.rb` in which you call ' \
|
288
|
+
"this:\n\n" \
|
289
|
+
" if defined?(UnionStationHooks)\n" \
|
290
|
+
" UnionStationHooks.initialize!\n" \
|
291
|
+
" end"
|
292
|
+
else
|
293
|
+
message = 'The Union Station hooks are not initialized. Please ensure ' \
|
294
|
+
'that the following code is called during application ' \
|
295
|
+
"startup:\n\n" \
|
296
|
+
" if defined?(UnionStationHooks)\n" \
|
297
|
+
" UnionStationHooks.initialize!\n" \
|
298
|
+
" end"
|
302
299
|
end
|
300
|
+
|
301
|
+
STDERR.puts(" *** WARNING: #{message}")
|
302
|
+
@@config[:initialize_from_check] = true
|
303
|
+
initialize!
|
304
|
+
report_internal_information('HOOKS_NOT_INITIALIZED', message)
|
303
305
|
end
|
304
306
|
|
305
307
|
def now
|
@@ -355,6 +357,48 @@ module UnionStationHooks
|
|
355
357
|
"Union Station hooks configuration option required: #{key}"
|
356
358
|
end
|
357
359
|
end
|
360
|
+
|
361
|
+
def require_simple_json
|
362
|
+
if defined?(PhusionPassenger)
|
363
|
+
begin
|
364
|
+
PhusionPassenger.require_passenger_lib('utils/json')
|
365
|
+
UnionStationHooks.const_set(:SimpleJSON, PhusionPassenger::Utils)
|
366
|
+
rescue LoadError
|
367
|
+
end
|
368
|
+
end
|
369
|
+
if !defined?(UnionStationHooks::SimpleJSON)
|
370
|
+
require_lib('simple_json')
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
def report_internal_information(type, message, data = nil)
|
375
|
+
data ||= {}
|
376
|
+
data[:app_type] ||= :ruby
|
377
|
+
if defined?(::Rails)
|
378
|
+
data[:framework_type] = :rails
|
379
|
+
end
|
380
|
+
|
381
|
+
if defined?(PhusionPassenger)
|
382
|
+
data[:app_server] = {
|
383
|
+
:id => :passenger,
|
384
|
+
:version => PhusionPassenger::VERSION_STRING
|
385
|
+
}
|
386
|
+
end
|
387
|
+
|
388
|
+
body = SimpleJSON::JSON.generate(
|
389
|
+
:type => type,
|
390
|
+
:message => message,
|
391
|
+
:data => data
|
392
|
+
)
|
393
|
+
|
394
|
+
transaction = context.new_transaction(app_group_name,
|
395
|
+
:internal_information, key)
|
396
|
+
begin
|
397
|
+
transaction.message(body)
|
398
|
+
ensure
|
399
|
+
transaction.close
|
400
|
+
end
|
401
|
+
end
|
358
402
|
end
|
359
403
|
end
|
360
404
|
|
@@ -68,7 +68,14 @@ module UnionStationHooks
|
|
68
68
|
txn_id = rack_env['PASSENGER_TXN_ID']
|
69
69
|
return nil if !txn_id
|
70
70
|
|
71
|
-
|
71
|
+
# Workaround for Ruby < 2.1 support where there is no function for querying
|
72
|
+
# the monotonic time.
|
73
|
+
delta_monotonic = rack_env['PASSENGER_DELTA_MONOTONIC']
|
74
|
+
if delta_monotonic
|
75
|
+
delta_monotonic = delta_monotonic.to_i
|
76
|
+
end
|
77
|
+
|
78
|
+
reporter = RequestReporter.new(context, txn_id, app_group_name, key, delta_monotonic)
|
72
79
|
return if reporter.null?
|
73
80
|
|
74
81
|
rack_env['union_station_hooks'] = reporter
|
@@ -186,6 +193,7 @@ module UnionStationHooks
|
|
186
193
|
if @@config[:debug]
|
187
194
|
UnionStationHooks::Log.debugging = true
|
188
195
|
end
|
196
|
+
require_simple_json
|
189
197
|
@@initialized = true
|
190
198
|
end
|
191
199
|
end
|
@@ -59,10 +59,8 @@ module UnionStationHooks
|
|
59
59
|
@server_address = ust_router_address
|
60
60
|
@username = username
|
61
61
|
@password = password
|
62
|
-
if node_name &&
|
63
|
-
@node_name =
|
64
|
-
else
|
65
|
-
@node_name = `hostname`.strip
|
62
|
+
if node_name && node_name.empty?
|
63
|
+
@node_name = nil
|
66
64
|
end
|
67
65
|
|
68
66
|
# This mutex protects the following instance variables, but
|
@@ -175,7 +173,7 @@ module UnionStationHooks
|
|
175
173
|
end
|
176
174
|
end
|
177
175
|
|
178
|
-
def continue_transaction(txn_id, group_name, category, key)
|
176
|
+
def continue_transaction(txn_id, group_name, category, key, delta_monotonic = 0)
|
179
177
|
if !@server_address
|
180
178
|
return Transaction.new(nil, nil)
|
181
179
|
elsif !txn_id || txn_id.empty?
|
@@ -211,7 +209,7 @@ module UnionStationHooks
|
|
211
209
|
Utils.encoded_timestamp,
|
212
210
|
key,
|
213
211
|
true)
|
214
|
-
return Transaction.new(@connection, txn_id)
|
212
|
+
return Transaction.new(@connection, txn_id, delta_monotonic)
|
215
213
|
rescue SystemCallError, IOError
|
216
214
|
@connection.disconnect
|
217
215
|
UnionStationHooks::Log.warn(
|
@@ -271,7 +269,11 @@ module UnionStationHooks
|
|
271
269
|
end
|
272
270
|
|
273
271
|
def handshake_initialization(channel)
|
274
|
-
|
272
|
+
if @node_name
|
273
|
+
channel.write('init', @node_name)
|
274
|
+
else
|
275
|
+
channel.write('init')
|
276
|
+
end
|
275
277
|
process_ust_router_reply(channel,
|
276
278
|
'UstRouter client initialization error')
|
277
279
|
end
|
@@ -102,7 +102,7 @@ module UnionStationHooks
|
|
102
102
|
# in the {RequestReporter class description}.
|
103
103
|
#
|
104
104
|
# @api private
|
105
|
-
def initialize(context, txn_id, app_group_name, key)
|
105
|
+
def initialize(context, txn_id, app_group_name, key, delta_monotonic)
|
106
106
|
raise ArgumentError, 'Transaction ID must be given' if txn_id.nil?
|
107
107
|
raise ArgumentError, 'App group name must be given' if app_group_name.nil?
|
108
108
|
raise ArgumentError, 'Union Station key must be given' if key.nil?
|
@@ -110,6 +110,7 @@ module UnionStationHooks
|
|
110
110
|
@txn_id = txn_id
|
111
111
|
@app_group_name = app_group_name
|
112
112
|
@key = key
|
113
|
+
@delta_monotonic = delta_monotonic
|
113
114
|
@transaction = continue_transaction
|
114
115
|
@next_view_rendering_number = 1
|
115
116
|
@next_user_activity_number = 1
|
@@ -138,7 +139,7 @@ module UnionStationHooks
|
|
138
139
|
|
139
140
|
def continue_transaction
|
140
141
|
@context.continue_transaction(@txn_id, @app_group_name,
|
141
|
-
:requests, @key)
|
142
|
+
:requests, @key, @delta_monotonic)
|
142
143
|
end
|
143
144
|
|
144
145
|
# Called when one of the methods return early upon detecting null
|
@@ -145,11 +145,12 @@ module UnionStationHooks
|
|
145
145
|
# This is automatically called by Passenger's Rack handler.
|
146
146
|
#
|
147
147
|
# @private
|
148
|
-
# @return An ID to be passed later to {#log_writing_rack_body_end}
|
148
|
+
# @return An ID to be passed later to {#log_writing_rack_body_end}, or nil
|
149
|
+
# on error.
|
149
150
|
def log_writing_rack_body_begin
|
150
151
|
return do_nothing_on_null(:log_writing_rack_body_begin) if null?
|
151
152
|
@transaction.log_activity_begin('app writing out response body')
|
152
|
-
nil
|
153
|
+
:writing_rack_body # Random non-nil ID
|
153
154
|
end
|
154
155
|
|
155
156
|
# Logs that the application server is done writing out the Rack
|
@@ -162,8 +163,8 @@ module UnionStationHooks
|
|
162
163
|
# @private
|
163
164
|
def log_writing_rack_body_end(id)
|
164
165
|
return do_nothing_on_null(:log_writing_rack_body_end) if null?
|
166
|
+
return if id.nil?
|
165
167
|
@transaction.log_activity_end('app writing out response body')
|
166
|
-
nil
|
167
168
|
end
|
168
169
|
|
169
170
|
# Logs that the application server is about to call `#close` on the
|
@@ -175,11 +176,12 @@ module UnionStationHooks
|
|
175
176
|
# This is automatically called by Passenger's Rack handler.
|
176
177
|
#
|
177
178
|
# @private
|
178
|
-
# @return An ID to be passed later to {#log_closing_rack_body_end}
|
179
|
+
# @return An ID to be passed later to {#log_closing_rack_body_end}, or nil
|
180
|
+
# on error.
|
179
181
|
def log_closing_rack_body_begin
|
180
182
|
return do_nothing_on_null(:log_closing_rack_body_begin) if null?
|
181
183
|
@transaction.log_activity_begin('closing rack body object')
|
182
|
-
nil
|
184
|
+
:closing_rack_body # Random non-nil ID
|
183
185
|
end
|
184
186
|
|
185
187
|
# Logs that the application server is done calling `#close` on the
|
@@ -190,6 +192,7 @@ module UnionStationHooks
|
|
190
192
|
# @private
|
191
193
|
def log_closing_rack_body_end(id)
|
192
194
|
return do_nothing_on_null(:log_closing_rack_body_end) if null?
|
195
|
+
return if id.nil?
|
193
196
|
@transaction.log_activity_end('closing rack body object')
|
194
197
|
end
|
195
198
|
end
|
@@ -0,0 +1,395 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
## Stupid small pure Ruby JSON parser & generator.
|
4
|
+
#
|
5
|
+
# Copyright © 2013 Mislav Marohnić
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
8
|
+
# software and associated documentation files (the “Software”), to deal in the Software
|
9
|
+
# without restriction, including without limitation the rights to use, copy, modify,
|
10
|
+
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
# permit persons to whom the Software is furnished to do so, subject to the following
|
12
|
+
# conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all copies or
|
15
|
+
# substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
18
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
19
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
|
21
|
+
# OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
# We use this in Phusion Passenger at places where we cannot depend on the JSON
|
25
|
+
# gem being available, for example in 'passenger start' before the RuntimeInstaller
|
26
|
+
# has run.
|
27
|
+
|
28
|
+
require 'strscan'
|
29
|
+
require 'forwardable'
|
30
|
+
|
31
|
+
module UnionStationHooks
|
32
|
+
module SimpleJSON
|
33
|
+
|
34
|
+
# Usage:
|
35
|
+
#
|
36
|
+
# JSON.parse(json_string) => Array/Hash
|
37
|
+
# JSON.generate(object) => json string
|
38
|
+
#
|
39
|
+
# Run tests by executing this file directly. Pipe standard input to the script to have it
|
40
|
+
# parsed as JSON and to display the result in Ruby.
|
41
|
+
#
|
42
|
+
class JSON
|
43
|
+
def self.parse(data) new(data).parse end
|
44
|
+
|
45
|
+
WSP = /(\s|\/\/.*?\n|\/\*.*?\*\/)+/m
|
46
|
+
OBJ = /[{\[]/; HEN = /\}/; AEN = /\]/
|
47
|
+
COL = /\s*:\s*/; KEY = /\s*,\s*/
|
48
|
+
NUM = /-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/
|
49
|
+
BOL = /true|false/; NUL = /null/
|
50
|
+
|
51
|
+
extend Forwardable
|
52
|
+
|
53
|
+
attr_reader :scanner
|
54
|
+
alias_method :s, :scanner
|
55
|
+
def_delegators :scanner, :scan, :matched
|
56
|
+
private :s, :scan, :matched
|
57
|
+
|
58
|
+
def initialize data
|
59
|
+
@scanner = StringScanner.new data.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
def parse
|
63
|
+
space
|
64
|
+
object
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def space() scan WSP end
|
70
|
+
|
71
|
+
def endkey() scan(KEY) or space end
|
72
|
+
|
73
|
+
def object
|
74
|
+
matched == '{' ? hash : array if scan(OBJ)
|
75
|
+
end
|
76
|
+
|
77
|
+
def value
|
78
|
+
object or string or
|
79
|
+
scan(NUL) ? nil :
|
80
|
+
scan(BOL) ? matched.size == 4:
|
81
|
+
scan(NUM) ? eval(matched) :
|
82
|
+
error
|
83
|
+
end
|
84
|
+
|
85
|
+
def hash
|
86
|
+
obj = {}
|
87
|
+
space
|
88
|
+
repeat_until(HEN) do
|
89
|
+
space
|
90
|
+
k = string
|
91
|
+
scan(COL)
|
92
|
+
obj[k] = value
|
93
|
+
endkey
|
94
|
+
end
|
95
|
+
obj
|
96
|
+
end
|
97
|
+
|
98
|
+
def array
|
99
|
+
ary = []
|
100
|
+
space
|
101
|
+
repeat_until(AEN) do
|
102
|
+
space
|
103
|
+
ary << value
|
104
|
+
endkey
|
105
|
+
end
|
106
|
+
ary
|
107
|
+
end
|
108
|
+
|
109
|
+
SPEC = {'b' => "\b", 'f' => "\f", 'n' => "\n", 'r' => "\r", 't' => "\t"}
|
110
|
+
UNI = 'u'; CODE = /[a-fA-F0-9]{4}/
|
111
|
+
STR = /"/; STE = '"'
|
112
|
+
ESC = '\\'
|
113
|
+
|
114
|
+
def string
|
115
|
+
if scan(STR)
|
116
|
+
str, esc = '', false
|
117
|
+
while c = s.getch
|
118
|
+
if esc
|
119
|
+
str << (c == UNI ? (s.scan(CODE) || error).to_i(16).chr : SPEC[c] || c)
|
120
|
+
esc = false
|
121
|
+
else
|
122
|
+
case c
|
123
|
+
when ESC then esc = true
|
124
|
+
when STE then break
|
125
|
+
else str << c
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
str
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def error
|
134
|
+
raise "parse error at: #{scan(/.{1,20}/m).inspect}"
|
135
|
+
end
|
136
|
+
|
137
|
+
def repeat_until reg
|
138
|
+
until scan(reg)
|
139
|
+
pos = s.pos
|
140
|
+
yield
|
141
|
+
error unless s.pos > pos
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
module Generator
|
146
|
+
def generate(obj)
|
147
|
+
raise ArgumentError unless obj.is_a? Array or obj.is_a? Hash
|
148
|
+
generate_type(obj)
|
149
|
+
end
|
150
|
+
alias dump generate
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def generate_type(obj)
|
155
|
+
type = obj.is_a?(Numeric) ? :Numeric : obj.class.name
|
156
|
+
begin send(:"generate_#{type}", obj)
|
157
|
+
rescue NoMethodError; raise ArgumentError, "can't serialize #{type}"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
ESC_MAP = Hash.new {|h,k| k }.update \
|
162
|
+
"\r" => 'r',
|
163
|
+
"\n" => 'n',
|
164
|
+
"\f" => 'f',
|
165
|
+
"\t" => 't',
|
166
|
+
"\b" => 'b'
|
167
|
+
|
168
|
+
def quote(str) %("#{str}") end
|
169
|
+
|
170
|
+
def generate_String(str)
|
171
|
+
quote str.gsub(/[\r\n\f\t\b"\\]/) { "\\#{ESC_MAP[$&]}"}
|
172
|
+
end
|
173
|
+
|
174
|
+
def generate_simple(obj) obj.inspect end
|
175
|
+
alias generate_Numeric generate_simple
|
176
|
+
alias generate_TrueClass generate_simple
|
177
|
+
alias generate_FalseClass generate_simple
|
178
|
+
|
179
|
+
def generate_Symbol(sym) generate_String(sym.to_s) end
|
180
|
+
|
181
|
+
def generate_Time(time)
|
182
|
+
quote time.strftime(time.utc? ? "%F %T UTC" : "%F %T %z")
|
183
|
+
end
|
184
|
+
def generate_Date(date) quote date.to_s end
|
185
|
+
|
186
|
+
def generate_NilClass(*) 'null' end
|
187
|
+
|
188
|
+
def generate_Array(ary) '[%s]' % ary.map {|o| generate_type(o) }.join(', ') end
|
189
|
+
|
190
|
+
def generate_Hash(hash)
|
191
|
+
'{%s}' % hash.map { |key, value|
|
192
|
+
"#{generate_String(key.to_s)}: #{generate_type(value)}"
|
193
|
+
}.join(', ')
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
extend Generator
|
198
|
+
end
|
199
|
+
|
200
|
+
if __FILE__ == $0
|
201
|
+
if !$stdin.tty?
|
202
|
+
data = JSON.parse $stdin.read
|
203
|
+
require 'pp'
|
204
|
+
pp data
|
205
|
+
else
|
206
|
+
require 'test/unit'
|
207
|
+
require 'date'
|
208
|
+
class ParserTest < Test::Unit::TestCase
|
209
|
+
PARSED = JSON.parse DATA.read
|
210
|
+
def parsed() PARSED end
|
211
|
+
def parse_string(str) JSON.parse(%(["#{str}"]).gsub('\\\\', '\\')).first end
|
212
|
+
def test_string
|
213
|
+
assert_equal "Pagination library for \"Rails 3\", Sinatra, Merb, DataMapper, and more",
|
214
|
+
parsed['head']['repository']['description']
|
215
|
+
end
|
216
|
+
def test_string_specials
|
217
|
+
assert_equal "\r\n\t\f\b", parse_string('\r\n\t\f\b')
|
218
|
+
assert_equal "aA", parse_string('\u0061\u0041')
|
219
|
+
assert_equal "\e", parse_string('\u001B')
|
220
|
+
assert_equal "xyz", parse_string('\x\y\z')
|
221
|
+
assert_equal '"\\/', parse_string('\"\\\\\\/')
|
222
|
+
assert_equal 'no #{interpolation}', parse_string('no #{interpolation}')
|
223
|
+
end
|
224
|
+
def test_hash
|
225
|
+
assert_equal %w[label ref repository sha user], parsed['head'].keys.sort
|
226
|
+
end
|
227
|
+
def test_number
|
228
|
+
assert_equal 124.3e2, parsed['head']['repository']['size']
|
229
|
+
end
|
230
|
+
def test_bool
|
231
|
+
assert_equal true, parsed['head']['repository']['fork']
|
232
|
+
assert_equal false, parsed['head']['repository']['private']
|
233
|
+
end
|
234
|
+
def test_nil
|
235
|
+
assert_nil parsed['head']['user']['company']
|
236
|
+
end
|
237
|
+
def test_array
|
238
|
+
assert_equal ["4438f", {"a" => "b"}], parsed['head']['sha']
|
239
|
+
end
|
240
|
+
def test_invalid
|
241
|
+
assert_raises(RuntimeError) { JSON.parse %({) }
|
242
|
+
assert_raises(RuntimeError) { JSON.parse %({ "foo": }) }
|
243
|
+
assert_raises(RuntimeError) { JSON.parse %([ "foo": "bar" ]) }
|
244
|
+
assert_raises(RuntimeError) { JSON.parse %([ ~"foo" ]) }
|
245
|
+
assert_raises(RuntimeError) { JSON.parse %([ "foo ]) }
|
246
|
+
assert_raises(RuntimeError) { JSON.parse %([ "foo\\" ]) }
|
247
|
+
assert_raises(RuntimeError) { JSON.parse %([ "foo\\uabGd" ]) }
|
248
|
+
end
|
249
|
+
def test_single_line_comments
|
250
|
+
source = %Q{
|
251
|
+
// comment before document
|
252
|
+
{
|
253
|
+
// comment
|
254
|
+
"foo": "1",
|
255
|
+
"bar": "2",
|
256
|
+
// another comment
|
257
|
+
"baz": "3",
|
258
|
+
"array": [
|
259
|
+
// comment inside array
|
260
|
+
1, 2, 3
|
261
|
+
// comment at end of array
|
262
|
+
]
|
263
|
+
// comment at end of hash
|
264
|
+
}
|
265
|
+
// comment after document
|
266
|
+
}
|
267
|
+
doc = { "foo" => "1", "bar" => "2", "baz" => "3", "array" => [1, 2, 3] }
|
268
|
+
assert_equal(doc, JSON.parse(source))
|
269
|
+
end
|
270
|
+
def test_multi_line_comments
|
271
|
+
source = %Q{
|
272
|
+
/* comment before
|
273
|
+
* document */
|
274
|
+
{
|
275
|
+
/* comment */
|
276
|
+
"foo": "1",
|
277
|
+
"bar": "2",
|
278
|
+
/* another
|
279
|
+
comment
|
280
|
+
*/
|
281
|
+
"baz": "3",
|
282
|
+
"array": [
|
283
|
+
/* comment inside array */
|
284
|
+
1, 2, 3,
|
285
|
+
4, /* comment inside an array */ 5,
|
286
|
+
/*
|
287
|
+
// "nested" comments
|
288
|
+
{ "faux json": "inside comment" }
|
289
|
+
*/
|
290
|
+
6, 7
|
291
|
+
/**
|
292
|
+
* comment at end of array
|
293
|
+
*/
|
294
|
+
]
|
295
|
+
/**************************
|
296
|
+
comment at end of hash
|
297
|
+
**************************/
|
298
|
+
}
|
299
|
+
/* comment after
|
300
|
+
document */
|
301
|
+
}
|
302
|
+
doc = { "foo" => "1", "bar" => "2", "baz" => "3", "array" => [1, 2, 3, 4, 5, 6, 7] }
|
303
|
+
assert_equal(doc, JSON.parse(source))
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
class GeneratorTest < Test::Unit::TestCase
|
308
|
+
def generate(obj) JSON.generate(obj) end
|
309
|
+
def test_array
|
310
|
+
assert_equal %([1, 2, 3]), generate([1, 2, 3])
|
311
|
+
end
|
312
|
+
def test_bool
|
313
|
+
assert_equal %([true, false]), generate([true, false])
|
314
|
+
end
|
315
|
+
def test_null
|
316
|
+
assert_equal %([null]), generate([nil])
|
317
|
+
end
|
318
|
+
def test_string
|
319
|
+
assert_equal %(["abc\\n123"]), generate(["abc\n123"])
|
320
|
+
end
|
321
|
+
def test_string_unicode
|
322
|
+
assert_equal %(["ć\\"č\\nž\\tš\\\\đ"]), generate(["ć\"č\nž\tš\\đ"])
|
323
|
+
end
|
324
|
+
def test_time
|
325
|
+
time = Time.utc(2012, 04, 19, 1, 2, 3)
|
326
|
+
assert_equal %(["2012-04-19 01:02:03 UTC"]), generate([time])
|
327
|
+
end
|
328
|
+
def test_date
|
329
|
+
time = Date.new(2012, 04, 19)
|
330
|
+
assert_equal %(["2012-04-19"]), generate([time])
|
331
|
+
end
|
332
|
+
def test_symbol
|
333
|
+
assert_equal %(["abc"]), generate([:abc])
|
334
|
+
end
|
335
|
+
def test_hash
|
336
|
+
json = generate(:abc => 123, 123 => 'abc')
|
337
|
+
assert_match /^\{/, json
|
338
|
+
assert_match /\}$/, json
|
339
|
+
assert_equal [%("123": "abc"), %("abc": 123)], json[1...-1].split(', ').sort
|
340
|
+
end
|
341
|
+
def test_nested_structure
|
342
|
+
json = generate(:hash => {1=>2}, :array => [1,2])
|
343
|
+
assert json.include?(%("hash": {"1": 2}))
|
344
|
+
assert json.include?(%("array": [1, 2]))
|
345
|
+
end
|
346
|
+
def test_invalid_json
|
347
|
+
assert_raises(ArgumentError) { generate("abc") }
|
348
|
+
end
|
349
|
+
def test_invalid_object
|
350
|
+
err = assert_raises(ArgumentError) { generate("a" => Object.new) }
|
351
|
+
assert_equal "can't serialize Object", err.message
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
end # module SimpleJSON
|
358
|
+
end # module UnionStationHooks
|
359
|
+
|
360
|
+
__END__
|
361
|
+
{
|
362
|
+
"head": {
|
363
|
+
"ref": "master",
|
364
|
+
"repository": {
|
365
|
+
"forks": 0,
|
366
|
+
"integrate_branch": "rails3",
|
367
|
+
"watchers": 1,
|
368
|
+
"language": "Ruby",
|
369
|
+
"description": "Pagination library for \"Rails 3\", Sinatra, Merb, DataMapper, and more",
|
370
|
+
"has_downloads": true,
|
371
|
+
"fork": true,
|
372
|
+
"created_at": "2011/10/24 03:20:48 -0700",
|
373
|
+
"homepage": "http://github.com/mislav/will_paginate/wikis",
|
374
|
+
"size": 124.3e2,
|
375
|
+
"private": false,
|
376
|
+
"has_wiki": true,
|
377
|
+
"name": "will_paginate",
|
378
|
+
"owner": "dbackeus",
|
379
|
+
"url": "https://github.com/dbackeus/will_paginate",
|
380
|
+
"has_issues": false,
|
381
|
+
"open_issues": 0,
|
382
|
+
"pushed_at": "2011/10/25 05:44:05 -0700"
|
383
|
+
},
|
384
|
+
"label": "dbackeus:master",
|
385
|
+
"sha": ["4438f", { "a" : "b" }],
|
386
|
+
"user": {
|
387
|
+
"name": "David Backeus",
|
388
|
+
"company": null,
|
389
|
+
"gravatar_id": "ebe96524f5db9e92188f0542dc9d1d1a",
|
390
|
+
"location": "Stockholm (Sweden)",
|
391
|
+
"type": "User",
|
392
|
+
"login": "dbackeus"
|
393
|
+
}
|
394
|
+
}
|
395
|
+
}
|