Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,40 @@
- Refactor logging for more sane defaults
- Remove long-deprecated configuration and API functionality

For most users this should be a minor upgrade; as long as not depending on deprecated functionality or JRuby 9.x.
For most users this should be a minor upgrade; as long as you do not depend on functionality deprecated within
JRuby-Rack 1.2.x, EOL JRuby or EOL Rails versions.

Breaking compatibility changes
- Drop support for JRuby 9.x (and thus Java < 21)
- Drop support for Rails < 7.2
- Drop JMS support

Breaking behavioral changes
- Change context listener to throw by default in case of an exception during initialization
- Change rails context listener to assume a thread-safe application by default
- Rack is no longer vendored inside the jar, so applications must ensure rack is provided via bundler or GEM_PATH

Breaking Java API changes
- Drop JMS support
Breaking configuration capability changes
- Drop `jruby.rack.jruby.version` and `jruby.rack.rack.release` keys from rack `env` Hash
- Drop deprecated and undocumented jruby-rack 1.0 backwards compat properties `jruby.runtime.timeout.sec`, `jruby.runtime.initializer.threads`, `jruby.init.serial`, `jruby.rack.request.size.threshold.bytes`
- Drop deprecated `jruby.rack.ignore.env` property, replaced long ago by `jruby.runtime.env` and optional `jruby.runtime.env.rubyopt`
- Drop deprecated `jruby.rack.filter.*` properties, replaced long ago by init parameters `addsHtmlToPathInfo` and `verifiesHtmlResource`
- Drop handling of `# rack.version` magic comments inside `config.ru` files, replaced by bundler or user-managed `GEM_PATH`

Breaking Java API changes (only relevant for users extending the Java API)
- Drop unnecessary `jruby.compat.version` and `RackConfig.getCompatVersion()` API
- Drop deprecated `org.jruby.rack.RackInput` alias for `org.jruby.rack.ext.Input` class
- Drop/rename deprecated `RackConfig` and `ServletRackEnvironment` API methods per their earlier comments
- Drop deprecated `RackLogger` string (`level`) constants
- Custom `RackLogger` implementations must accept `CharSequence` rather than `String` to allow `RubyString` passthrough
- Rename deprecated `JRuby::Rack::ServletLog` to `JRuby::Rack::ErrorLog` for clarity, despite usage only in servlet contexts.

Breaking Ruby API changes
Breaking Ruby API changes (only relevant for users extending the Ruby API)
- Drop deprecated `JRuby::Rack::RailsFileSystemLayout` alias for `JRuby::Rack::FileSystemLayout`
- Drop deprecated `JRuby::Rack::Errors` alias for `JRuby::Rack::ErrorApp`
- Drop deprecated `Rack::Handler::Servlet::Env` and `Rack::Handler::Servlet::LazyEnv` types (replaced by `DefaultEnv`)
- Drop deprecated setting of global `$servlet_context` variable during embedded usage (replaced by `JRuby::Rack.context`)

Breaking configuration capability changes
- Drop `jruby.rack.jruby.version` and `jruby.rack.rack.release` keys from rack `env` Hash
- Drop deprecated and undocumented jruby-rack 1.0 backwards compat properties `jruby.runtime.timeout.sec`, `jruby.runtime.initializer.threads`, `jruby.init.serial`, `jruby.rack.request.size.threshold.bytes`
- Drop deprecated `jruby.rack.ignore.env` property, replaced long ago by `jruby.runtime.env` and optional `jruby.runtime.env.rubyopt`
- Drop deprecated `jruby.rack.filter.*` properties, replaced long ago by init parameters `addsHtmlToPathInfo` and `verifiesHtmlResource`

## 1.2.8

