Skip to content

Instantly share code, notes, and snippets.

@hx
Last active October 26, 2015 06:20
Show Gist options
  • Save hx/2f02b8aef9c999297971 to your computer and use it in GitHub Desktop.
Save hx/2f02b8aef9c999297971 to your computer and use it in GitHub Desktop.
Bookmarks

Run a bunch of processes (e.g. Python-based web services), and bind an additional server to port 80 that encapsulates a list of "bookmark" urls.

#!/usr/bin/env ruby
require 'rubygems'
gem 'thin'
gem 'foreman'
require 'shellwords'
require 'pathname'
require 'yaml'
require 'thin'
require 'erb'
require 'cgi'
class Bookmarks
HEIGHT = 30
HTML = <<-EOF
<!doctype html>
<html>
<head>
<title><%= render data['title'] %></title>
<style>
<%= CSS %>
</style>
</head>
<body>
<nav>
<ul>
<% data['links'].each do |name, link| %>
<li>
<a href="<%= render link %>" target="viewport"><%= render name %></a>
</li>
<% end %>
</ul>
</nav>
<iframe frameborder="0" name="viewport"/>
</body>
</html>
EOF
CSS = <<-EOF
* {
margin: 0;
padding: 0;
text-decoration: none;
}
html, body, iframe, ul, li {
height: 100%;
}
iframe {
position: fixed;
top: #{HEIGHT}px;
left: 0;
bottom: 0;
width: 100%;
border: none;
}
nav {
position: fixed;
top: 0;
height: #{HEIGHT}px;
left: 0;
right: 0;
background: black;
font: 14px/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
padding: 0 8px;
}
li {
display: inline-block;
}
a {
color: #aaa;
display: block;
padding: 8px;
}
a:hover {
background: #222;
color: #eee;
}
EOF
def self.run
new.run
end
def run
make_data_file
if `whoami`.chomp != 'root'
escalate
elsif ARGV.first == 'server'
run_server
else
run_foreman
end
end
def escalate
puts 'Escalating to root; password may be requested.'
system 'sudo', '-E', $0, *ARGV
end
def run_foreman
system "echo #{Shellwords.escape procfile_contents} | foreman start -f /dev/stdin"
end
def procfile_contents
{'bookmarks' => "#{File.expand_path __FILE__} server 2>&1"}.merge(data['processes']).map { |line| line.join(':') << "\n" }.join
end
def make_data_file
data_path.write YAML.dump(data) unless data_path.exist?
end
def data
@data ||= data_path.exist? ? YAML.load(data_path.read) : default_data
end
def data_path
@data_path ||= Pathname(__FILE__).parent + 'bookmarks.yml'
end
def default_data
{
'title' => 'Give your bookmarks server a title!',
'processes' => {
'sample' => 'echo Replace this with something you want to keep running'
},
'links' => {
'Home' => 'javascript:alert("Put your links here, or numbers for local ports")'
}
}
end
def run_server
Thin::Logging.logger = Logger.new(STDOUT)
Thin::Server.start '0.0.0.0', 80 do
run Bookmarks.new
end
end
def render(str)
case str
when Fixnum
render "http://#{host}:#{str}"
else
CGI.escapeHTML str
end
end
def host
@env['SERVER_NAME']
end
def body
@body ||= ERB.new(HTML).result binding
end
def call(env)
@env = env
[200, {'Content-Type' => 'text/html;charset=utf8'}, [body]]
end
end
Bookmarks.run if $0 == __FILE__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment