Simple_Server_Example 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: afb5f851b068675773a3e7fc0d52178d9732ee3c
4
+ data.tar.gz: 35de123dfb24039b4869a632c1110110680290f8
5
+ SHA512:
6
+ metadata.gz: 886a4866d3c6cb651847b1785293a6b3cd89ad9d3c938fdb2744121035fc4ca36d702a830db77b5c1a81d87f8ef973540158f2d1a4325ea491b0fa8e776134ec
7
+ data.tar.gz: 8a97d67c2bca9f5e0157d5e120d84425a3f168d0801b9edf36748a0ee19f7d3e2e5ef2f917f2d7ee0709426d43dc2de981a6f25a6b72bd2b59f8acfb6c888149
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .DS_Store
data/README.md ADDED
@@ -0,0 +1,17 @@
1
+ Super Awesome Server
2
+ =====================================
3
+
4
+ 1. Download this git repo
5
+
6
+ 2. Inside the root of the repo, build the gem by typing:
7
+ ``` gem build server.gemspec ```
8
+
9
+ 3. Install the gem by typing:
10
+ ``` gem install server-0.0.1.gem ```
11
+
12
+ 4. Open a new terminal/commandline and run the server:
13
+ ``` server ```
14
+
15
+ 5. Open a broswer and point it to localhost:2345
16
+
17
+ 6. Party on
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |task|
4
+ task.libs << 'test'
5
+ end
6
+
7
+ desc 'Run tests'
8
+ task :default => :test
data/bin/server ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','lib/simple_server.rb'))
3
+
4
+ SimpleServer.new.run
data/bin/test ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+ function onDeath {
3
+ kill $SERVER
4
+ }
5
+ trap onDeath EXIT
6
+
7
+ bin/server 2>/dev/null &
8
+ SERVER=$!
9
+
10
+ rake test
data/lib/request.rb ADDED
@@ -0,0 +1,15 @@
1
+ class Request
2
+ attr_reader :method, :resource, :version
3
+
4
+ def initialize(method, resource, version)
5
+ @method = method
6
+ @resource = resource
7
+ @version = version
8
+ end
9
+
10
+ def self.parse(string)
11
+ pattern = /\A(?<method>\w+)\s+(?<resource>\S+)\s+(?<version>\S+)/
12
+ match = pattern.match(string)
13
+ Request.new(match["method"], match["resource"], match["version"])
14
+ end
15
+ end
data/lib/response.rb ADDED
@@ -0,0 +1,2 @@
1
+ class Response
2
+ end
@@ -0,0 +1,81 @@
1
+ require 'socket'
2
+ require_relative 'request'
3
+
4
+ class SimpleServer
5
+ attr_reader :server
6
+
7
+ WEB_ROOT = './public'
8
+
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'
17
+
18
+ def initialize(host='localhost', port=2345)
19
+ @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)
25
+ end
26
+
27
+ def clean_path(path)
28
+ clean = []
29
+
30
+ parts = path.split("/")
31
+ parts.each do |part|
32
+ next if part.empty? || part == '.'
33
+ part == '..' ? clean.pop : clean << part
34
+ end
35
+ File.join(WEB_ROOT, *clean)
36
+ end
37
+
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
63
+ end
64
+
65
+ def run
66
+ begin
67
+ loop do
68
+ 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)
74
+ socket.close
75
+ end
76
+ end
77
+ rescue Interrupt
78
+ puts "\nExiting...Thank you for using this super awesome server."
79
+ end
80
+ end
81
+ end
data/public/404.html ADDED
@@ -0,0 +1,10 @@
1
+ <html>
2
+ <head>
3
+ <title>
4
+ Page not found
5
+ </title>
6
+ </head>
7
+ <body>
8
+ <h1>404: Page Not Found!</h1>
9
+ </body>
10
+ </html>
data/public/index.html ADDED
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Hello World</title>
5
+ </head>
6
+ <body>
7
+ <h1>HELLO WORLD!</h1>
8
+ </body>
9
+ </html>
data/public/test.png ADDED
Binary file
@@ -0,0 +1,19 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'Simple_Server_Example'
7
+ s.version = "0.0.1"
8
+ s.files = `git ls-files`.split($/)
9
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
10
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
11
+ s.require_paths = ["lib"]
12
+ s.date = '2014-10-15'
13
+ s.summary = "Simple Server Example"
14
+ s.description = "A simple web server by me"
15
+ s.authors = ["Neil Northrop"]
16
+ s.email = 'nnorthrop@gmail.com'
17
+ s.homepage = 'http://www.example.com'
18
+ s.license = 'MIT'
19
+ end
@@ -0,0 +1,18 @@
1
+ require './lib/request'
2
+ require 'minitest/autorun'
3
+
4
+ class TestRequest < MiniTest::Test
5
+ def test_that_request_parser_returns_method
6
+ match = Request.parse('GET /index.html HTTP/1.1')
7
+ assert_equal match.method, 'GET'
8
+ assert_equal match.resource, '/index.html'
9
+ assert_equal match.version, 'HTTP/1.1'
10
+ end
11
+
12
+ def test_that_request_parser_ignores_body
13
+ match = Request.parse("GET /index.html HTTP/1.1\n Accept: This and that\n Body: GET /index2.html HTTP/1.90")
14
+ assert_equal match.method, 'GET'
15
+ assert_equal match.resource, '/index.html'
16
+ assert_equal match.version, 'HTTP/1.1'
17
+ end
18
+ end
@@ -0,0 +1 @@
1
+ require 'minitest/autorun'
@@ -0,0 +1,37 @@
1
+ require 'net/http'
2
+ require './lib/simple_server'
3
+ require 'minitest/autorun'
4
+
5
+ class TestSimpleServer < MiniTest::Test
6
+ def server
7
+ SimpleServer.new('localhost', 2346)
8
+ end
9
+
10
+ def request(path)
11
+ Net::HTTP.get_response(URI(path))
12
+ end
13
+
14
+ def test_hello_world_from_server
15
+ assert_equal request('http://localhost:2345').code, "200"
16
+ end
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'
28
+ end
29
+
30
+ def test_requested_file_removes_double_periods_from_resource_but_keeps_directories
31
+ assert_equal server.clean_path('/../../../hello/index.html'), './public/hello/index.html'
32
+ end
33
+
34
+ def test_requested_file_removes_double_periods_from_resource
35
+ assert_equal server.clean_path('/../../hello/../index.html'), './public/index.html'
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Simple_Server_Example
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Neil Northrop
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-15 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple web server by me
14
+ email: nnorthrop@gmail.com
15
+ executables:
16
+ - server
17
+ - test
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".gitignore"
22
+ - README.md
23
+ - Rakefile
24
+ - bin/server
25
+ - bin/test
26
+ - lib/request.rb
27
+ - lib/response.rb
28
+ - lib/simple_server.rb
29
+ - public/404.html
30
+ - public/index.html
31
+ - public/test.png
32
+ - simple_server.gemspec
33
+ - test/test_request.rb
34
+ - test/test_response.rb
35
+ - test/test_server.rb
36
+ homepage: http://www.example.com
37
+ licenses:
38
+ - MIT
39
+ metadata: {}
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubyforge_project:
56
+ rubygems_version: 2.3.0
57
+ signing_key:
58
+ specification_version: 4
59
+ summary: Simple Server Example
60
+ test_files:
61
+ - test/test_request.rb
62
+ - test/test_response.rb
63
+ - test/test_server.rb