- Improve isolation and bundler version/CLI boot issues with more opinionated boot process (#461)
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
source 'https://rubygems.org'

group :default do
if rack_version = ENV['RACK_VERSION']
if (rack_version = ENV['RACK_VERSION'])
gem 'rack', rack_version
else
gem 'rack', '~> 2.2.24'
Expand Down
22 changes: 4 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,24 +267,10 @@ Ruby environment before booting the application. You can create a file called
These files, if found, will be evaluated before booting the Rack environment,
allowing you to set environment variables, load scripts, etc.

For plain Rack applications, JRuby-Rack also supports a magic comment to solve
the "rackup" chicken-egg problem (you need Rack's builder loaded before loading
the `config.ru`, yet you may want to setup the gem version from within the rackup
file). As we ship with the Rack gem bundled, otherwise when executing the
provided `config.ru` the bundled (latest) version of Rack will get loaded.

Use `rack.version` to specify the Rack gem version to be loaded before rackup :

```ruby
# encoding: UTF-8
# rack.version: ~>2.2.10 (before code is loaded gem '~>2.2.10' will be called)
```

Or the equivalent of doing `bundle exec rackup ...` if you're using Bundler :

```ruby
# rack.version: bundler (require 'bundler'; Bundler.setup; before loading the script)
```
JRuby-Rack does not vendor Rack - the application is expected to provide it, just like
with other Ruby web servers. For applications depending on `jruby-rack` via jar (rather than gem),
this means having `rack` in the `Gemfile` (usually implied by the web framework);
or available on the application's gem path.

## Logging

Expand Down
43 changes: 4 additions & 39 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,53 +51,18 @@ task(:test_prepare => ['target/classes', 'target/test-classes']) do
sh "./mvnw -ntp -Dstyle.color=always -Djruby.compat.artifact=jruby-complete test-compile"
end

desc "Unpack the rack gem"
task :unpack_gem => "target" do |t|
target = File.expand_path(t.prerequisites.first)
rack_gemfile = Gem.loaded_specs['rack'].cache_file
unless uptodate?("#{target}/vendor/rack.rb", [__FILE__, rack_gemfile])
mkdir_p "target/vendor"
require 'rubygems/installer'
rack_dir = File.basename(rack_gemfile).sub(/\.gem$/, '')
Gem::Package.new(rack_gemfile).extract_files("#{target}/#{rack_dir}")
File.open("#{target}/vendor/rack.rb", "w") do |f|
f << "dir = File.dirname(__FILE__)\n"
f << "if dir =~ /.jar!/ && dir !~ /^file:/\n"
f << " $LOAD_PATH.unshift 'file:' + dir + '/#{rack_dir}'\n"
f << "else\n"
f << " $LOAD_PATH.unshift dir + '/#{rack_dir}'\n"
f << "end\n"
f << "require 'rack'"
end
end
end
GENERATED << 'target/vendor/rack.rb'

desc "Generate (ruby) resources"
task :resources => ['target/classes', :unpack_gem] do |t|
rack_dir = File.basename(FileList["target/rack-*"].first)
classes_dir = t.prerequisites.first
{ 'target/vendor' => "#{classes_dir}/vendor",
"target/#{rack_dir}/lib" => "#{classes_dir}/vendor/#{rack_dir}"}.each do |src,dest|
mkdir_p dest
FileList["#{src}/*"].each do |f|
cp_r f, dest
end
end
end

task :test_resources => ["target/test-classes"]

namespace :resources do
desc "Copy (and generate) resources"
task :copy => :resources do
desc "Copy resources"
task :copy do
sh './mvnw -ntp process-resources -Dstyle.color=always -Dmdep.skip=true'
end
desc "Generate test resources"
task :test => :test_resources
end

task :speconly => [ :resources, :test_resources ] do
task :speconly => [ :test_resources ] do
if ENV['SKIP_SPECS'].to_s == 'true'
puts "Skipping specs due to SKIP_SPECS=#{ENV['SKIP_SPECS']}"
else
Expand Down Expand Up @@ -143,7 +108,6 @@ GENERATED << target_jruby_rack

file (target_jar = "target/jruby-rack-#{JAR_VERSION}.jar") do |file|
Rake::Task['compile'].invoke
Rake::Task['resources'].invoke
sh "jar cf #{file.name} -C target/classes ."
end

Expand Down Expand Up @@ -179,6 +143,7 @@ task :gem => [:clean, target_jar, target_jruby_rack, target_jruby_rack_version]
gem.files = FileList["./**/*"].exclude("*.gem").map{ |f| f.sub(/^\.\//, '') }
gem.homepage = %q{http://jruby.org}
gem.required_ruby_version = '>= 3.4.0' # JRuby >= 10.0
gem.add_dependency 'rack', '~> 2.2.0'
end

require 'rubygems/package'
Expand Down
32 changes: 16 additions & 16 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,29 @@ As an executable jar within Jetty:
rm -f Gemfile.lock && bundle install && bundle exec warble executable war
```
2. ```shell
java -Dwarbler.debug=true -Dwarbler.port=8080 -jar *.war
java -Dwarbler.debug=true -Dwarbler.port=8989 -jar *.war
```

## Demo routes

| Example | Component | Embedded Route | Deployed War Route |
|---------|------------------------|-------------------------------------|---------------------------------------------|
| Rails 7 | Status Page | http://localhost:8080/up | http://localhost:8080/rails7/up |
| Rails 7 | Snoop Dump | http://localhost:8080/snoop | http://localhost:8080/rails7/snoop |
| Rails 7 | Simple Form submission | http://localhost:8080/simple_form | http://localhost:8080/rails7/simple_form |
| Rails 7 | Body Posts | http://localhost:8080/body | http://localhost:8080/rails7/body |
| Rails 7 | JSP (render) | http://localhost:8080/jsp/ | http://localhost:8080/rails7/jsp/ |
| Rails 7 | JSP (forward to) | http://localhost:8080/jsp-forward/ | http://localhost:8080/rails7/jsp-forward/ |
| Rails 7 | JSP (include) | http://localhost:8080/jsp-include/ | http://localhost:8080/rails7/jsp-include/ |
| Sinatra | Demo Index | http://localhost:8080/ | http://localhost:8080/sinatra |
| Sinatra | Info | http://localhost:8080/info | http://localhost:8080/sinatra/info |
| Sinatra | Snoop Dump | http://localhost:8080/env | http://localhost:8080/sinatra/env |
| Sinatra | JSP (render) | http://localhost:8080/jsp/index.jsp | http://localhost:8080/sinatra/jsp/index.jsp |
| Sinatra | JSP (forward to) | http://localhost:8080/jsp_forward | http://localhost:8080/sinatra/jsp_forward |
| Sinatra | JSP (include) | http://localhost:8080/jsp_include | http://localhost:8080/sinatra/jsp_include |
| Sinatra | Streaming Demo | http://localhost:8080/stream | http://localhost:8080/sinatra/stream |
| Camping | Demo Index | http://localhost:8080/ | http://localhost:8080/camping |
| Camping | Snoop Dump | http://localhost:8080/snoop | http://localhost:8080/camping/snoop |
| Rails 7 | Snoop Dump | http://localhost:8989/snoop | http://localhost:8080/rails7/snoop |
| Rails 7 | Simple Form submission | http://localhost:8989/simple_form | http://localhost:8080/rails7/simple_form |
| Rails 7 | Body Posts | http://localhost:8989/body | http://localhost:8080/rails7/body |
| Rails 7 | JSP (render) | http://localhost:8989/jsp/ | http://localhost:8080/rails7/jsp/ |
| Rails 7 | JSP (forward to) | http://localhost:8989/jsp-forward/ | http://localhost:8080/rails7/jsp-forward/ |
| Rails 7 | JSP (include) | http://localhost:8989/jsp-include/ | http://localhost:8080/rails7/jsp-include/ |
| Sinatra | Demo Index | http://localhost:8989/ | http://localhost:8080/sinatra |
| Sinatra | Info | http://localhost:8989/info | http://localhost:8080/sinatra/info |
| Sinatra | Snoop Dump | http://localhost:8989/env | http://localhost:8080/sinatra/env |
| Sinatra | JSP (render) | http://localhost:8989/jsp/index.jsp | http://localhost:8080/sinatra/jsp/index.jsp |
| Sinatra | JSP (forward to) | http://localhost:8989/jsp_forward | http://localhost:8080/sinatra/jsp_forward |
| Sinatra | JSP (include) | http://localhost:8989/jsp_include | http://localhost:8080/sinatra/jsp_include |
| Sinatra | Streaming Demo | http://localhost:8989/stream | http://localhost:8080/sinatra/stream |
| Camping | Demo Index | http://localhost:8989/ | http://localhost:8080/camping |
| Camping | Snoop Dump | http://localhost:8989/snoop | http://localhost:8080/camping/snoop |

## Development

Expand Down
3 changes: 1 addition & 2 deletions examples/camping/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ source 'https://rubygems.org'

ruby RUBY_VERSION

gem 'camping', '< 3'
gem 'rack', '~> 2.2.0'
gem 'camping', '< 3' # v3 requires Rack 3.x support

group :development do
gem 'jruby-jars', JRUBY_VERSION
Expand Down
1 change: 0 additions & 1 deletion examples/rails7/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ ruby RUBY_VERSION

gem 'rails', '~> 7.2.0'
gem 'sprockets-rails'
gem 'rack', '~> 2.2.0'

group :development do
gem 'jruby-jars', JRUBY_VERSION
Expand Down
8 changes: 6 additions & 2 deletions examples/sinatra/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ source 'https://rubygems.org'

ruby RUBY_VERSION

gem 'sinatra', '< 4'
gem 'rack', '~> 2.2.0'
gem 'sinatra', '< 4' # v4 requires Rack 3.x support

if JRUBY_VERSION.start_with?('10.1.')
gem 'ostruct'
gem 'logger'
end

group :development do
gem 'jruby-jars', JRUBY_VERSION
Expand Down
10 changes: 0 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -275,16 +275,6 @@
<args>-S rake speconly SKIP_SPECS=${skipTests}</args>
</configuration>
</execution>
<execution>
<!-- additional (ruby) generated resources -->
<id>rake-resources</id>
<phase>prepare-package</phase>
<!-- bind "late" so we do not run during compile/test-compile -->
<goals><goal>exec</goal></goals>
<configuration>
<args>-S rake resources VERSION=${project.version}</args>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
Expand Down
35 changes: 0 additions & 35 deletions src/main/java/org/jruby/rack/DefaultRackApplicationFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ public IRubyObject createApplicationObject(final Ruby runtime) {
rackContext.log(WARN, "no rackup script found - starting empty Rack application!");
rackupScript = "";
}
checkAndSetRackVersion(runtime);
runtime.evalScriptlet("load 'jruby/rack/boot/rack.rb'");
return createRackServletWrapper(runtime, rackupScript, rackupLocation);
}
Expand Down Expand Up @@ -366,40 +365,6 @@ public void initRuntime(final Ruby runtime) {
}
}

/**
* Checks and sets the required Rack version (if specified as a magic comment).
*
* e.g. # rack.version: =2.2.0
*
* @apiNote Internal API, only visible due tests.
*
* @param runtime the JRuby runtime
* @return the rack version requirement
*/
public String checkAndSetRackVersion(final Ruby runtime) {
String rackVersion = null;
try {
rackVersion = IOHelpers.rubyMagicCommentValue(rackupScript, "rack.version:");
}
catch (Exception e) {
rackContext.log(DEBUG, "could not read 'rack.version' magic comment from rackup", e);
}

if ( rackVersion != null ) {
runtime.evalScriptlet("require 'rubygems'");

if ( rackVersion.equalsIgnoreCase("bundler") ) {
runtime.evalScriptlet("require 'bundler'; Bundler.setup");
}
else {
rackContext.log(DEBUG, "detected 'rack.version' magic comment, " +
"will use `gem 'rack', '"+ rackVersion +"'`");
runtime.evalScriptlet("gem 'rack', '"+ rackVersion +"' if defined? gem");
}
}
return rackVersion;
}

private RackApplication createApplication(final ApplicationObjectFactory appFactory) {
return new RackApplicationImpl(appFactory);
}
Expand Down
25 changes: 0 additions & 25 deletions src/main/java/org/jruby/rack/util/IOHelpers.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@
*/
package org.jruby.rack.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -67,27 +65,4 @@ public static String inputStreamToString(final InputStream stream)
return str.toString();
}

public static String rubyMagicCommentValue(final String script, final String prefix)
throws IOException {
if ( script == null ) return null;

final BufferedReader reader = new BufferedReader(new StringReader(script), 80);

String line, comment = null; Pattern pattern = null;
while ( (line = reader.readLine()) != null ) {
// we only support (magic) comments at the beginning :
if (line.isEmpty() || line.charAt(0) != '#' ) break;

if (pattern == null) {
pattern = Pattern.compile(prefix + "\\s*(\\S+)");
}
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
comment = matcher.group(1); break;
}
}
reader.close();
return comment;
}

}
4 changes: 2 additions & 2 deletions src/main/ruby/jruby/rack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ def logger=(logger); @@logger = logger end
require 'jruby/rack/servlet_ext'
require 'jruby/rack/core_ext'

# loading Rack is delayed to allow the application to boot it's desired Rack
# version (if it needs one) e.g. in a Rails application until Bundler setups
# loading Rack is delayed until the booter has run `Bundler.setup` (for a
# bundled application), so that the application's lockfile decides the version
JRuby::Rack::Booter.on_boot { require 'jruby/rack/rack_ext' }
14 changes: 14 additions & 0 deletions src/main/ruby/jruby/rack/booter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def boot!
export_global_settings
load_settings_from_init_rb
prepare_bundler_env
prepare_bundler
set_relative_url_root
run_boot_hooks
self
Expand Down Expand Up @@ -199,6 +200,19 @@ def prepare_bundler_env
ENV['BUNDLE_FROZEN'] ||= 'true' if File.exist?("#{ENV['BUNDLE_GEMFILE']}.lock")
end

# Boots Bundler (`Bundler.setup`) up-front for a bundled application, so that gems required during the boot - Rack
# in particular - resolve per the application's lockfile, instead of rubygems activating the newest version found
# on the gem path. The application's own `Bundler.setup` (e.g. from *config.ru*) then becomes a no-op.
def prepare_bundler
boot_bundler! if ENV['BUNDLE_GEMFILE'] # not a bundled application
end

def boot_bundler!
require 'bundler'
# pre-boot bundler with groups respecting BUNDLE_WITHOUT from the environment
Bundler.ui.silence { Bundler.setup }
end

def relative_url_root(init_param = 'rack.relative_url_append')
relative_url_root = @rack_context.getContextPath || ''
if relative_url_append = @rack_context.getInitParameter(init_param)
Expand Down
5 changes: 3 additions & 2 deletions src/main/ruby/jruby/rack/rack_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

begin
require 'rack'
rescue LoadError
require 'vendor/rack'
rescue LoadError => e
raise LoadError, "#{e.message}\nJRuby-Rack no longer vendors Rack - make sure the rack gem is " \
"available to the application (e.g. add it to the Gemfile or install it into the gem path)"
end unless defined?(::Rack::RELEASE)

# Servlet API friendly extensions to Rack
Expand Down
Loading
Loading