miniserver 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9ad70987c27eba35d73e421e04b626e8cd0bd6a5
4
+ data.tar.gz: f974f8e519e04bf356e9f24497600e561fa2d0a8
5
+ SHA512:
6
+ metadata.gz: b5fefa23eb21d64ee6473e25712b6153fde6bc674ac0081c12d4f4b3e7c5b9e34aa73c54bab6062aa077ea6aaa4e916650cb67598f13e3bb718a6d4c6082168f
7
+ data.tar.gz: 57e62a7cf011f9e4d78aedaec76248dd8d76af9e528c4799eed8edc0af28ec6d2ac2749296e756c8167cf70ca72ce0e2d5d35c61d1caa889f58bc5b4acdd79ab
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in miniserver.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 zhouguangming
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,25 @@
1
+ # Miniserver
2
+
3
+ Miniserver is a simple fast HTTP 1.1 server for Ruby/Rack applications.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'miniserver'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install miniserver
18
+
19
+ ## Contributing
20
+
21
+ 1. Fork it
22
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
23
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
24
+ 4. Push to the branch (`git push origin my-new-feature`)
25
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'miniserver'
4
+
5
+ Miniserver::Command.new(ARGV).run!
@@ -0,0 +1,26 @@
1
+ require 'miniserver/version'
2
+ require 'miniserver/server'
3
+ require 'miniserver/const'
4
+ require 'miniserver/command'
5
+ require 'rack/handler/miniserver'
6
+
7
+ module Process
8
+ def running?(pid)
9
+ Process.getpgid(pid) != -1
10
+ rescue Errno::EPERM
11
+ true
12
+ rescue Errno::ESRCH
13
+ false
14
+ end
15
+ module_function :running?
16
+ end
17
+
18
+ module Miniserver
19
+ def self.logger=(logger)
20
+ @logger=logger
21
+ end
22
+
23
+ def self.logger
24
+ @logger
25
+ end
26
+ end
@@ -0,0 +1,106 @@
1
+ require 'miniserver/runner'
2
+ require 'open3'
3
+ require 'optparse'
4
+
5
+ module Miniserver
6
+ class Command
7
+ COMMANDS = %w(start stop restart status)
8
+
9
+ def initialize(argv)
10
+ @options = {
11
+ daemonize: false,
12
+ host: '0.0.0.0',
13
+ port: 8080,
14
+ rackup: ::File.expand_path('config.ru'),
15
+ log: ::File.expand_path('log/miniserver.log'),
16
+ pid: ::File.expand_path('tmp/pids/miniserver.pid'),
17
+ environment: 'development'
18
+ }
19
+
20
+ parser.parse!(argv)
21
+
22
+ @command = argv.pop || 'start'
23
+ end
24
+
25
+ def run!
26
+ if COMMANDS.include?(@command)
27
+ Runner.new(@options).send(@command)
28
+ else
29
+ puts @parser
30
+ end
31
+ end
32
+
33
+ def parser
34
+ @parser ||= OptionParser.new do |o|
35
+ o.banner = "Miniserver #{Miniserver::VERSION}\nUsage: miniserver <options> #{COMMANDS.join('|')}"
36
+ o.separator ""
37
+
38
+ o.on "-p", "--port PORT", "Define the TCP port to bind (default: #{@options[:port]})" do |arg|
39
+ @options[:port] = arg
40
+ end
41
+
42
+ o.on "-o", "--host HOST", "Bind to HOST address (default: #{@options[:host]})" do |arg|
43
+ @options[:host] = arg
44
+ end
45
+
46
+ o.on "-l", "--log FILE", "File to redirect output (default: log/miniserver.log)" do |arg|
47
+ @options[:log] = arg
48
+ end
49
+
50
+ o.on "-P", "--pid FILE", "File to store PID (default: tmp/pids/miniserver.pid)" do |arg|
51
+ @options[:pid] = arg
52
+ end
53
+
54
+ o.on "-d", "--daemonize", "Run daemonized in the background(default: false)" do |arg|
55
+ @options[:daemonize] = arg
56
+ end
57
+
58
+ o.on "-e", "--environment ENVIRONMENT", "The environment to run the Rack app on (default development)" do |arg|
59
+ @options[:environment] = arg
60
+ end
61
+
62
+ o.on "-R", "--rackup FILE", "Load a Rack config file (default: #{@options[:rackup]})" do |arg|
63
+ @options[:rackup] = arg
64
+ end
65
+
66
+ o.on_tail "-h", "--help", "Show help" do
67
+ puts @parser
68
+ exit
69
+ end
70
+
71
+ o.on_tail("-v", "--version", "Show version") do
72
+ puts "Miniserver #{Miniserver::VERSION}"
73
+ exit
74
+ end
75
+ end
76
+ end
77
+
78
+ def self.restart(script, options)
79
+ File.delete(options[:pid]) if File.exist?(options[:pid])
80
+
81
+ shellified_options = options.inject([]) do |args, (name, value)|
82
+ option_name = name.to_s.tr("_", "-")
83
+ case value
84
+ when NilClass, TrueClass
85
+ args << "--#{option_name}"
86
+ when FalseClass
87
+ when Array
88
+ value.each { |v| args << "--#{option_name}=#{v}" }
89
+ else
90
+ args << "--#{option_name}=#{value}"
91
+ end
92
+
93
+ args
94
+ end
95
+
96
+ cmd = "#{script} #{shellified_options.compact.join(' ')} start"
97
+
98
+ Open3.popen3(cmd) do |stdin, stdout, stderr|
99
+ puts stdout.gets until stdout.eof?
100
+ puts stderr.gets until stderr.eof?
101
+ end
102
+
103
+ exit
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,78 @@
1
+ require 'miniserver/request'
2
+ require 'miniserver/response'
3
+ require 'http/parser'
4
+ require 'time'
5
+
6
+ module Miniserver
7
+ class Connection < EM::Connection
8
+ attr_accessor :app
9
+
10
+ def post_init
11
+ @request = Request.new
12
+ @response = Response.new
13
+ @parser = Http::Parser.new(self)
14
+ end
15
+
16
+ def on_headers_complete(headers)
17
+ @request.headers = headers
18
+ @request.parse_header(@parser, self)
19
+ end
20
+
21
+ def on_body(chunk)
22
+ @request.body << chunk
23
+ end
24
+
25
+ def on_message_complete
26
+ begin
27
+ Rack::Handler::Miniserver.new(app).process(@request, @response)
28
+ send_response!
29
+ rescue
30
+ Miniserver.logger.error("!! Unexpected error while processing request: #{$!.message}")
31
+ ensure
32
+ close_connection_after_writing
33
+ end
34
+ end
35
+
36
+ def receive_data(data)
37
+ @parser << data
38
+ end
39
+
40
+ def send_response!
41
+ send_status_line
42
+ send_headers
43
+ send_data(BLANK_LINE)
44
+ send_body
45
+ end
46
+
47
+ def send_status_line
48
+ send_data("#{HTTP_VERSION} #{@response.status} #{HTTP_CODE[@response.status]}#{BLANK_LINE}")
49
+ end
50
+
51
+ def send_headers
52
+ headers = String.new
53
+
54
+ @response.headers[SERVER] = MINISERVER
55
+ @response.headers[DATE] = Time.now.httpdate
56
+
57
+ @response.headers.each do |name, value|
58
+ if value.is_a?(String)
59
+ value.split(NEWLINE).each do |v|
60
+ headers.concat("#{name}#{COLON} #{v}#{BLANK_LINE}")
61
+ end
62
+ else
63
+ headers.concat("#{name}#{COLON} #{value}#{BLANK_LINE}")
64
+ end
65
+ end
66
+
67
+ send_data(headers)
68
+ end
69
+
70
+ def send_body
71
+ begin
72
+ @response.body.each { |chunk| send_data(chunk) }
73
+ ensure
74
+ @response.body.close if @response.body.respond_to?(:close)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,96 @@
1
+ module Miniserver
2
+ HTTP_VERSION = 'HTTP/1.1'
3
+ NEWLINE = "\n"
4
+ BLANK_LINE = "\r\n"
5
+ SERVER = 'Server'
6
+ MINISERVER = "Miniserver #{Miniserver::VERSION}"
7
+ CONTENT_LENGTH = 'Content-Length'
8
+ CONTENT_TYPE = 'Content-Type'
9
+ COLON = ':'
10
+ HTTP_PREFIX = 'HTTP_'
11
+ HTTP = 'http'
12
+ HTTPS = 'https'
13
+ EMPTY_STRING = ''
14
+ MINUS = '-'
15
+ UNDERLINE = '_'
16
+ DATE = 'Date'
17
+ CONNECTION = 'Connection'
18
+ KEEP_ALIVE = 'keep-alive'
19
+ CLOSE = 'close'
20
+ HOST = 'Host'
21
+ PORT_80 = '80'
22
+ PATH_INFO = 'PATH_INFO'
23
+ REQUEST_METHOD = 'REQUEST_METHOD'
24
+ REQUEST_PATH = 'REQUEST_PATH'
25
+ SCRIPT_NAME = 'SCRIPT_NAME'
26
+ FRAGMENT = 'FRAGMENT'
27
+ QUERY_STRING = 'QUERY_STRING'
28
+ REMOTE_ADDR = 'REMOTE_ADDR'
29
+ SERVER_NAME = 'SERVER_NAME'
30
+ SERVER_PORT = 'SERVER_PORT'
31
+
32
+ HTTP_CODE = {
33
+ 100 => 'Continue',
34
+ 101 => 'Switching Protocols',
35
+ 102 => 'Processing',
36
+ 200 => 'OK',
37
+ 201 => 'Created',
38
+ 202 => 'Accepted',
39
+ 203 => 'Non-Authoritative Information',
40
+ 204 => 'No Content',
41
+ 205 => 'Reset Content',
42
+ 206 => 'Partial Content',
43
+ 207 => 'Multi-Status',
44
+ 208 => 'Already Reported',
45
+ 226 => 'IM Used',
46
+ 300 => 'Multiple Choices',
47
+ 301 => 'Moved Permanently',
48
+ 302 => 'Found',
49
+ 303 => 'See Other',
50
+ 304 => 'Not Modified',
51
+ 305 => 'Use Proxy',
52
+ 306 => 'Reserved',
53
+ 307 => 'Temporary Redirect',
54
+ 308 => 'Permanent Redirect',
55
+ 400 => 'Bad Request',
56
+ 401 => 'Unauthorized',
57
+ 402 => 'Payment Required',
58
+ 403 => 'Forbidden',
59
+ 404 => 'Not Found',
60
+ 405 => 'Method Not Allowed',
61
+ 406 => 'Not Acceptable',
62
+ 407 => 'Proxy Authentication Required',
63
+ 408 => 'Request Timeout',
64
+ 409 => 'Conflict',
65
+ 410 => 'Gone',
66
+ 411 => 'Length Required',
67
+ 412 => 'Precondition Failed',
68
+ 413 => 'Request Entity Too Large',
69
+ 414 => 'Request-URI Too Long',
70
+ 415 => 'Unsupported Media Type',
71
+ 416 => 'Requested Range Not Satisfiable',
72
+ 417 => 'Expectation Failed',
73
+ 422 => 'Unprocessable Entity',
74
+ 423 => 'Locked',
75
+ 424 => 'Failed Dependency',
76
+ 425 => 'Reserved for WebDAV advanced collections expired proposal',
77
+ 426 => 'Upgrade Required',
78
+ 427 => 'Unassigned',
79
+ 428 => 'Precondition Required',
80
+ 429 => 'Too Many Requests',
81
+ 430 => 'Unassigned',
82
+ 431 => 'Request Header Fields Too Large',
83
+ 500 => 'Internal Server Error',
84
+ 501 => 'Not Implemented',
85
+ 502 => 'Bad Gateway',
86
+ 503 => 'Service Unavailable',
87
+ 504 => 'Gateway Timeout',
88
+ 505 => 'HTTP Version Not Supported',
89
+ 506 => 'Variant Also Negotiates (Experimental)',
90
+ 507 => 'Insufficient Storage',
91
+ 508 => 'Loop Detected',
92
+ 509 => 'Unassigned',
93
+ 510 => 'Not Extended',
94
+ 511 => 'Network Authentication Required'
95
+ }
96
+ end
@@ -0,0 +1,12 @@
1
+ require 'logger'
2
+
3
+ module Miniserver
4
+ class Logger < Logger
5
+ def initialize(*args)
6
+ super
7
+ @formatter = Proc.new do |severity, timestamp, progname, msg|
8
+ "#{String === msg ? msg : msg.inspect}\n"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ module Miniserver
2
+ class Request
3
+ attr_accessor :headers
4
+ attr_accessor :body
5
+ attr_reader :request_path
6
+ attr_reader :http_method
7
+ attr_reader :query_string
8
+ attr_reader :keep_alive
9
+ attr_reader :remote_addr
10
+ attr_reader :server_name
11
+ attr_reader :server_port
12
+ attr_reader :request_url
13
+
14
+ def initialize
15
+ @body = String.new
16
+ @headers = Hash.new
17
+ end
18
+
19
+ def parse_header(parser, socket)
20
+ @request_url = parser.request_url
21
+ @query_string = parser.query_string
22
+ @request_path = parser.request_path
23
+ @http_method = parser.http_method
24
+ @keep_alive = parser.keep_alive?
25
+ @remote_addr = Socket.unpack_sockaddr_in(socket.get_peername)[1]
26
+ @server_name, @server_port = @headers[HOST].split(COLON)
27
+ @server_port ||= PORT_80
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,11 @@
1
+ module Miniserver
2
+ class Response
3
+ attr_reader :status, :headers, :body
4
+
5
+ def parse(status, headers, body)
6
+ @status = status
7
+ @headers = headers
8
+ @body = body
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,64 @@
1
+ module Miniserver
2
+ class Runner
3
+ attr_reader :app, :options
4
+
5
+ def initialize(options)
6
+ @options = options
7
+ end
8
+
9
+ def status
10
+ status = if File.exist?(options[:pid])
11
+ pid = File.open(options[:pid], 'r').read.to_i
12
+
13
+ if Process.running?(pid)
14
+ :Started
15
+ else
16
+ :Stopped
17
+ end
18
+ else
19
+ :Stopped
20
+ end
21
+
22
+ puts status
23
+ end
24
+
25
+ def start
26
+ if File.exist?(options[:pid])
27
+ pid = File.open(options[:pid], 'r').read.to_i
28
+
29
+ if Process.running?(pid)
30
+ raise "Miniserver has started in pid #{pid}."
31
+ else
32
+ File.delete(options[:pid])
33
+ end
34
+ end
35
+
36
+ require 'rack/builder'
37
+
38
+ ENV["RACK_ENV"] = options[:environment]
39
+
40
+ @app = Rack::Builder.new_from_string(File.read(options[:rackup]))
41
+
42
+ Server.new(app, options).start
43
+ end
44
+
45
+ def stop
46
+ if File.exist?(options[:pid])
47
+ pid = File.open(options[:pid], 'r').read.to_i
48
+ Process.kill(:INT, pid)
49
+ File.delete(options[:pid])
50
+ else
51
+ raise 'Miniserver is not running.'
52
+ end
53
+ end
54
+
55
+ def restart
56
+ if File.exist?(options[:pid])
57
+ pid = File.open(options[:pid], 'r').read.to_i
58
+ Process.kill(:HUP, pid)
59
+ else
60
+ raise 'Miniserver is not running.'
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,65 @@
1
+ require 'eventmachine'
2
+ require 'miniserver/connection'
3
+ require 'miniserver/logger'
4
+ require 'fileutils'
5
+
6
+ module Miniserver
7
+ class Server
8
+ attr_reader :app, :options, :script
9
+
10
+ def initialize(app, options={})
11
+ @app = app
12
+ @options = options
13
+ @script = $PROGRAM_NAME
14
+
15
+ FileUtils.mkdir_p(File.dirname(options[:log]))
16
+ Miniserver.logger = Logger.new(options[:log])
17
+ end
18
+
19
+ def start
20
+ Miniserver.logger.info "=> #{Time.now.asctime}"
21
+ Miniserver.logger.info "=> Starting Miniserver #{Miniserver::VERSION}"
22
+ Miniserver.logger.info "=> Listening on #{options[:host]}:#{options[:port]}"
23
+
24
+ if options[:daemonize]
25
+ daemonize_app
26
+ else
27
+ puts "=> Miniserver #{Miniserver::VERSION}"
28
+ puts "=> Listening on #{options[:host]}:#{options[:port]}"
29
+ puts "=> CTRL+C to stop"
30
+ end
31
+
32
+ trap(:INT) { stop }
33
+ trap(:TERM) { stop }
34
+ trap(:HUP) { restart }
35
+
36
+ EM.run do
37
+ EM.start_server(options[:host], options[:port], Connection) do |connection|
38
+ connection.app = app
39
+ end
40
+ end
41
+ end
42
+
43
+ def daemonize_app
44
+ Process.daemon(true)
45
+
46
+ $0 = "Miniserver #{Miniserver::VERSION} (#{options[:host]}:#{options[:port]})"
47
+
48
+ FileUtils.mkdir_p(File.dirname(options[:pid]))
49
+
50
+ File.open(options[:pid], "w") do |f|
51
+ f.puts(Process.pid)
52
+ end
53
+ end
54
+
55
+ def stop
56
+ EM.stop
57
+ end
58
+
59
+ def restart
60
+ stop
61
+
62
+ Command.restart(script, options)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ module Miniserver
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,93 @@
1
+ require 'rack/handler'
2
+ require 'stringio'
3
+
4
+ module Rack
5
+ module Handler
6
+ class Miniserver
7
+ RACK_ERRORS = "rack.errors"
8
+ RACK_INPUT = "rack.input"
9
+ RACK_VERSION = 'rack.version'
10
+ RACK_MULTITHREAD = 'rack.multithread'
11
+ RACK_MULTIPROCESS = 'rack.multiprocess'
12
+ RACK_RUN_ONCE = 'rack.run_once'
13
+ RACK_URL_SCHEME = 'rack.url_scheme'
14
+
15
+ DEFAULT_OPTIONS = {
16
+ daemonize: false,
17
+ Host: '0.0.0.0',
18
+ Port: 8080,
19
+ rackup: ::File.expand_path('config.ru'),
20
+ log: ::File.expand_path('log/miniserver.log'),
21
+ environment: 'development'
22
+ }
23
+
24
+ class << self
25
+ def run(app, options={})
26
+ options = DEFAULT_OPTIONS.merge(options)
27
+
28
+ options[:host] = options.delete(:Host)
29
+ options[:port] = options.delete(:Port)
30
+ options[:daemonize] = false
31
+
32
+ server = ::Miniserver::Server.new(app, options)
33
+
34
+ yield(server) if block_given?
35
+
36
+ server.start
37
+ end
38
+
39
+ def valid_options
40
+ {
41
+ "Host=HOST" => "Hostname to listen on (default: 0.0.0.0)",
42
+ "Port=PORT" => "Port to listen on (default: 8080)",
43
+ }
44
+ end
45
+ end
46
+
47
+ def initialize(app)
48
+ @app = app
49
+ end
50
+
51
+ def process(request, response)
52
+ env = Hash.new
53
+
54
+ request.headers.each_pair do |name, value|
55
+ name = "#{::Miniserver::HTTP_PREFIX}#{name.upcase.tr(::Miniserver::MINUS, ::Miniserver::UNDERLINE)}"
56
+ env[name] = value
57
+ end
58
+
59
+ %w(CONTENT_TYPE CONTENT_LENGTH).each do |name|
60
+ env[name] = env.delete("HTTP_#{name}") if env["HTTP_#{name}"]
61
+ end
62
+
63
+ uri = URI(request.request_url)
64
+
65
+ env[::Miniserver::REQUEST_METHOD] = request.http_method
66
+ env[::Miniserver::REMOTE_ADDR] = request.remote_addr
67
+ env[::Miniserver::SERVER_NAME] = request.server_name
68
+ env[::Miniserver::SERVER_PORT] = request.server_port
69
+ env[::Miniserver::QUERY_STRING] = request.query_string
70
+ env[::Miniserver::REQUEST_PATH] = uri.path
71
+ env[::Miniserver::PATH_INFO] = uri.path
72
+ env[::Miniserver::SCRIPT_NAME] = ::Miniserver::EMPTY_STRING
73
+ env[::Miniserver::FRAGMENT] = uri.fragment || ::Miniserver::EMPTY_STRING
74
+
75
+ env[RACK_ERRORS] = STDERR
76
+ env[RACK_INPUT] = StringIO.new(request.body)
77
+ env[RACK_VERSION] = Rack::VERSION
78
+ env[RACK_MULTITHREAD] = false
79
+ env[RACK_MULTIPROCESS] = false
80
+ env[RACK_RUN_ONCE] = false
81
+ env[RACK_URL_SCHEME] = ::Miniserver::HTTP
82
+
83
+ begin
84
+ response.parse(*@app.call(env))
85
+ ensure
86
+ request.body.clear
87
+ end
88
+ end
89
+ end
90
+
91
+ register :miniserver, Miniserver
92
+ end
93
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'miniserver/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "miniserver"
8
+ spec.version = Miniserver::VERSION
9
+ spec.authors = ["zhouguangming"]
10
+ spec.email = ["zhouguangming1989@gmail.com"]
11
+ spec.description = %q{Miniserver is a simple fast HTTP 1.1 server for Ruby/Rack applications.}
12
+ spec.summary = %q{Miniserver is a simple fast HTTP 1.1 server for Ruby/Rack applications.}
13
+ spec.homepage = "https://github.com/zhouguangming/miniserver"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_dependency 'http_parser.rb'
24
+ spec.add_dependency 'eventmachine'
25
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: miniserver
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - zhouguangming
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: http_parser.rb
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: eventmachine
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Miniserver is a simple fast HTTP 1.1 server for Ruby/Rack applications.
70
+ email:
71
+ - zhouguangming1989@gmail.com
72
+ executables:
73
+ - miniserver
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - bin/miniserver
83
+ - lib/miniserver.rb
84
+ - lib/miniserver/command.rb
85
+ - lib/miniserver/connection.rb
86
+ - lib/miniserver/const.rb
87
+ - lib/miniserver/logger.rb
88
+ - lib/miniserver/request.rb
89
+ - lib/miniserver/response.rb
90
+ - lib/miniserver/runner.rb
91
+ - lib/miniserver/server.rb
92
+ - lib/miniserver/version.rb
93
+ - lib/rack/handler/miniserver.rb
94
+ - miniserver.gemspec
95
+ homepage: https://github.com/zhouguangming/miniserver
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.0.3
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Miniserver is a simple fast HTTP 1.1 server for Ruby/Rack applications.
119
+ test_files: []