Skip to content

Instantly share code, notes, and snippets.

@kuboon
Created February 8, 2023 04:09
Show Gist options
  • Save kuboon/b3df5ff2002b8bcd15ee26a680d7cb02 to your computer and use it in GitHub Desktop.
Save kuboon/b3df5ff2002b8bcd15ee26a680d7cb02 to your computer and use it in GitHub Desktop.
rails を cgi で無理やり動かす
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.cgi/$1 [QSA,L]
#!/bin/ruby
require 'bundler/setup' # Set up gems listed in the Gemfile.
require 'drb/drb'
require 'logger'
require "rack"
require 'rack/rewindable_input'
module Dispatch
RAILS_ENV = 'value_server'
DRUBY_URI = "druby://localhost:13142"
LOCKFILE = "../tmp/pids/dispatch.pid"
LOGGER = Logger.new('../log/dispatch.log')
class CGIHandler
def initialize(app)
@app = app
end
def call(env, stdin, stdout)
env.update(Rack::SCRIPT_NAME => '', # clear
"rack.version" => Rack::VERSION,
"rack.input" => stdin,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => true,
"rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http"
)
LOGGER.info "#{DRb.uri} call rack"
status, headers, body = @app.call(env)
LOGGER.info "#{DRb.uri} status: #{status}"
begin
stdout.print "Status: #{status}\r\n"
send_headers stdout, headers
send_body stdout, body
ensure
body.close if body.respond_to? :close
end
end
private
def send_headers(stdout, headers)
headers.each { |k, vs|
vs.split("\n").each { |v|
stdout.print "#{k}: #{v}\r\n"
}
}
stdout.print "\r\n"
stdout.flush
end
def send_body(stdout, body)
body.each { |part|
stdout.print part.to_str
stdout.flush
}
end
end
class << self
def main
spawn_server unless server_alive?
$stdin.binmode
DRb.start_service
cgi_handler = DRbObject.new_with_uri(DRUBY_URI)
LOGGER.info "#{DRb.uri} call cgi_handler"
cgi_handler.call(ENV.to_h, Rack::RewindableInput.new($stdin), $stdout)
LOGGER.info "#{DRb.uri} done"
rescue => e
puts "Content-Type: text/plain\nStatus: 500\n\n#{e}"
puts e.backtrace
LOGGER.error ([e] + e.backtrace).join("\n")
end
private
def server_alive?
return false unless File.exist?(LOCKFILE)
return true if process_alive? File.read(LOCKFILE).to_i
File.delete(LOCKFILE)
false
end
def process_alive?(pid)
Process.getpgid( pid )
true
rescue Errno::ESRCH
false
end
def spawn_server
File.open(LOCKFILE, "w") do |f|
if f.flock(File::LOCK_EX | File::LOCK_NB)
f.puts fork { start_service }
sleep 5
else
LOGGER.error("lock failed")
end
end
end
def start_service
$stdout.reopen("/dev/null", "w")
$stderr.reopen("/dev/null", "w")
LOGGER.info 'starting server..'
DRb.start_service(DRUBY_URI, cgi_handler)
LOGGER.info 'started server'
DRb.thread.join
rescue => e
LOGGER.error ([e] + e.backtrace).join("\n")
end
def cgi_handler
ENV['RAILS_ENV'] = RAILS_ENV
require '../config/environment'
CGIHandler.new(Rails.application)
end
end
end
Dispatch.main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment