Class: Paquette::GemServer

Inherits:
Object
  • Object
show all
Defined in:
lib/paquette/gem_server.rb,
lib/paquette/gem_server/gem_repacker.rb,
lib/paquette/gem_server/personalizer.rb,
lib/paquette/gem_server/gem_repository.rb,
lib/paquette/gem_server/read_gated_repository.rb,
lib/paquette/gem_server/directory_gem_repository.rb

Defined Under Namespace

Classes: DirectoryGemRepository, GemRepacker, GemRepository, Personalizer, ReadGatedRepository

Constant Summary collapse

@@routes =
Routes.draw do |r|
  # Root endpoint
  r.get "/" do
    text_ok("Paquette RubyGems Repository")
  end
   # API endpoints
  r.post "/api/v1/gems" do
    handle_push
  end
   r.delete "/api/v1/gems/yank" do
    handle_yank
  end
   r.get "/api/v1/versions" do
    handle_versions
  end
   r.get "/api/v1/names" do
    handle_names
  end
   r.get "/api/v1/search.json" do |query: nil|
    handle_search(query)
  end
   # Specs endpoints
  r.get "/specs.4.8" do
    handle_specs("4.8")
  end
   r.get "/specs.4.8.gz" do
    handle_specs("4.8.gz")
  end
   r.get "/latest_specs.4.8" do
    handle_latest_specs("4.8")
  end
   r.get "/latest_specs.4.8.gz" do
    handle_latest_specs("4.8.gz")
  end
   # Compact index endpoints
  r.get "/names" do
    handle_compact_names
  end
   r.get "/versions" do
    handle_compact_versions
  end
   # Dynamic endpoints with parameters
  r.get "/info/:gem_name" do |gem_name:|
    info_lines = @repository.compact_info(gem_name)
     if info_lines.empty?
      not_found("Not Found")
    else
      text_ok(info_lines.join("\n"))
    end
  end
   r.get "/quick/Marshal.4.8/:gem_spec_name.gemspec.rz" do |gem_spec_name:|
    # Parse gem name and version from the spec name (e.g., "zip_kit-6.3.2")
    if (match = gem_spec_name.match(/^(.+?)-(\d+\.\d+\.\d+.*)$/))
      gem_name, version = match[1], match[2]
       if @repository.gem_exists?(gem_name, version)
        spec = @repository.gem_spec(gem_name, version)
        if spec
          # Marshal the spec and compress it with raw deflate (not gzip)
          marshaled_spec = Marshal.dump(spec)
          compressed_spec = Zlib::Deflate.deflate(marshaled_spec)
          [200, {"Content-Type" => "application/octet-stream"}, [compressed_spec]]
        else
          not_found("Spec not found")
        end
      else
        not_found("Gem not found: #{gem_name}-#{version}")
      end
    else
      not_found("Invalid gem spec name: #{gem_spec_name}")
    end
  end
   r.get "/gems/:gem_filename" do |gem_filename:|
    # Extract gem name and version from filename
    if (match = gem_filename.match(/^(.+)-(\d+\.\d+\.\d+.*)\.gem$/))
      gem_name, version = match[1], match[2]
      return not_found("Gem not found or it is not within your license") unless @repository.gem_exists?(gem_name, version)
       # gem_file_path now automatically returns personalized gem
      gem_path = @repository.gem_file_path(gem_name, version)
      clen = File.size(gem_path).to_s
      hh = {"Content-Type" => "application/octet-stream", "Content-Length" => clen}
       [200, hh, File.open(gem_path, "rb")]
    else
      not_found("Invalid gem filename")
    end
  end
end

Instance Method Summary collapse

Constructor Details

#initialize(repository) ⇒ GemServer

Build a gem server backed by ‘repository`. Reads, writes, and yanks all flow through this one object — whether writes are accepted depends on the wrapper chain the caller assembled. A ReadGatedRepository, for example, refuses add_gem and yank_gem; a bare DirectoryGemRepository accepts both. Callers typically construct the stack per-request so user-specific state (entitlements, license keys) is captured in plain closures rather than stored on the server.



128
129
130
# File 'lib/paquette/gem_server.rb', line 128

def initialize(repository)
  @repository = repository
end

Instance Method Details

#call(env) ⇒ Object



132
133
134
135
136
137
138
139
# File 'lib/paquette/gem_server.rb', line 132

def call(env)
  request = Rack::Request.new(env)
  route = @@routes.match(request)
  return not_found("Not found") unless route

  @request = request
  @@routes.perform_action(route, self, request)
end