Simple_Server_Example 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rubyversion +1 -0
- data/README.md +19 -1
- data/config.yaml +12 -0
- data/lib/logging.rb +18 -0
- data/lib/response.rb +62 -0
- data/lib/simple_server.rb +23 -44
- data/simple_server.gemspec +1 -1
- data/test/test_response.rb +24 -1
- data/test/test_server.rb +2 -10
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a77ecf7f63b04e47594d3ad66ebdc67479f53588
|
4
|
+
data.tar.gz: 2108026442152fde83486908f3af3b900ed26d76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf8d23d953bd5dd86a6ee176e331532a1eedc04ba1a9d29c2cb03d9044b596e496f7a061317a579d92cab1c73a1783ed9bd7288ee0c3cb13b7a4dd7e1f7f6c07
|
7
|
+
data.tar.gz: 372b3effaa156fe28626885476711398c073f194f5903f390a849472906c3007d7f451ae35c27154422be0cffad00804371e7df8eeee643e1001b85bdfd21e27
|
data/.gitignore
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
.DS_Store
|
1
|
+
.DS_Store
|
2
|
+
log/server.log
|
data/.rubyversion
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.1
|
data/README.md
CHANGED
@@ -1,6 +1,24 @@
|
|
1
1
|
Super Awesome Server
|
2
2
|
=====================================
|
3
3
|
|
4
|
+
Uses Ruby 2.1.1
|
5
|
+
|
6
|
+
Two ways to install this gem.
|
7
|
+
|
8
|
+
First way:
|
9
|
+
|
10
|
+
1. Make sure Ruby and Rubygems are installed
|
11
|
+
|
12
|
+
2. In a terminal type the following to install the gem:
|
13
|
+
``` gem install Simple_Server_Example ```
|
14
|
+
|
15
|
+
3. Open a new terminal and type:
|
16
|
+
``` server ```
|
17
|
+
|
18
|
+
4. Open a broswer and point it to http://localhost:2345
|
19
|
+
|
20
|
+
Second way:
|
21
|
+
|
4
22
|
1. Download this git repo
|
5
23
|
|
6
24
|
2. Inside the root of the repo, build the gem by typing:
|
@@ -12,6 +30,6 @@ Super Awesome Server
|
|
12
30
|
4. Open a new terminal/commandline and run the server:
|
13
31
|
``` server ```
|
14
32
|
|
15
|
-
5. Open a broswer and point it to localhost:2345
|
33
|
+
5. Open a broswer and point it to http://localhost:2345
|
16
34
|
|
17
35
|
6. Party on
|
data/config.yaml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# The only two levels used so far are debug and info.
|
2
|
+
# Will need to impliment warn, error, and fatal.
|
3
|
+
# level: 0 #debug
|
4
|
+
level: 1 #info
|
5
|
+
# level: 2 #warn
|
6
|
+
# level: 3 #error
|
7
|
+
# level: 4 #fatal
|
8
|
+
# level: 5 #unknown
|
9
|
+
|
10
|
+
# The commented output line will default output to the stdout.
|
11
|
+
# Uncomment the line and edit where the logs output to.
|
12
|
+
output: 'log/server.log'
|
data/lib/logging.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class Logging
|
5
|
+
def self.setup
|
6
|
+
log = Logger.new(load_output.nil? ? $stdout : load_output)
|
7
|
+
log.level = set_level
|
8
|
+
return log
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.load_output
|
12
|
+
File.open("config.yaml", "r") { |file| return YAML.load(file)['output'] }
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.set_level
|
16
|
+
File.open("config.yaml", "r") { |file| return YAML.load(file)['level'] }
|
17
|
+
end
|
18
|
+
end
|
data/lib/response.rb
CHANGED
@@ -1,2 +1,64 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
1
3
|
class Response
|
4
|
+
attr_reader :header, :body
|
5
|
+
|
6
|
+
def initialize(header, body)
|
7
|
+
@header = header
|
8
|
+
@body = body
|
9
|
+
end
|
10
|
+
|
11
|
+
RESPONSE_CODE = {
|
12
|
+
'200' => 'OK',
|
13
|
+
'404' => 'Not Found'
|
14
|
+
}
|
15
|
+
|
16
|
+
CONTENT_TYPE_MAPPING = {
|
17
|
+
'html' => 'text/html',
|
18
|
+
'txt' => 'text/plain',
|
19
|
+
'png' => 'image/png',
|
20
|
+
'jpg' => 'image/jpg'
|
21
|
+
}
|
22
|
+
|
23
|
+
DEFAULT_CONTENT_TYPE = 'application/octet-stream'
|
24
|
+
|
25
|
+
NOT_FOUND = './public/404.html'
|
26
|
+
|
27
|
+
def self.build(path)
|
28
|
+
if File.exist?(path) && !File.directory?(path)
|
29
|
+
body, body_size = build_body(path)
|
30
|
+
header = build_header(RESPONSE_CODE.rassoc('OK').join,
|
31
|
+
content_type(path),
|
32
|
+
body_size)
|
33
|
+
Response.new(header, body)
|
34
|
+
else
|
35
|
+
body, body_size = build_body(NOT_FOUND)
|
36
|
+
header = build_header(RESPONSE_CODE.rassoc('Not Found').join,
|
37
|
+
content_type(path),
|
38
|
+
body_size)
|
39
|
+
Response.new(header, body)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.content_type(path)
|
44
|
+
ext = File.extname(path).split('.').last
|
45
|
+
CONTENT_TYPE_MAPPING.fetch(ext, DEFAULT_CONTENT_TYPE)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.build_header(code, type, size)
|
49
|
+
"HTTP/1.1 #{code}\r\n" +
|
50
|
+
"Content-Type: #{type}\r\n" +
|
51
|
+
"Content-Length: #{size}\r\n" +
|
52
|
+
"Connection: close\r\n\r\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.build_body(path)
|
56
|
+
File.open(path, "rb") do |file|
|
57
|
+
return file, file.size
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def stream
|
62
|
+
File.read(self.body)
|
63
|
+
end
|
2
64
|
end
|
data/lib/simple_server.rb
CHANGED
@@ -1,27 +1,19 @@
|
|
1
1
|
require 'socket'
|
2
|
+
require_relative 'logging'
|
2
3
|
require_relative 'request'
|
4
|
+
require_relative 'response'
|
3
5
|
|
4
6
|
class SimpleServer
|
5
|
-
attr_reader :server
|
7
|
+
attr_reader :server, :level, :output
|
6
8
|
|
7
9
|
WEB_ROOT = './public'
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
'txt' => 'text/plain',
|
12
|
-
'png' => 'image/png',
|
13
|
-
'jpg' => 'image/jpg'
|
14
|
-
}
|
15
|
-
|
16
|
-
DEFAULT_CONTENT_TYPE = 'application/octet-stream'
|
11
|
+
LOG = Logging.setup
|
12
|
+
LOG.debug("Logging is set up.")
|
17
13
|
|
18
14
|
def initialize(host='localhost', port=2345)
|
19
15
|
@server = TCPServer.new(host, port)
|
20
|
-
|
21
|
-
|
22
|
-
def content_type(path)
|
23
|
-
ext = File.extname(path).split('.').last
|
24
|
-
CONTENT_TYPE_MAPPING.fetch(ext, DEFAULT_CONTENT_TYPE)
|
16
|
+
LOG.debug("Server is set up.")
|
25
17
|
end
|
26
18
|
|
27
19
|
def clean_path(path)
|
@@ -35,42 +27,29 @@ class SimpleServer
|
|
35
27
|
File.join(WEB_ROOT, *clean)
|
36
28
|
end
|
37
29
|
|
38
|
-
def
|
39
|
-
|
40
|
-
File.open(path, "rb") do |file|
|
41
|
-
socket.print "HTTP/1.1 200 OK\r\n" +
|
42
|
-
"Content-Type: #{content_type(file)}\r\n" +
|
43
|
-
"Content-Length: #{file.size}\r\n" +
|
44
|
-
"Connection: close\r\n"
|
45
|
-
|
46
|
-
socket.print "\r\n"
|
47
|
-
|
48
|
-
IO.copy_stream(file, socket)
|
49
|
-
end
|
50
|
-
else
|
51
|
-
File.open('./public/404.html', "rb") do |file|
|
52
|
-
|
53
|
-
socket.print "HTTP/1.1 404 Not Found\r\n" +
|
54
|
-
"Content-Type: #{content_type(file)}\r\n" +
|
55
|
-
"Content-Length #{file.size}\r\n" +
|
56
|
-
"Connection: close\r\n"
|
57
|
-
|
58
|
-
socket.print "\r\n"
|
59
|
-
|
60
|
-
IO.copy_stream(file, socket)
|
61
|
-
end
|
62
|
-
end
|
30
|
+
def server_info
|
31
|
+
puts "#{'-' * 30}\nWelcome to the Simple Server.\nPlease use CONTROL-C to exit.\n#{'-' * 30}\n\n"
|
63
32
|
end
|
64
33
|
|
65
34
|
def run
|
35
|
+
server_info
|
66
36
|
begin
|
67
37
|
loop do
|
68
38
|
Thread.start(server.accept) do |socket|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
39
|
+
LOG.debug("Accepted socket: #{socket.inspect}")
|
40
|
+
|
41
|
+
request = Request.parse(socket.gets)
|
42
|
+
LOG.debug("Incoming request: #{request.inspect}")
|
43
|
+
|
44
|
+
path = clean_path(request.resource)
|
45
|
+
path = File.join(path, 'index.html') if File.directory?(path)
|
46
|
+
LOG.debug("Requested path: #{path.inspect}")
|
47
|
+
|
48
|
+
response = Response.build(path)
|
49
|
+
socket.print response.header
|
50
|
+
socket.print response.stream
|
51
|
+
LOG.info(response.header)
|
52
|
+
|
74
53
|
socket.close
|
75
54
|
end
|
76
55
|
end
|
data/simple_server.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'Simple_Server_Example'
|
7
|
-
s.version = "0.0
|
7
|
+
s.version = "1.0.0"
|
8
8
|
s.files = `git ls-files`.split($/)
|
9
9
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
10
10
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
data/test/test_response.rb
CHANGED
@@ -1 +1,24 @@
|
|
1
|
-
require '
|
1
|
+
require './lib/response.rb'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
class TestResponse < MiniTest::Test
|
5
|
+
def server
|
6
|
+
SimpleServer.new('localhost', 2346)
|
7
|
+
end
|
8
|
+
|
9
|
+
def request(path)
|
10
|
+
Net::HTTP.get_response(URI(path))
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_content_type_mapping_html
|
14
|
+
assert_equal request('http://localhost:2345').response.content_type, 'text/html'
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_content_type_mapping_for_png
|
18
|
+
assert_equal request('http://localhost:2345/test.png').response.content_type, 'image/png'
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_requested_file_joins_a_resource
|
22
|
+
assert_equal server.clean_path('/index.html'), './public/index.html'
|
23
|
+
end
|
24
|
+
end
|
data/test/test_server.rb
CHANGED
@@ -15,16 +15,8 @@ class TestSimpleServer < MiniTest::Test
|
|
15
15
|
assert_equal request('http://localhost:2345').code, "200"
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
assert_equal request('http://localhost:2345').
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_content_type_mapping_for_png
|
23
|
-
assert_equal request('http://localhost:2345/test.png').response.content_type, 'image/png'
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_requested_file_joins_a_resource
|
27
|
-
assert_equal server.clean_path('/index.html'), './public/index.html'
|
18
|
+
def test_404_from_server
|
19
|
+
assert_equal request('http://localhost:2345/bad_request').code, "404"
|
28
20
|
end
|
29
21
|
|
30
22
|
def test_requested_file_removes_double_periods_from_resource_but_keeps_directories
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Simple_Server_Example
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Neil Northrop
|
@@ -19,10 +19,13 @@ extensions: []
|
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
21
|
- ".gitignore"
|
22
|
+
- ".rubyversion"
|
22
23
|
- README.md
|
23
24
|
- Rakefile
|
24
25
|
- bin/server
|
25
26
|
- bin/test
|
27
|
+
- config.yaml
|
28
|
+
- lib/logging.rb
|
26
29
|
- lib/request.rb
|
27
30
|
- lib/response.rb
|
28
31
|
- lib/simple_server.rb
|