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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: afb5f851b068675773a3e7fc0d52178d9732ee3c
4
- data.tar.gz: 35de123dfb24039b4869a632c1110110680290f8
3
+ metadata.gz: a77ecf7f63b04e47594d3ad66ebdc67479f53588
4
+ data.tar.gz: 2108026442152fde83486908f3af3b900ed26d76
5
5
  SHA512:
6
- metadata.gz: 886a4866d3c6cb651847b1785293a6b3cd89ad9d3c938fdb2744121035fc4ca36d702a830db77b5c1a81d87f8ef973540158f2d1a4325ea491b0fa8e776134ec
7
- data.tar.gz: 8a97d67c2bca9f5e0157d5e120d84425a3f168d0801b9edf36748a0ee19f7d3e2e5ef2f917f2d7ee0709426d43dc2de981a6f25a6b72bd2b59f8acfb6c888149
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
- CONTENT_TYPE_MAPPING = {
10
- 'html' => 'text/html',
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
- end
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 request(path, socket)
39
- if File.exist?(path) && !File.directory?(path)
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
- request = Request.parse(socket.gets)
70
- STDERR.puts request
71
- path = clean_path(request.resource)
72
- path = File.join(path, 'index.html') if File.directory?(path)
73
- request(path, socket)
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
@@ -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.1"
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)/})
@@ -1 +1,24 @@
1
- require 'minitest/autorun'
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 test_content_type_mapping_html
19
- assert_equal request('http://localhost:2345').response.content_type, 'text/html'
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.1
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