Class: WebserverAbstract
Overview
Tiny embeded webserver
Direct Known Subclasses
Constant Summary
- LICON =
"☀☃☎☑☑☠☣☮☺☂".split(/;/).map {|c| c+";"}
- MIME =
{"png" => "image/png", "gif" => "image/gif", "html" => "text/html","htm" => "text/html", "js" => "text/javascript" ,"css" => "text/css","jpeg" => "image/jpeg" ,"jpg" => "image/jpeg" , "pdf"=> "application/pdf" , "svg" => "image/svg+xml","svgz" => "image/svg+xml", "xml" => "text/xml" ,"xsl" => "text/xml" ,"bmp" => "image/bmp" ,"txt" => "text/plain" , "rb" => "text/plain" ,"pas" => "text/plain" ,"tcl" => "text/plain" ,"java" => "text/plain" , "c" => "text/plain" ,"h" => "text/plain" ,"cpp" => "text/plain", "xul" => "application/vnd.mozilla.xul+xml", "doc" => "application/msword", "docx" => "application/msword","dot"=> "application/msword", "xls" => "application/vnd.ms-excel","xla" => "application/vnd.ms-excel","xlt" => "application/vnd.ms-excel","xlsx" => "application/vnd.ms-excel", "ppt" => "application/vnd.ms-powerpoint", "pptx" => "application/vnd.ms-powerpoint" }
Instance Method Summary (collapse)
- - (Object) do_service(session, request, service, user_passwd, params)
- - (Object) error(txt)
- - (Object) escape(string)
- - (Object) hescape(string)
- - (Object) httpdate(aTime)
- - (Object) info(txt)
-
- (WebserverAbstract) initialize(port, root, name, cadence, timeout, options)
constructor
A new instance of WebserverAbstract.
- - (Object) logg(*args)
- - (Object) makeIndex(adir)
- - (Object) mime(string)
- - (Object) n3(n)
- - (Object) observe(sleeping, delta)
- - (Object) redirect(o, d)
- - (Object) request(session)
- - (Object) run(session)
- - (Object) sendData(sock, type, content)
- - (Object) sendError(sock, no, txt = nil)
- - (Object) sendFile(sock, filename)
- - (Object) serve(uri, &blk)
- - (Object) stop_browser
- - (Object) to_absolute(f)
- - (Object) to_relative(f)
- - (Object) to_table(l)
- - (Object) to_tableb(l, &bl)
- - (Object) unescape(string)
Constructor Details
- (WebserverAbstract) initialize(port, root, name, cadence, timeout, options)
A new instance of WebserverAbstract
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/plugins/httpd.rb', line 22 def initialize(port,root,name,cadence,timeout,) @cb_log= ["logg"] @last_mtime=File.mtime(__FILE__) @port=port @root=root @name=name @rootd=root[-1,1]=="/" ? root : root+"/" @timeout=timeout @th={} @cb={} @redirect={} @server = TCPServer.new('0.0.0.0', @port) @server.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true) info(" serveur http #{port} on #{@rootd} ready!") observe(cadence,timeout*2) @thm=Thread.new { loop { begin while (session = @server.accept) run(session) end rescue error($!.to_s) session.close raise nil end sleep(10); info("restart accept") } } end |
Instance Method Details
- (Object) do_service(session, request, service, user_passwd, params)
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/plugins/httpd.rb', line 87 def do_service(session,request,service,user_passwd,params) logg(session.peeraddr.last,request) redir=@redirect["/"+service] service=redir.gsub(/^\//,"") if @redirect[redir] aservice=to_absolute(service) if redir && ! @redirect[redir] do_service(session,request,redir.gsub(/^\//,""),user_passwd,params) elsif @cb["/"+service] begin code,type,data= @cb["/"+service].call(params) if code==0 && data != '/'+service do_service(session,request,data[1..-1],user_passwd,params) else code==200 ? sendData(session,type,data) : sendError(session,code,data) end rescue logg session.peeraddr.last,"Error in get /#{service} : #{$!}" sendError(session,501,$!.to_s) end elsif service =~ /^stop/ sendData(session,".html","Stopping..."); Thread.new() { sleep(0.1); stop_browser() } elsif File.directory?(aservice) sendData(session,".html",makeIndex(aservice)) elsif File.exists?(aservice) sendFile(session,aservice) else info("unknown request serv=#{service} params=#{params.inspect} #{File.exists?(service)}") sendError(session,500); end end |
- (Object) error(txt)
10 |
# File 'lib/plugins/httpd.rb', line 10 def error(txt) ; logg("nw>e>",txt) ; end |
- (Object) escape(string)
12 |
# File 'lib/plugins/httpd.rb', line 12 def escape(string) ; string.gsub(/([^ \/a-zA-Z0-9_.-]+)/) { '%' + $1.unpack('H2' * $1.size).join('%').upcase }.tr(' ', '+'); end |
- (Object) hescape(string)
13 |
# File 'lib/plugins/httpd.rb', line 13 def hescape(string) ; escape(string.gsub("/./","/").gsub("//","/")) ; end |
- (Object) httpdate(aTime)
172 |
# File 'lib/plugins/httpd.rb', line 172 def httpdate( aTime ); (aTime||Time.now).gmtime.strftime( "%a, %d %b %Y %H:%M:%S GMT" ); end |
- (Object) info(txt)
9 |
# File 'lib/plugins/httpd.rb', line 9 def info(txt) ; logg("nw>i>",txt) ; end |
- (Object) logg(*args)
8 |
# File 'lib/plugins/httpd.rb', line 8 def logg(*args) @cb_log && @cb_log.call(@name,*args) end |
- (Object) makeIndex(adir)
123 124 125 126 127 128 129 130 |
# File 'lib/plugins/httpd.rb', line 123 def makeIndex(adir) dir=to_relative(adir) dirs,files=Dir.glob(adir==@rootd ? "#{@rootd}*" : "#{adir}/*").sort.partition { |f| File.directory?(f)} updir = hescape( dir.split(/\//)[0..-2].join("/")) updir="/" if updir.length==0 up=(dir!="/") ? "<input type='button' onclick='location.href=\"#{updir}\"' value='Parent'>" : "" "<html><head><title>#{dir}</title></head>\n<body><h3><center>#{@name} : #{dir[0..-1]}</center></h3>\n<hr>#{up}<br>#{to_table(dirs.map {|s| " <a href='#{hescape(to_relative(s))}'>"+File.basename(s)+"/"+"</a>\n"})}<hr>#{to_tableb(files) {|f| [" <a href='#{hescape(to_relative(f))}'>"+File.basename(f)+"</a>",n3(File.size(f)),File.mtime(f).strftime("%d/%m/%Y %H:%M:%S")]}}</body></html>" end |
- (Object) mime(string)
173 174 175 |
# File 'lib/plugins/httpd.rb', line 173 def mime(string) MIME[string.split(/\./).last] || "application/octet-stream" end |
- (Object) n3(n)
133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/plugins/httpd.rb', line 133 def n3(n) u=" B" if n> 10000000 n=n/(1024*1024) u=" MB" elsif n> 100000 n=n/1024 u=" KB" end "<div style='width:100px;text-align:right;'>#{(n.round.to_i.to_s.reverse.gsub(/(\d\d\d)(?=\d)/,'\1 ' ).reverse) +u} | </div>" end |
- (Object) observe(sleeping, delta)
14 15 16 17 18 19 20 21 |
# File 'lib/plugins/httpd.rb', line 14 def observe(sleeping,delta) @tho=Thread.new do loop do sleep(sleeping) nowDelta=Time.now-delta l=@th.select { |th,tm| (tm[0]<nowDelta) } l.each { |th,tm| info("killing thread") ; th.kill; @th.delete(th) ; tm[1].close rescue nil } end ; end end |
- (Object) redirect(o, d)
84 85 86 |
# File 'lib/plugins/httpd.rb', line 84 def redirect(o,d) @redirect[o]=d end |
- (Object) request(session)
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/plugins/httpd.rb', line 64 def request(session) request = session.gets uri = (request.split(/\s+/)+['','',''])[1] #info uri service,param,*bidon=(uri+"?").split(/\?/) params=Hash[*(param.split(/#/)[0].split(/[=&]/))] rescue {} params.each { |k,v| params[k]=unescape(v) } uri=unescape(service)[1..-1].gsub(/\.\./,"") userpass=nil if (buri=uri.split(/@/)).size>1 uri=buri[1..-1].join("@") userpass=buri[0].split(/:/) end do_service(session,request,uri,userpass,params) rescue error("Error Web get on #{request}: \n #{$!.to_s} \n #{$!.backtrace.join("\n ")}" ) rescue nil session.write "HTTP/1.1 501 NOK\r\nContent-type: text/html\r\n\r\n<html><head><title>WS</title></head><body>Error : #{$!}" rescue nil ensure session.close rescue nil end |
- (Object) run(session)
50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/plugins/httpd.rb', line 50 def run(session) if ! File.exists?(@root) sendError(session,500,txt="root directory unknown: #{@root}") else Thread.new(session) do |sess| @th[Thread.current]=[Time.now,sess] request(sess) @th.delete(Thread.current) end end end |
- (Object) sendData(sock, type, content)
156 157 158 159 |
# File 'lib/plugins/httpd.rb', line 156 def sendData(sock,type,content) sock.write "HTTP/1.0 200 OK\r\nContent-type: #{mime(type)}\r\nContent-size: #{content.size}\r\n\r\n" sock.write(content) end |
- (Object) sendError(sock, no, txt = nil)
150 151 152 153 154 155 |
# File 'lib/plugins/httpd.rb', line 150 def sendError(sock,no,txt=nil) if txt txt="<html><body><code><pre></pre>#{txt}</code></body></html>" end sock.write "HTTP/1.0 #{no} NOK\r\nContent-type: #{mime(".html")}\r\n\r\n <html><p>Error #{no} : #{txt}</p></html>" end |
- (Object) sendFile(sock, filename)
160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/plugins/httpd.rb', line 160 def sendFile(sock,filename) s=File.size(filename) if s < 0 || File.extname(filename).downcase==".lnk" sendError(sock,500,"Error reading file #{filename} : (size=#{s})" ) return end sock.write "HTTP/1.0 200 OK\r\nContent-type: #{mime(filename)}\r\nContent-size: #{File.size(filename)}\r\nLast-Modified: #{httpdate(File.mtime(filename))}\r\nDate: #{httpdate(Time.now)}\r\n\r\n" File.open(filename,"rb") do |f| f.binmode; sock.binmode; ( sock.write(f.read(32000)) while (! f.eof? && ! sock.closed?) ) rescue nil end end |
- (Object) serve(uri, &blk)
61 62 63 |
# File 'lib/plugins/httpd.rb', line 61 def serve(uri,&blk) @cb[uri] = blk end |
- (Object) stop_browser
118 119 120 121 122 |
# File 'lib/plugins/httpd.rb', line 118 def stop_browser info "exit on web demand !" @serveur.close rescue nil [@tho,@thm].each { |th| th.kill } end |
- (Object) to_absolute(f)
132 |
# File 'lib/plugins/httpd.rb', line 132 def to_absolute(f) "#{@rootd}#{f.gsub(/^\//,'')}" end |
- (Object) to_relative(f)
131 |
# File 'lib/plugins/httpd.rb', line 131 def to_relative(f) f.gsub(/^#{@rootd}/,"/") end |
- (Object) to_table(l)
144 145 146 |
# File 'lib/plugins/httpd.rb', line 144 def to_table(l) "<table><tr>#{l.map {|s| "<td>#{s}</td>"}.join("</tr><tr>")}</tr></table>" end |
- (Object) to_tableb(l, &bl)
147 148 149 |
# File 'lib/plugins/httpd.rb', line 147 def to_tableb(l,&bl) "<table><tr>#{l.map {|s| "<td>#{bl.call(s).join("</td><td>")}</td>"}.join("</tr><tr>")}</tr></table>" end |
- (Object) unescape(string)
11 |
# File 'lib/plugins/httpd.rb', line 11 def unescape(string) ; string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2}))/n) { [$1.delete('%')].pack('H*') } ; end |