Project

femtows

0.0
No commit activity in last 3 years
No release in over 3 years
a tiny web server, for local file transfert, embedded, http experimentations
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

Femtows : femto sized web server

Presentation

The tiny web server ... 400 Lines of code.

Build to be embedded in any ruby application, test/debug/admin access...

Features :

  • methods GET POST (PUT, REMOVE, HEAD... are missing!)
  • index generate as simple explorer (if path correspond to existant directory or file)
  • multipart/data supported
  • upload file via multipart
  • multipart dynamic (can be active continiously, a timeout inter-part is setted to 10 minutes)
  • http redirection

Performances are not so bad : better than Sinatra/Thin, near Puma/Thin)

Install

gem install femtows

Usage

As file http server :

> ruby -rfemtows -e "cliweb()"
> ruby -rfemtows -e "cliweb('/tmp',8080)"
or
> femtows.bat
# femtows.sh

Embedded V1:

# server all file in current dir and .info request :

$ws=WebserverRoot.new(8080,"/tmp","femto ws",10,300, {})

$ws.serve("/info")    {|p|  
 [200,".html", "Femto demo<hr><a href='/'>site</a><hr>#{$ws.to_table(p)}" ] 
}

Embedded V2:

class App < Fem
  def get_app_html(p)
    "<html><body><h2><center>Hello</center></h2><hr>
      <p>#{content}</p><hr><center>[femtows]</center>
    </body></html>"
  end
  def content
    to_tableb(Dir.glob("*.rb")) {|f| [f,File.size(f),File.mtime(f)]}
  end
end
App.new(ARGV[0].to_i)

Upload file

class App < Fem
  def get_app_html(p)
	  form=<<EEND
<form action="mp" method="post" enctype="multipart/form-data">
  <p><input type="text" name="text" value="dddddddddddddddd">
  <p><input type="file" name="file1">
  <p><input type="file" name="file2">
  <p><button type="submit">Submit</button>
</form>
EEND
      "<html><body><h2><center>Hello</center></h2><hr><p>#{form}</p><hr><center>[femtows]</center></body>"
  end
  def get_mp_html(p)
	bilan={}
	stream_input { |name,type,value,headers|
		puts ["!!!!!!!!!! stream_input reactor ==> ",name,type,value,headers].join(" ")
		puts("           File size of %s  => %d" % [value,File.size(value)]) if type==:file
		size= (type==:file) ? File.size(value) : -1
		bilan[name]=[type,value,size]
	}
    "<html><body><h2><center>Stream input (multipart)</center></h2><hr><p>#{bilan.inspect.split(",").join("<br>")}</p><hr><center>[femtows]</center></body>"
  end
end

With v2 API, all methods which name match get_()_() will be associate with url $1 and his output will be sending with MIME code corresponding to file extension $2.

So def get_login_html() while match for path /login,method GET or POST, end returned value is sended as Content-type: text/html

API

WebserverRoot.new(
	port_http,  # server http  port (>1024 on posix, if not root)
	root-dir,	# only one file root. indexed by defalut
	ws_name,	# name in trace & index title 
	10,300, 	# watch too long connection: every  10 secondes, 
				    # kill session which have started from more than 300 seconds
	{}			  # options. only one, for logg events , see demo.rb
)

Servlet receive params hash which content :

  • all http header, with key upercase, prefixed with 'HEAD-'
  • http parameters (?a=b&...)

Exemple : http://localhost:9980/info?aa=bb&cc=dd, give with p.to_a.inspect:

["aa", "bb"]
["cc", "dd"]
["HEAD-HOST", "localhost:9980"]
["HEAD-USER-AGENT", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2"]
["HEAD-ACCEPT", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"]
["HEAD-ACCEPT-LANGUAGE", "fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3"]
["HEAD-ACCEPT-ENCODING", "gzip, deflate"]
["HEAD-CONNECTION", "keep-alive"]

License

LGPL