-
-
Save akitaonrails/961187 to your computer and use it in GitHub Desktop.
Rack app for caching RubyGems files. Very useful in our build server that sometimes fails due to our network or rubygems.org timeout.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.DS_Store | |
*.swp | |
*.swo | |
log/** | |
tmp/** | |
cache/** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Page Not Found</title> | |
</head> | |
<body> | |
<h1>Page Not Found</h1> | |
<p>Please, type the correct address for the file.</p> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "./rubygems_proxy" | |
run RubygemsProxy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> | |
<head> | |
<title>Rubygems Mirror</title> | |
</head> | |
<body> | |
<h1>RubyGems Mirror</h1> | |
<h2>List of Available Gems:</h2> | |
<ul> | |
<% @gem_list.each do |file| %> | |
<li><%= file[:name] %> (<%= file[:versions].join(", ") %>)</li> | |
<% end %> | |
</ul> | |
<p>Total: <strong><%= @gem_list.size %> gems.</strong></p> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "open-uri" | |
require "fileutils" | |
require "logger" | |
require "erb" | |
class RubygemsProxy | |
attr_reader :env | |
def self.call(env) | |
new(env).run | |
end | |
def initialize(env) | |
@env = env | |
end | |
def run | |
logger.info "GET #{env["PATH_INFO"]}" | |
if env["PATH_INFO"] == "/" | |
[200, {"Content-Type" => "text/html"}, [listing]] | |
else | |
[200, {"Content-Type" => "application/octet-stream"}, [contents]] | |
end | |
rescue Exception => error | |
# Just try to load from file if something goes wrong. | |
# This includes HTTP timeout, or something. | |
# If it fails again, we won't have any files anyway! | |
logger.error "Error: #{error.class} => #{error.message}" | |
if File.exists?(filepath) | |
content = open(filepath).read | |
[200, {"Content-Type" => "application/octet-stream"}, [content]] | |
else | |
content = open(File.expand_path("../public/404.html", __FILE__)) | |
[404, {"Content-Type" => "text/html"}, [content]] | |
end | |
end | |
private | |
def logger | |
FileUtils.mkdir_p File.expand_path("../log", __FILE__) | |
@logger ||= Logger.new(File.expand_path("../log/proxy.log", __FILE__), "monthly") | |
end | |
def cache_dir | |
File.expand_path "../cache", __FILE__ | |
end | |
def listing | |
last_gem = "" | |
gem_versions = [] | |
@gem_list = [] | |
Dir.glob(File.expand_path("../cache/gems/*.gem", __FILE__)).sort.each do |file| | |
file = File.basename(file) | |
if file =~ /^(.*?)\-(\d+.*?)\.gem$/ | |
if last_gem != $1 | |
@gem_list << { :name => last_gem, :versions => gem_versions } unless last_gem == "" | |
gem_versions = [$2] | |
last_gem = $1 | |
else | |
gem_versions << $2 | |
end | |
end | |
end | |
rhtml = ERB.new(File.read(File.expand_path("../index.erb", __FILE__)), nil, "%") | |
rhtml.result(binding) | |
end | |
def contents | |
if cached? && valid? | |
logger.info "Read from cache: #{filepath}" | |
open(filepath).read | |
else | |
logger.info "Read from interwebz: #{url}" | |
open(url).read.tap {|content| save(content)} | |
end | |
end | |
def save(contents) | |
FileUtils.mkdir_p File.dirname(filepath) | |
File.open(filepath, "wb") {|handler| handler << contents} | |
end | |
def valid? | |
filepath =~ /specs\..+\.gz$/ ? Time.now - File.mtime(filepath) < 300 : true | |
end | |
def cached? | |
File.file?(filepath) | |
end | |
def filepath | |
File.join(cache_dir, env["PATH_INFO"]) | |
end | |
def url | |
File.join("http://rubygems.org", env["PATH_INFO"]) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment