knod 0.6.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/Readme.md +2 -2
- data/knod.gemspec +1 -1
- data/lib/knod.rb +1 -4
- data/lib/knod/file_utilities.rb +6 -0
- data/lib/knod/patch_merge.rb +2 -3
- data/lib/knod/request.rb +3 -3
- data/lib/knod/server.rb +20 -19
- data/lib/knod/version.rb +1 -1
- data/test/test_knod.rb +19 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8446a5531fc6d08eb78e71e980168a931d1ac919
|
4
|
+
data.tar.gz: d52ad8908dc15d28be4be47c0730ab173c701209
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b9a3ef52a2dab0171621c4ee32f19b1f6d1e3e0dc46e04ff037b8e7d0274059ccc1801e6b74f49ff4be9d9b30e00a1e52167812117162083b2f1f08606ea432
|
7
|
+
data.tar.gz: fc1a4437cf870a38032161a4b9159d43e8fbe0e35727cfd826d0b3aafebad05f838918d98ad96515794777f0eed3936f978ebe2b150bf603239e6293c12fd87f
|
data/Gemfile.lock
CHANGED
data/Readme.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/knod.svg)](http://badge.fury.io/rb/knod) [![Build Status](https://travis-ci.org/moserrya/knod.svg?branch=master)](https://travis-ci.org/moserrya/knod) [![Code Climate](https://codeclimate.com/github/moserrya/knod.png)](https://codeclimate.com/github/moserrya/knod)
|
4
4
|
|
5
|
-
Knod is a
|
5
|
+
Knod is a simple HTTP server for prototyping rich JavaScript apps. It responds to GET, PUT, POST, PATCH, and DELETE, serving up, writing to, and deleting from the directory of your choice. Knod has no dependencies outside of the Ruby standard library.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -23,7 +23,7 @@ Logging is enabled by default. The server will select an open ephemeral port at
|
|
23
23
|
|
24
24
|
Knod sanitizes the path on all requests and does not allow access to folders outside of the root directory where it is run.
|
25
25
|
|
26
|
-
GET
|
26
|
+
If the path for a GET request is a file, file will be mapped to its MIME type based on the file suffix. Data is considered to be `application/octet-stream` if the content type is unrecognized. If the path for a GET request is a directory, Knod will concatenate the contents of all files in the directory into a JSON array.
|
27
27
|
|
28
28
|
All data from PUT, POST, and PATCH requests is stored as JSON. If the pathway specified in the request does not exist, Knod will create it.
|
29
29
|
|
data/knod.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'knod/version'
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = 'knod'
|
8
8
|
gem.version = Knod::VERSION
|
9
|
-
gem.date = '2014-06-
|
9
|
+
gem.date = '2014-06-15'
|
10
10
|
gem.authors = ['Ryan Moser']
|
11
11
|
gem.email = 'ryanpmoser@gmail.com'
|
12
12
|
gem.homepage = 'https://github.com/moserrya/knod'
|
data/lib/knod.rb
CHANGED
data/lib/knod/file_utilities.rb
CHANGED
@@ -14,5 +14,11 @@ module Knod
|
|
14
14
|
def file_extension(path)
|
15
15
|
File.extname(path).split('.').last
|
16
16
|
end
|
17
|
+
|
18
|
+
def concat_json(path)
|
19
|
+
files = Dir.glob(join_path(path, "*"))
|
20
|
+
data = files.map { |f| File.read(f) }
|
21
|
+
json_data = '[' + data.join(',') + ']'
|
22
|
+
end
|
17
23
|
end
|
18
24
|
end
|
data/lib/knod/patch_merge.rb
CHANGED
@@ -5,17 +5,16 @@ module HashWithPatchMerge
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def patch_merge!(other_hash, &block)
|
8
|
-
other_hash.each_pair do |k,v|
|
8
|
+
other_hash.each_pair do |k, v|
|
9
9
|
tv = self[k]
|
10
10
|
if tv.is_a?(Hash) && v.is_a?(Hash)
|
11
11
|
self[k] = tv.patch_merge(v, &block)
|
12
12
|
else
|
13
13
|
self[k] = block && tv ? block.call(k, tv, v) : v
|
14
|
-
|
14
|
+
delete(k) if self[k].nil?
|
15
15
|
end
|
16
16
|
end
|
17
17
|
self
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
data/lib/knod/request.rb
CHANGED
@@ -13,18 +13,18 @@ module Knod
|
|
13
13
|
loop do
|
14
14
|
line = socket.gets
|
15
15
|
break if line == "\r\n"
|
16
|
-
name, value = line.strip.split(
|
16
|
+
name, value = line.strip.split(': ')
|
17
17
|
headers[name] = value
|
18
18
|
end
|
19
19
|
@headers = headers
|
20
20
|
end
|
21
21
|
|
22
22
|
def content_length
|
23
|
-
headers[
|
23
|
+
headers['Content-Length'].to_i
|
24
24
|
end
|
25
25
|
|
26
26
|
def content_type
|
27
|
-
headers[
|
27
|
+
headers['Content-Type']
|
28
28
|
end
|
29
29
|
|
30
30
|
def uri
|
data/lib/knod/server.rb
CHANGED
@@ -7,7 +7,7 @@ module Knod
|
|
7
7
|
DEFAULT_PORT = 4444
|
8
8
|
DEFAULT_WEB_ROOT = './'
|
9
9
|
|
10
|
-
def initialize(options={})
|
10
|
+
def initialize(options = {})
|
11
11
|
port = options.fetch(:port) { DEFAULT_PORT }
|
12
12
|
@root = options.fetch(:root) { DEFAULT_WEB_ROOT }
|
13
13
|
@logging = options.fetch(:logging) { true }
|
@@ -34,15 +34,16 @@ module Knod
|
|
34
34
|
socket.close if socket
|
35
35
|
end
|
36
36
|
|
37
|
-
def do_GET(head=false)
|
37
|
+
def do_GET(head = false)
|
38
38
|
path = requested_path
|
39
|
-
path = join_path(path, 'index.html') if directory?(path)
|
40
39
|
|
41
40
|
if file?(path)
|
42
41
|
File.open(path, 'rb') do |file|
|
43
42
|
socket.print file_response_header(file)
|
44
43
|
IO.copy_stream(file, socket) unless head
|
45
44
|
end
|
45
|
+
elsif directory?(path)
|
46
|
+
respond(200, concat_json(path))
|
46
47
|
else
|
47
48
|
message = head ? '' : "\"File not found\""
|
48
49
|
respond(404, message)
|
@@ -50,7 +51,7 @@ module Knod
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def do_HEAD
|
53
|
-
do_GET(head=true)
|
54
|
+
do_GET(head = true)
|
54
55
|
end
|
55
56
|
|
56
57
|
def do_DELETE
|
@@ -100,8 +101,8 @@ module Knod
|
|
100
101
|
end
|
101
102
|
|
102
103
|
def max_id_in_path(path)
|
103
|
-
records = Dir.glob(path +
|
104
|
-
records.map {|r| File.basename(r,
|
104
|
+
records = Dir.glob(path + '/*.json')
|
105
|
+
records.map { |r| File.basename(r, '.json') }.map(&:to_i).max || 0
|
105
106
|
end
|
106
107
|
|
107
108
|
def merge_json(file, request_body)
|
@@ -119,12 +120,12 @@ module Knod
|
|
119
120
|
end
|
120
121
|
|
121
122
|
STATUS_CODE_MAPPINGS = {
|
122
|
-
200 =>
|
123
|
-
201 =>
|
124
|
-
204 =>
|
125
|
-
404 =>
|
126
|
-
500 =>
|
127
|
-
501 =>
|
123
|
+
200 => 'OK',
|
124
|
+
201 => 'Created',
|
125
|
+
204 => 'No Content',
|
126
|
+
404 => 'Not Found',
|
127
|
+
500 => 'Internal Server Error',
|
128
|
+
501 => 'Not Implemented'
|
128
129
|
}
|
129
130
|
|
130
131
|
def response_header(status_code, message)
|
@@ -134,15 +135,15 @@ module Knod
|
|
134
135
|
header << "Connection: close\r\n\r\n"
|
135
136
|
end
|
136
137
|
|
137
|
-
def respond(status_code, message='')
|
138
|
+
def respond(status_code, message = '')
|
138
139
|
socket.print response_header(status_code, message)
|
139
140
|
socket.print message unless message.empty?
|
140
141
|
end
|
141
142
|
|
142
143
|
def file_response_header(file)
|
143
|
-
"HTTP/1.1 200 OK\r\n"
|
144
|
-
"Content-Type: #{content_type(file)}\r\n"
|
145
|
-
"Content-Length: #{file.size}\r\n"
|
144
|
+
"HTTP/1.1 200 OK\r\n" \
|
145
|
+
"Content-Type: #{content_type(file)}\r\n" \
|
146
|
+
"Content-Length: #{file.size}\r\n" \
|
146
147
|
"Connection: close\r\n\r\n"
|
147
148
|
end
|
148
149
|
|
@@ -170,7 +171,7 @@ module Knod
|
|
170
171
|
|
171
172
|
clean = []
|
172
173
|
|
173
|
-
parts = local_path.split(
|
174
|
+
parts = local_path.split('/')
|
174
175
|
|
175
176
|
parts.each do |part|
|
176
177
|
next if part.empty? || part == '.'
|
@@ -181,8 +182,8 @@ module Knod
|
|
181
182
|
end
|
182
183
|
|
183
184
|
def method_missing(method_sym, *args, &block)
|
184
|
-
if method_sym.to_s.start_with?(
|
185
|
-
respond(501, "
|
185
|
+
if method_sym.to_s.start_with?('do_')
|
186
|
+
respond(501, '"not implemented"')
|
186
187
|
else
|
187
188
|
super
|
188
189
|
end
|
data/lib/knod/version.rb
CHANGED
data/test/test_knod.rb
CHANGED
@@ -37,11 +37,6 @@ describe Knod, "a tiny http server" do
|
|
37
37
|
response.body.must_equal @body
|
38
38
|
end
|
39
39
|
|
40
|
-
it 'implictly serves up the index' do
|
41
|
-
response = connection.get "/"
|
42
|
-
response.body.must_equal @body
|
43
|
-
end
|
44
|
-
|
45
40
|
it 'returns a 404 if the file does not exist' do
|
46
41
|
response = connection.get "/squidbat.random"
|
47
42
|
response.code.must_equal '404'
|
@@ -66,6 +61,25 @@ describe Knod, "a tiny http server" do
|
|
66
61
|
response = connection.delete @path
|
67
62
|
response.code.must_equal '204'
|
68
63
|
end
|
64
|
+
|
65
|
+
describe 'contatenates files into a json array' do
|
66
|
+
let(:path) {'index'}
|
67
|
+
let(:data) { 3.times.map { |i| { id: i+1, state: 'squiddy' } } }
|
68
|
+
|
69
|
+
before do
|
70
|
+
FileUtils.mkdir_p(path)
|
71
|
+
data.each_with_index {|d, i| File.write(File.join(".", path, "#{i+1}.json"), d.to_json)}
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should concatenate file contents into an array' do
|
75
|
+
response = connection.get path
|
76
|
+
response.body.sort_by { |h| h[:id] }.must_equal data
|
77
|
+
end
|
78
|
+
|
79
|
+
after do
|
80
|
+
FileUtils.remove_entry(path, true)
|
81
|
+
end
|
82
|
+
end
|
69
83
|
end
|
70
84
|
|
71
85
|
describe 'PUT' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Moser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|