cmux/node_modules/@vercel/ruby/vc_init_dev.rb
2026-01-29 17:36:26 -08:00

83 lines
1.9 KiB
Ruby

"""
Auto-generated template used by vercel dev (Ruby, Rack)
Serves static files from PUBLIC_DIR before delegating to the user Rack app.
This file is written to the project at .vercel/ruby/vc_init_dev.rb
and executed by the dev server launcher.
"""
require 'rack'
require 'rack/handler/webrick'
require 'webrick'
require 'socket'
$stdout.sync = true
$stderr.sync = true
USER_ENTRYPOINT = "__VC_DEV_ENTRYPOINT__"
PUBLIC_DIR = 'public'
def build_user_app
if USER_ENTRYPOINT.end_with?('.ru')
app, _ = Rack::Builder.parse_file(USER_ENTRYPOINT)
app
else
# For dev we only support Rack entrypoints (.ru) to ensure consistent behavior
abort("Unsupported entrypoint: #{USER_ENTRYPOINT}. Please use a Rack config (.ru) file for vercel dev.")
end
end
class StaticThenApp
def initialize(app, public_dir)
@app = app
@public_dir = public_dir
@file_server = Rack::File.new(public_dir)
@base = File.expand_path(public_dir)
end
def call(env)
req_path = env['PATH_INFO'] || '/'
# Normalize path and guard against traversal
safe = req_path.sub(/^\//, '')
full = File.expand_path(safe, @base)
if full.start_with?(@base + File::SEPARATOR) && File.file?(full)
# Delegate to Rack::File which handles HEAD/GET correctly
return @file_server.call(env)
end
@app.call(env)
end
end
def static_then_app(user_app)
StaticThenApp.new(user_app, PUBLIC_DIR)
end
host = '127.0.0.1'
begin
sock = TCPServer.new(host, 0)
port = sock.addr[1]
ensure
sock&.close
end
app = static_then_app(build_user_app)
logger = WEBrick::Log.new($stderr)
logger.level = WEBrick::Log::WARN
server = WEBrick::HTTPServer.new(
BindAddress: host,
Port: port,
AccessLog: [],
Logger: logger
)
# Mount the Rack app at root
server.mount '/', Rack::Handler::WEBrick, app
trap('INT') { server.shutdown }
trap('TERM') { server.shutdown }
puts "Serving on http://#{host}:#{server.config[:Port]}"
server.start