Skip to content

Instantly share code, notes, and snippets.

@ohac
Created April 19, 2010 11:53
Show Gist options
  • Save ohac/370965 to your computer and use it in GitHub Desktop.
Save ohac/370965 to your computer and use it in GitHub Desktop.
%html
%head
%title== #{hashstr} - p2pweb
- jq = "http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"
%script{:type => "text/javascript", :src => jq}
%script{:type => "text/javascript", :src => "/haml.js"}
%script{:type => "text/javascript", :src => "/usehamljs.js"}
%body
%a{:href => '/'} Home
%input#hash{:type => :hidden, :value => hashstr}
%hr
#hamljs
%hr
%form{:method => "post", :action => "/"}
%textarea#raw{:name => "piece", :rows => 12, :cols => 80}
== %a{href: '#{hashstr}'} Parent
%br
%input{:type => "submit"}
%a#preview{:href => "#"} Preview
%hr
#previewarea
%html
%head
%title p2pweb
- jq = "http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"
%script{:type => "text/javascript", :src => jq}
%script{:type => "text/javascript", :src => "/p2p.js"}
%link{:rel => "alternate", :href => "/rss.xml", :title => "Recent Added", :type => "application/rss+xml"}
%body
- $cache.keys.each do |k|
%a{:href => "/h/#{k}"} haml-js
|
%a{:href => "/#{k}?raw=t&retry=t"} raw
- prop = $prop[k] || {}
|
= prop[:last]
|
= prop[:count]
%br
- $request.keys.each do |k|
= k
%br
%br
%a{:href => "/rss.xml", :rel => "alternate", :type => "application/rss+xml"} RSS feed
%br
%br
%form{:method => "post", :action => "/"}
%textarea{:name => "piece", :rows => 12, :cols => 80}
%br
%input{:type => "submit"}
%a#clear{:href => "#"} Clear Local Storage
$(function(){
var poll = function() {
$.getJSON("/request", function(json) {
$.each(json, function(hash) {
var piece = localStorage[hash];
if (piece) {
$.post("/base64", hash + "=" + piece);
}
});
});
$.getJSON("/offer", function(json) {
$.each(json, function(i, hash) {
var piece = localStorage[hash];
if (!piece) {
// TODO decide to get this piece or not (get all for now)
$.get("/" + hash, function(data) {
localStorage[hash] = data;
});
}
});
});
for (var i = 0; i < localStorage.length; i++) {
var hash = localStorage.key(i);
$.get("/have?hash=" + hash);
}
setTimeout(poll, 10000);
};
poll();
$('#clear').click(function() {
hash = localStorage.clear();
});
});
#!/usr/bin/env ruby
require 'rubygems'
require 'sinatra'
require 'haml'
require 'json'
require 'base64'
$recent = []
$prop = {}
$cache = {}
$request = {}
CONTENT_TYPES = {:html => 'text/html', :css => 'text/css',
:js => 'application/javascript', :plain => 'text/plain'}
before do
request_uri = case request.env['REQUEST_URI']
when /\.css$/; :css
when /\.js$/; :js
else :html
end
content_type CONTENT_TYPES[request_uri], :charset => 'utf-8'
end
get '/' do
haml :index
end
get '/request' do
$request.to_json
end
get '/offer' do
$cache.keys.to_json
end
get '/have' do
hash = params[:hash]
$request[hash] ||= true unless $cache.include?(hash)
''
end
get '/:hash' do |hash|
pass if hash.size != 40
piece = $cache[hash]
if piece
$request.delete(hash)
content_type CONTENT_TYPES[:plain], :charset => 'utf-8'
params[:raw] ? piece : Base64.encode64(piece)
else
$request[hash] ||= true
if params[:retry]
haml :retry
else
pass
end
end
end
get '/rss.xml' do
haml :rss, :locals => { :baseurl => 'http://localhost:4567' }
end
get '/h/:hash' do |hash|
$prop[hash] ||= {}
prop = $prop[hash]
prop[:last] = Time.now
prop[:count] ||= 0
prop[:count] += 1
haml :hamljs, :locals => { :hashstr => hash }
end
post '/base64' do
params.each do |hash, data|
piece = Base64.decode64(data)
if hash == Digest::SHA1.hexdigest(piece)
$cache[hash] = piece
$request.delete(hash)
end
end
''
end
post '/' do
piece = params[:piece]
hash = Digest::SHA1.hexdigest(piece)
$cache[hash] = piece
$recent << { :date => Time.now, :id => hash }
$recent.shift if $recent.size > 10
redirect "/h/#{hash}"
end
%html
%head
%meta{'http-equiv' => "refresh", :content => '3'}
- jq = "http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"
%script{:type => "text/javascript", :src => jq}
%script{:type => "text/javascript", :src => "/p2p.js"}
%body
waiting...
!!! XML
%rss{:version=>"2.0"}
%channel
%title Recent Added Pages
%link= baseurl
%description p2pweb
%language en
- $recent.reverse.each do |h|
%item
%pubDate= h[:date].strftime('%a, %d %b %Y %H:%M:%S %z')
- url = "#{baseurl}/h/#{h[:id]}"
%guid{:isPermaLink => true}= url
%link= url
%title= h[:id]
%description= h[:id]
$(function() {
$.get('/' + $('#hash').val(), { raw: 't' }, function(data) {
var main = Haml(data.split('\r').join(''));
$('#hamljs').html(main({}));
});
$('#preview').click(function() {
var main = Haml($('#raw').val());
$('#previewarea').html(main({}));
});
});
@ohac
Copy link
Author

ohac commented Apr 19, 2010

ウェブブラウザをピアとした分散データストアっぽいものを作ってみた。
ウェブサーバはポストされたデータをキャッシュに一時保管する。
ウェブサーバはこのデータをピアに保存してもらうために/offerを提供する。
ウェブブラウザは/offerにあるデータをゲットし、localStorageに保存する。
ウェブサーバが持たないデータを要求された場合、データを持つピアにポストしてもらうために/requestを提供する。
ウェブブラウザは/requestにあるキーと一致するものがlocalStorageにあればウェブサーバにポストする。これにより、ウェブサーバはリクエストに答えることができるようになる。

@ohac
Copy link
Author

ohac commented Jun 4, 2010

haml-jsでwikiっぽく使えるようにしました。
http://github.com/creationix/haml-js の lib/haml.js を public にコピーして使ってみてください。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment