unicorn-maintained 6.2.0

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.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.CHANGELOG.old +25 -0
  3. data/.document +28 -0
  4. data/.gitattributes +5 -0
  5. data/.gitignore +25 -0
  6. data/.mailmap +26 -0
  7. data/.manifest +149 -0
  8. data/.olddoc.yml +25 -0
  9. data/Application_Timeouts +77 -0
  10. data/CONTRIBUTORS +39 -0
  11. data/COPYING +674 -0
  12. data/DESIGN +99 -0
  13. data/Documentation/.gitignore +3 -0
  14. data/Documentation/unicorn.1 +222 -0
  15. data/Documentation/unicorn_rails.1 +207 -0
  16. data/FAQ +70 -0
  17. data/GIT-VERSION-FILE +1 -0
  18. data/GIT-VERSION-GEN +39 -0
  19. data/GNUmakefile +317 -0
  20. data/HACKING +112 -0
  21. data/ISSUES +102 -0
  22. data/KNOWN_ISSUES +79 -0
  23. data/LATEST +1 -0
  24. data/LICENSE +67 -0
  25. data/Links +58 -0
  26. data/NEWS +1 -0
  27. data/PHILOSOPHY +139 -0
  28. data/README +156 -0
  29. data/Rakefile +16 -0
  30. data/SIGNALS +123 -0
  31. data/Sandbox +104 -0
  32. data/TODO +3 -0
  33. data/TUNING +119 -0
  34. data/archive/.gitignore +3 -0
  35. data/archive/slrnpull.conf +4 -0
  36. data/bin/unicorn +128 -0
  37. data/bin/unicorn_rails +209 -0
  38. data/examples/big_app_gc.rb +2 -0
  39. data/examples/echo.ru +26 -0
  40. data/examples/init.sh +102 -0
  41. data/examples/logger_mp_safe.rb +25 -0
  42. data/examples/logrotate.conf +44 -0
  43. data/examples/nginx.conf +156 -0
  44. data/examples/unicorn.conf.minimal.rb +13 -0
  45. data/examples/unicorn.conf.rb +110 -0
  46. data/examples/unicorn.socket +11 -0
  47. data/examples/unicorn@.service +40 -0
  48. data/ext/unicorn_http/CFLAGS +13 -0
  49. data/ext/unicorn_http/c_util.h +116 -0
  50. data/ext/unicorn_http/common_field_optimization.h +128 -0
  51. data/ext/unicorn_http/epollexclusive.h +128 -0
  52. data/ext/unicorn_http/ext_help.h +38 -0
  53. data/ext/unicorn_http/extconf.rb +39 -0
  54. data/ext/unicorn_http/global_variables.h +97 -0
  55. data/ext/unicorn_http/httpdate.c +91 -0
  56. data/ext/unicorn_http/unicorn_http.c +4334 -0
  57. data/ext/unicorn_http/unicorn_http.rl +1040 -0
  58. data/ext/unicorn_http/unicorn_http_common.rl +76 -0
  59. data/lib/unicorn/app/old_rails/static.rb +59 -0
  60. data/lib/unicorn/app/old_rails.rb +35 -0
  61. data/lib/unicorn/cgi_wrapper.rb +147 -0
  62. data/lib/unicorn/configurator.rb +748 -0
  63. data/lib/unicorn/const.rb +21 -0
  64. data/lib/unicorn/http_request.rb +201 -0
  65. data/lib/unicorn/http_response.rb +93 -0
  66. data/lib/unicorn/http_server.rb +859 -0
  67. data/lib/unicorn/launcher.rb +62 -0
  68. data/lib/unicorn/oob_gc.rb +81 -0
  69. data/lib/unicorn/preread_input.rb +33 -0
  70. data/lib/unicorn/select_waiter.rb +6 -0
  71. data/lib/unicorn/socket_helper.rb +185 -0
  72. data/lib/unicorn/stream_input.rb +151 -0
  73. data/lib/unicorn/tee_input.rb +131 -0
  74. data/lib/unicorn/tmpio.rb +33 -0
  75. data/lib/unicorn/util.rb +90 -0
  76. data/lib/unicorn/version.rb +1 -0
  77. data/lib/unicorn/worker.rb +165 -0
  78. data/lib/unicorn.rb +136 -0
  79. data/man/man1/unicorn.1 +222 -0
  80. data/man/man1/unicorn_rails.1 +207 -0
  81. data/setup.rb +1586 -0
  82. data/t/.gitignore +4 -0
  83. data/t/GNUmakefile +5 -0
  84. data/t/README +49 -0
  85. data/t/active-unix-socket.t +117 -0
  86. data/t/bin/unused_listen +40 -0
  87. data/t/broken-app.ru +12 -0
  88. data/t/client_body_buffer_size.ru +14 -0
  89. data/t/client_body_buffer_size.t +80 -0
  90. data/t/detach.ru +11 -0
  91. data/t/env.ru +3 -0
  92. data/t/fails-rack-lint.ru +5 -0
  93. data/t/heartbeat-timeout.ru +12 -0
  94. data/t/heartbeat-timeout.t +62 -0
  95. data/t/integration.ru +115 -0
  96. data/t/integration.t +356 -0
  97. data/t/lib.perl +258 -0
  98. data/t/listener_names.ru +4 -0
  99. data/t/my-tap-lib.sh +201 -0
  100. data/t/oob_gc.ru +17 -0
  101. data/t/oob_gc_path.ru +17 -0
  102. data/t/pid.ru +3 -0
  103. data/t/preread_input.ru +22 -0
  104. data/t/reload-bad-config.t +54 -0
  105. data/t/reopen-logs.ru +13 -0
  106. data/t/reopen-logs.t +39 -0
  107. data/t/t0008-back_out_of_upgrade.sh +110 -0
  108. data/t/t0009-broken-app.sh +56 -0
  109. data/t/t0010-reap-logging.sh +55 -0
  110. data/t/t0012-reload-empty-config.sh +86 -0
  111. data/t/t0013-rewindable-input-false.sh +24 -0
  112. data/t/t0013.ru +12 -0
  113. data/t/t0014-rewindable-input-true.sh +24 -0
  114. data/t/t0014.ru +12 -0
  115. data/t/t0015-configurator-internals.sh +25 -0
  116. data/t/t0020-at_exit-handler.sh +49 -0
  117. data/t/t0021-process_detach.sh +29 -0
  118. data/t/t0022-listener_names-preload_app.sh +32 -0
  119. data/t/t0300-no-default-middleware.sh +20 -0
  120. data/t/t0301-no-default-middleware-ignored-in-config.sh +25 -0
  121. data/t/t0301.ru +13 -0
  122. data/t/t9001-oob_gc.sh +47 -0
  123. data/t/t9002-oob_gc-path.sh +75 -0
  124. data/t/test-lib.sh +125 -0
  125. data/t/winch_ttin.t +67 -0
  126. data/t/working_directory.t +94 -0
  127. data/test/aggregate.rb +15 -0
  128. data/test/benchmark/README +60 -0
  129. data/test/benchmark/dd.ru +18 -0
  130. data/test/benchmark/ddstream.ru +50 -0
  131. data/test/benchmark/readinput.ru +40 -0
  132. data/test/benchmark/stack.ru +8 -0
  133. data/test/benchmark/uconnect.perl +66 -0
  134. data/test/exec/README +5 -0
  135. data/test/exec/test_exec.rb +1029 -0
  136. data/test/test_helper.rb +306 -0
  137. data/test/unit/test_ccc.rb +91 -0
  138. data/test/unit/test_configurator.rb +175 -0
  139. data/test/unit/test_droplet.rb +28 -0
  140. data/test/unit/test_http_parser.rb +884 -0
  141. data/test/unit/test_http_parser_ng.rb +714 -0
  142. data/test/unit/test_request.rb +169 -0
  143. data/test/unit/test_server.rb +244 -0
  144. data/test/unit/test_signals.rb +188 -0
  145. data/test/unit/test_socket_helper.rb +159 -0
  146. data/test/unit/test_stream_input.rb +210 -0
  147. data/test/unit/test_tee_input.rb +303 -0
  148. data/test/unit/test_util.rb +131 -0
  149. data/test/unit/test_waiter.rb +34 -0
  150. data/unicorn.gemspec +48 -0
  151. metadata +275 -0
