nile 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjUwY2UxMmFjNjc1NDJlZTY3NGMxYTUxZDA1MzBkNDBhNzRkZTAzZA==
5
+ data.tar.gz: !binary |-
6
+ NzUzNmM0MDkxMWJhZGVhNGNmODYyNzFmODg3MjZkZmMzODRkNWRlNQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YTQ5MjQzODg3YWVhZjRhMDI1NGI3ODI5NmVhMTIwNjA0N2RkZTEwMWRhNTI3
10
+ N2M0Zjk0ZTQ0NmEwYzJhNTM0MTFlNWE3YTQ0ODBkYjhiZTg5ZTQ0YmRjYWYy
11
+ NWU0NGNhNGVhZmI2M2I0YzVlZTI2OTVlMjcwYTk1OTg3ZWRhZGQ=
12
+ data.tar.gz: !binary |-
13
+ NjQwODliMzAwYjU2OWU4MDQ4ZTE5MmY0OTYzYTBlYWFhMjkwMzZjZGIzMDNj
14
+ M2UzNWFlYzg5MmNkZTk2YzE0MzFmMDc1Nzg5NTcxNTdhNzI0YjhlNjM3NjJm
15
+ ZjU4YTI3ZjQwNDhiZjYxNDg5YjA5ZGM4ZDlmZmIyZjBmNDJmZTk=
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .idea
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2014 Luca Cervasio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Nile webframework
2
+
3
+ A demonstrative and basic ruby webframework implementing http daemon from scratch.
4
+
5
+ You can register a route and return the body:
6
+
7
+ ```ruby
8
+ #!/usr/bin/env ruby
9
+
10
+ require 'nile'
11
+
12
+ n = Nile::Core.new :bind => '0.0.0.0', :port => 7125
13
+ n.get '/' do
14
+ [200, {'Content-Type' => 'text/html'}, ['<h1>Hello Nile !</h1>']]
15
+ end
16
+
17
+ n.post '/status' do |env|
18
+ data = JSON.parse(env[:req][:body])
19
+ puts data
20
+ puts env[:params]
21
+ [200, {'Content-Type' => 'application/json'}, [JSON.pretty_generate({:status => 'ok'})]]
22
+ end
23
+
24
+ n.run
25
+ ```
26
+
27
+ # Using the http daemon
28
+
29
+ Nile includes an http daemon written in pure ruby from scratch, just for didactic purposes.
30
+ You can use it this way:
31
+
32
+ ```ruby
33
+ #!/usr/bin/env ruby
34
+
35
+ require 'nile'
36
+
37
+ class HttpHandler
38
+ def handle req, sock
39
+ [200, {'Content-Type' => 'text/plain'}, ['Hello from Nile !']]
40
+ end
41
+ end
42
+
43
+ http = Nile::HttpServer.new "0.0.0.0", 7125, HttpHandler.new
44
+ http.serve
45
+ ```
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'nile'
4
+
5
+ n = Nile::Core.new :bind => '0.0.0.0', :port => 7125
6
+ n.get '/' do
7
+ [200, {'Content-Type' => 'text/html'}, ['<h1>Hello Nile !</h1>']]
8
+ end
9
+
10
+ n.post '/status' do |env|
11
+ data = JSON.parse(env[:req][:body])
12
+ puts data
13
+ puts env[:params]
14
+ [200, {'Content-Type' => 'application/json'}, [JSON.pretty_generate({:status => 'ok'})]]
15
+ end
16
+
17
+ n.run
data/lib/nile.rb ADDED
@@ -0,0 +1,3 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "nile")
2
+ require 'httpd'
3
+ require 'framework'
@@ -0,0 +1,90 @@
1
+ require 'singleton'
2
+ require 'json'
3
+ require 'httpd'
4
+
5
+ module Nile
6
+
7
+ class Router
8
+ include Singleton
9
+ attr_accessor :routes
10
+
11
+ def initialize
12
+ @routes = []
13
+ end
14
+
15
+ def add_route(verb, url, block)
16
+ @routes << {:verb => verb, :url => url, :cb => block}
17
+ end
18
+
19
+ def find_route verb, url
20
+ @routes.each do |route|
21
+ if route[:url] == url && route[:verb] == verb
22
+ return route
23
+ end
24
+ end
25
+ return {:cb => Proc.new { [404, {}, ["Not found"]] } }
26
+ end
27
+ end
28
+
29
+ class HttpHandler
30
+ def handle req, sock
31
+ start = Time.new
32
+ r = Router.instance
33
+
34
+ querystring = req[:url].split("?")
35
+ params = {}
36
+ if querystring[1].respond_to? :split
37
+ querystring[1].split("&").each do |param|
38
+ param =~ /(\w+)=*(.*)/
39
+ params[$1] = $2
40
+ end
41
+ end
42
+
43
+ route = r.find_route(req[:verb], querystring[0])
44
+ begin
45
+ response = route[:cb].call({:params => params, :req => req})
46
+ rescue Exception => e
47
+ response = [500, {}, ['Internal Server Error: ' + e.message]]
48
+ end
49
+
50
+ response[1]['Server'] = 'Nile 0.1'
51
+ response[1]['Content-Length'] = response[2].join("\n").length
52
+
53
+ return response
54
+ end
55
+ end
56
+
57
+ class Core
58
+ attr_accessor :router
59
+
60
+ def initialize args={}
61
+ args[:port] ||= 7125
62
+ args[:bind] ||= '127.0.0.1'
63
+ @http = Nile::HttpServer.new args[:bind], args[:port], HttpHandler.new
64
+ @router = Router.instance
65
+ end
66
+
67
+ def get url, &block
68
+ @router.add_route "GET", url, block
69
+ end
70
+
71
+ def post url, &block
72
+ @router.add_route "POST", url, block
73
+ end
74
+
75
+ def put url, &block
76
+ @router.add_route "PUT", url, block
77
+ end
78
+
79
+ def delete url, &block
80
+ @router.add_route "DELETE", url, block
81
+ end
82
+
83
+ def run
84
+ @http.serve
85
+ end
86
+
87
+ end
88
+
89
+
90
+ end
data/lib/nile/httpd.rb ADDED
@@ -0,0 +1,83 @@
1
+ require 'socket'
2
+
3
+ Thread::abort_on_exception = true
4
+
5
+ module Nile
6
+
7
+ class HttpServer
8
+
9
+ attr_accessor :bind_address, :port, :cb
10
+
11
+ def initialize (address, port, cb)
12
+ @bind_address = address
13
+ @port = port
14
+ @cb = cb
15
+ end
16
+
17
+ def serve
18
+ webserver = TCPServer.new(@bind_address, @port)
19
+ print "HttpServer running at http://#{@bind_address}:#{@port}\n"
20
+
21
+ while (client = webserver.accept)
22
+
23
+ Thread.start(client) do |client|
24
+ start = Time.new
25
+ req = read_request client
26
+ http_messages = {
27
+ 200 => 'OK',
28
+ 204 => 'No Content',
29
+ 301 => 'Moved Permanently',
30
+ 302 => 'Found',
31
+ 401 => 'Unauthorized',
32
+ 403 => 'Forbidden',
33
+ 404 => 'Not Found',
34
+ 500 => 'Internal Server Error'
35
+ }
36
+ response = @cb.handle req, client
37
+ finish = Time.new
38
+
39
+ print "handling request #{req[:url]} from #{req[:remote_ip]}:#{req[:remote_port]} (#{req[:len]} bytes) --> replying #{response[0]} #{http_messages[response[0]]} (#{response[2].join("\n").length} bytes) in #{((finish - start) * 1000.0).round(2)} ms\n"
40
+
41
+ client.write "HTTP/1.1 #{response[0]} #{http_messages[response[0]]}\r\n"
42
+ response[1].each do |k,v|
43
+ client.write "#{k}: #{v}\r\n"
44
+ end
45
+ client.write "\r\n" + response[2].join("\n")
46
+
47
+ client.close
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+
54
+ def read_request sock
55
+ data = sock.recv 1024
56
+ data =~ /Content-Length: (\d+)/
57
+ content_len = $1.to_i
58
+ split_point = data.index "\r\n\r\n"
59
+
60
+ while data.length - split_point - 4 < content_len
61
+ data += sock.recv 1024
62
+ end
63
+
64
+ headers = data[0..split_point-1].split("\r\n")
65
+ first = headers[0]
66
+ headers.delete_at(0)
67
+ first =~ /(\w+)\ ([\w|\/|\?|\-|\=|\&]+)\ HTTP\//
68
+ verb = $1
69
+ url = $2
70
+
71
+ headers_by_key = {}
72
+ headers.each do |header|
73
+ header =~ /^([\w|\-]+): (.*)/
74
+ headers_by_key[$1] = $2
75
+ end
76
+
77
+ sock_domain, remote_port, remote_hostname, remote_ip = sock.peeraddr
78
+ {:verb => verb, :url => url, :headers => headers_by_key, :body => data[split_point+4..data.length], :remote_ip => remote_ip, :remote_port => remote_port, :len => content_len, :overall_len => data.length}
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -0,0 +1,3 @@
1
+ module Nile
2
+ VERSION = "1.1.3"
3
+ end
data/nile.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ require './lib/nile/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'nile'
5
+ spec.version = Nile::VERSION
6
+ spec.date = Date.today.to_s
7
+ spec.summary = "A demonstrative and basic ruby webframework implementing http daemon from scratch"
8
+ spec.description = "A demonstrative and basic ruby webframework implementing http daemon from scratch"
9
+ spec.authors = ["Luca Cervasio"]
10
+ spec.email = 'luca.cervasio@gmail.com'
11
+ spec.files = `git ls-files`.split($/)
12
+ spec.homepage = 'https://github.com/lucacervasio/nile'
13
+ spec.license = 'MIT'
14
+
15
+ #spec.add_dependency('sourcify', '0.6.0.rc4')
16
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nile
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Luca Cervasio
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-24 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A demonstrative and basic ruby webframework implementing http daemon
14
+ from scratch
15
+ email: luca.cervasio@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .gitignore
21
+ - LICENSE
22
+ - README.md
23
+ - examples/simple.rb
24
+ - lib/nile.rb
25
+ - lib/nile/framework.rb
26
+ - lib/nile/httpd.rb
27
+ - lib/nile/version.rb
28
+ - nile.gemspec
29
+ homepage: https://github.com/lucacervasio/nile
30
+ licenses:
31
+ - MIT
32
+ metadata: {}
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 2.4.6
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: A demonstrative and basic ruby webframework implementing http daemon from
53
+ scratch
54
+ test_files: []