@@ -0,0 +1,76 @@
1
+ %%{
2
+
3
+ machine unicorn_http_common;
4
+
5
+ #### HTTP PROTOCOL GRAMMAR
6
+ # line endings
7
+ CRLF = ("\r\n" | "\n");
8
+
9
+ # character types
10
+ CTL = (cntrl | 127);
11
+ safe = ("$" | "-" | "_" | ".");
12
+ extra = ("!" | "*" | "'" | "(" | ")" | ",");
13
+ reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
14
+ sorta_safe = ("\"" | "<" | ">");
15
+ unsafe = (CTL | " " | "#" | "%" | sorta_safe);
16
+ national = any -- (alpha | digit | reserved | extra | safe | unsafe);
17
+ unreserved = (alpha | digit | safe | extra | national);
18
+ escape = ("%" xdigit xdigit);
19
+ uchar = (unreserved | escape | sorta_safe);
20
+ pchar = (uchar | ":" | "@" | "&" | "=" | "+");
21
+ tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
22
+ lws = (" " | "\t");
23
+ content = ((any -- CTL) | lws);
24
+
25
+ # elements
26
+ token = (ascii -- (CTL | tspecials));
27
+
28
+ # URI schemes and absolute paths
29
+ scheme = ( "http"i ("s"i)? ) $downcase_char >mark %scheme;
30
+ hostname = ((alnum | "-" | "." | "_")+ | ("[" (":" | xdigit)+ "]"));
31
+ host_with_port = (hostname (":" digit*)?) >mark %host;
32
+ userinfo = ((unreserved | escape | ";" | ":" | "&" | "=" | "+")+ "@")*;
33
+
34
+ path = ( pchar+ ( "/" pchar* )* ) ;
35
+ query = ( uchar | reserved )* %query_string ;
36
+ param = ( pchar | "/" )* ;
37
+ params = ( param ( ";" param )* ) ;
38
+ rel_path = (path? (";" params)? %request_path) ("?" %start_query query)?;
39
+ absolute_path = ( "/"+ rel_path );
40
+ path_uri = absolute_path > mark %request_uri;
41
+ Absolute_URI = (scheme "://" userinfo host_with_port path_uri);
42
+
43
+ Request_URI = ((absolute_path | "*") >mark %request_uri) | Absolute_URI;
44
+ Fragment = ( uchar | reserved )* >mark %fragment;
45
+ Method = (token){1,20} >mark %request_method;
46
+ GetOnly = "GET" >mark %request_method;
47
+
48
+ http_number = ( digit+ "." digit+ ) ;
49
+ HTTP_Version = ( "HTTP/" http_number ) >mark %http_version ;
50
+ Request_Line = ( Method " " Request_URI ("#" Fragment){0,1} " " HTTP_Version CRLF ) ;
51
+
52
+ field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
53
+
54
+ field_value = content* >start_value %write_value;
55
+
56
+ value_cont = lws+ content* >start_value %write_cont_value;
57
+
58
+ message_header = ((field_name ":" lws* field_value)|value_cont) :> CRLF;
59
+ chunk_ext_val = token*;
60
+ chunk_ext_name = token*;
61
+ chunk_extension = ( ";" " "* chunk_ext_name ("=" chunk_ext_val)? )*;
62
+ last_chunk = "0"+ chunk_extension CRLF;
63
+ chunk_size = (xdigit* [1-9a-fA-F] xdigit*) $add_to_chunk_size;
64
+ chunk_end = CRLF;
65
+ chunk_body = any >skip_chunk_data;
66
+ chunk_begin = chunk_size chunk_extension CRLF;
67
+ chunk = chunk_begin chunk_body chunk_end;
68
+ ChunkedBody := chunk* last_chunk @end_chunked_body;
69
+ Trailers := (message_header)* CRLF @end_trailers;
70
+
71
+ FullRequest = Request_Line (message_header)* CRLF @header_done;
72
+ SimpleRequest = GetOnly " " Request_URI ("#"Fragment){0,1} CRLF @header_done;
73
+
74
+ main := FullRequest | SimpleRequest;
75
+
76
+ }%%
@@ -0,0 +1,59 @@
1
+ # -*- encoding: binary -*-
2
+ # :enddoc:
3
+ # This code is based on the original Rails handler in Mongrel
4
+ # Copyright (c) 2005 Zed A. Shaw
5
+ # Copyright (c) 2009 Eric Wong
6
+ # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
7
+ # the GPLv3
8
+
9
+ # Static file handler for Rails < 2.3. This handler is only provided
10
+ # as a convenience for developers. Performance-minded deployments should
11
+ # use nginx (or similar) for serving static files.
12
+ #
13
+ # This supports page caching directly and will try to resolve a
14
+ # request in the following order:
15
+ #
16
+ # * If the requested exact PATH_INFO exists as a file then serve it.
17
+ # * If it exists at PATH_INFO+rest_operator+".html" exists
18
+ # then serve that.
19
+ #
20
+ # This means that if you are using page caching it will actually work
21
+ # with Unicorn and you should see a decent speed boost (but not as
22
+ # fast as if you use a static server like nginx).
23
+ class Unicorn::App::OldRails::Static < Struct.new(:app, :root, :file_server)
24
+ FILE_METHODS = { 'GET' => true, 'HEAD' => true }
25
+
26
+ # avoid allocating new strings for hash lookups
27
+ REQUEST_METHOD = 'REQUEST_METHOD'
28
+ REQUEST_URI = 'REQUEST_URI'
29
+ PATH_INFO = 'PATH_INFO'
30
+
31
+ def initialize(app)
32
+ self.app = app
33
+ self.root = "#{::RAILS_ROOT}/public"
34
+ self.file_server = ::Rack::File.new(root)
35
+ end
36
+
37
+ def call(env)
38
+ # short circuit this ASAP if serving non-file methods
39
+ FILE_METHODS.include?(env[REQUEST_METHOD]) or return app.call(env)
40
+
41
+ # first try the path as-is
42
+ path_info = env[PATH_INFO].chomp("/")
43
+ if File.file?("#{root}/#{::Rack::Utils.unescape(path_info)}")
44
+ # File exists as-is so serve it up
45
+ env[PATH_INFO] = path_info
46
+ return file_server.call(env)
47
+ end
48
+
49
+ # then try the cached version:
50
+ path_info << ActionController::Base.page_cache_extension
51
+
52
+ if File.file?("#{root}/#{::Rack::Utils.unescape(path_info)}")
53
+ env[PATH_INFO] = path_info
54
+ return file_server.call(env)
55
+ end
56
+
57
+ app.call(env) # call OldRails
58
+ end
59
+ end if defined?(Unicorn::App::OldRails)
@@ -0,0 +1,35 @@
1
+ # -*- encoding: binary -*-
2
+
3
+ # :enddoc:
4
+ # This code is based on the original Rails handler in Mongrel
5
+ # Copyright (c) 2005 Zed A. Shaw
6
+ # Copyright (c) 2009 Eric Wong
7
+ # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
8
+ # the GPLv2+ (GPLv3+ preferred)
9
+ # Additional work donated by contributors. See CONTRIBUTORS for more info.
10
+ require 'unicorn/cgi_wrapper'
11
+ require 'dispatcher'
12
+
13
+ module Unicorn; module App; end; end
14
+
15
+ # Implements a handler that can run Rails.
16
+ class Unicorn::App::OldRails
17
+
18
+ autoload :Static, "unicorn/app/old_rails/static"
19
+
20
+ def call(env)
21
+ cgi = Unicorn::CGIWrapper.new(env)
22
+ begin
23
+ Dispatcher.dispatch(cgi,
24
+ ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS,
25
+ cgi.body)
26
+ rescue => e
27
+ err = env['rack.errors']
28
+ err.write("#{e} #{e.message}\n")
29
+ e.backtrace.each { |line| err.write("#{line}\n") }
30
+ end
31
+ cgi.out # finalize the response
32
+ cgi.rack_response
33
+ end
34
+
35
+ end
@@ -0,0 +1,147 @@
1
+ # -*- encoding: binary -*-
2
+
3
+ # :enddoc:
4
+ # This code is based on the original CGIWrapper from Mongrel
5
+ # Copyright (c) 2005 Zed A. Shaw
6
+ # Copyright (c) 2009 Eric Wong
7
+ # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
8
+ # the GPLv2+ (GPLv3+ preferred)
9
+ #
10
+ # Additional work donated by contributors. See CONTRIBUTORS for more info.
11
+
12
+ require 'cgi'
13
+
14
+ module Unicorn; end
15
+
16
+ # The beginning of a complete wrapper around Unicorn's internal HTTP
17
+ # processing system but maintaining the original Ruby CGI module. Use
18
+ # this only as a crutch to get existing CGI based systems working. It
19
+ # should handle everything, but please notify us if you see special
20
+ # warnings. This work is still very alpha so we need testers to help
21
+ # work out the various corner cases.
22
+ class Unicorn::CGIWrapper < ::CGI
23
+ undef_method :env_table
24
+ attr_reader :env_table
25
+ attr_reader :body
26
+
27
+ # these are stripped out of any keys passed to CGIWrapper.header function
28
+ NPH = 'nph'.freeze # Completely ignored, Unicorn outputs the date regardless
29
+ CONNECTION = 'connection'.freeze # Completely ignored. Why is CGI doing this?
30
+ CHARSET = 'charset'.freeze # this gets appended to Content-Type
31
+ COOKIE = 'cookie'.freeze # maps (Hash,Array,String) to "Set-Cookie" headers
32
+ STATUS = 'status'.freeze # stored as @status
33
+ Status = 'Status'.freeze # code + human-readable text, Rails sets this
34
+
35
+ # some of these are common strings, but this is the only module
36
+ # using them and the reason they're not in Unicorn::Const
37
+ SET_COOKIE = 'Set-Cookie'.freeze
38
+ CONTENT_TYPE = 'Content-Type'.freeze
39
+ CONTENT_LENGTH = 'Content-Length'.freeze # this is NOT Const::CONTENT_LENGTH
40
+ RACK_INPUT = 'rack.input'.freeze
41
+ RACK_ERRORS = 'rack.errors'.freeze
42
+
43
+ # this maps CGI header names to HTTP header names
44
+ HEADER_MAP = {
45
+ 'status' => Status,
46
+ 'type' => CONTENT_TYPE,
47
+ 'server' => 'Server'.freeze,
48
+ 'language' => 'Content-Language'.freeze,
49
+ 'expires' => 'Expires'.freeze,
50
+ 'length' => CONTENT_LENGTH,
51
+ }
52
+
53
+ # Takes an a Rackable environment, plus any additional CGI.new
54
+ # arguments These are used internally to create a wrapper around the
55
+ # real CGI while maintaining Rack/Unicorn's view of the world. This
56
+ # this will NOT deal well with large responses that take up a lot of
57
+ # memory, but neither does the CGI nor the original CGIWrapper from
58
+ # Mongrel...
59
+ def initialize(rack_env, *args)
60
+ @env_table = rack_env
61
+ @status = nil
62
+ @head = {}
63
+ @headv = Hash.new { |hash,key| hash[key] = [] }
64
+ @body = StringIO.new("")
65
+ super(*args)
66
+ end
67
+
68
+ # finalizes the response in a way Rack applications would expect
69
+ def rack_response
70
+ # @head[CONTENT_LENGTH] ||= @body.size
71
+ @headv[SET_COOKIE].concat(@output_cookies) if @output_cookies
72
+ @headv.each_pair do |key,value|
73
+ @head[key] ||= value.join("\n") unless value.empty?
74
+ end
75
+
76
+ # Capitalized "Status:", with human-readable status code (e.g. "200 OK")
77
+ @status ||= @head.delete(Status)
78
+
79
+ [ @status || 500, @head, [ @body.string ] ]
80
+ end
81
+
82
+ # The header is typically called to send back the header. In our case we
83
+ # collect it into a hash for later usage. This can be called multiple
84
+ # times to set different cookies.
85
+ def header(options = "text/html")
86
+ # if they pass in a string then just write the Content-Type
87
+ if String === options
88
+ @head[CONTENT_TYPE] ||= options
89
+ else
90
+ HEADER_MAP.each_pair do |from, to|
91
+ from = options.delete(from) or next
92
+ @head[to] = from.to_s
93
+ end
94
+
95
+ @head[CONTENT_TYPE] ||= "text/html"
96
+ if charset = options.delete(CHARSET)
97
+ @head[CONTENT_TYPE] << "; charset=#{charset}"
98
+ end
99
+
100
+ # lots of ways to set cookies
101
+ if cookie = options.delete(COOKIE)
102
+ set_cookies = @headv[SET_COOKIE]
103
+ case cookie
104
+ when Array
105
+ cookie.each { |c| set_cookies << c.to_s }
106
+ when Hash
107
+ cookie.each_value { |c| set_cookies << c.to_s }
108
+ else
109
+ set_cookies << cookie.to_s
110
+ end
111
+ end
112
+ @status ||= options.delete(STATUS) # all lower-case
113
+
114
+ # drop the keys we don't want anymore
115
+ options.delete(NPH)
116
+ options.delete(CONNECTION)
117
+
118
+ # finally, set the rest of the headers as-is, allowing duplicates
119
+ options.each_pair { |k,v| @headv[k] << v }
120
+ end
121
+
122
+ # doing this fakes out the cgi library to think the headers are empty
123
+ # we then do the real headers in the out function call later
124
+ ""
125
+ end
126
+
127
+ # The dumb thing is people can call header or this or both and in
128
+ # any order. So, we just reuse header and then finalize the
129
+ # HttpResponse the right way. This will have no effect if called
130
+ # the second time if the first "outputted" anything.
131
+ def out(options = "text/html")
132
+ header(options)
133
+ @body.size == 0 or return
134
+ @body << yield if block_given?
135
+ end
136
+
137
+ # Used to wrap the normal stdinput variable used inside CGI.
138
+ def stdinput
139
+ @env_table[RACK_INPUT]
140
+ end
141
+
142
+ # return a pointer to the StringIO body since it's STDOUT-like
143
+ def stdoutput
144
+ @body
145
+ end
146
+
147
+ end