class Knod::Server
Constants
- CONTENT_TYPE_MAPPING
- DEFAULT_CONTENT_TYPE
- DEFAULT_PORT
- DEFAULT_WEB_ROOT
- STATUS_CODE_MAPPINGS
Attributes
client[R]
request[R]
server[R]
Public Class Methods
new(options = {})
click to toggle source
# File lib/knod/server.rb, line 10 def initialize(options = {}) port = options.fetch(:port) { DEFAULT_PORT } @root = options.fetch(:root) { DEFAULT_WEB_ROOT } @logging = options.fetch(:logging) { true } @server = TCPServer.new('0.0.0.0', port) end
Public Instance Methods
accept_request_and_respond(client)
click to toggle source
# File lib/knod/server.rb, line 26 def accept_request_and_respond(client) @client = client @request = Request.new(client) log request_line public_send "do_#{request.method}" rescue => e log "#{e.class}: #{e.message}" log e.backtrace respond 500 ensure client.close if client end
do_DELETE()
click to toggle source
# File lib/knod/server.rb, line 59 def do_DELETE path = requested_path delete_file(path) if file?(path) respond 204 end
do_GET(head = false)
click to toggle source
# File lib/knod/server.rb, line 39 def do_GET(head = false) path = requested_path if file?(path) File.open(path, 'rb') do |file| client.print file_response_header(file) IO.copy_stream(file, client) unless head end elsif directory?(path) respond(200, concat_json(path)) else message = head ? '' : "\"File not found\"" respond(404, message) end end
do_HEAD()
click to toggle source
# File lib/knod/server.rb, line 55 def do_HEAD do_GET(head = true) end
do_PATCH()
click to toggle source
# File lib/knod/server.rb, line 72 def do_PATCH path = requested_path data = if file?(path) merge_json(read_file(path), request.body) else request.body end write_to_path(path, data) respond(200, "\"Success\"") end
do_POST()
click to toggle source
# File lib/knod/server.rb, line 83 def do_POST path = requested_path create_directory(path) next_id = max_id_in_path(path) + 1 write_file(join_path(path, "#{next_id}.json"), request.body) respond(201, "{\"id\":#{next_id}}") end
do_PUT()
click to toggle source
# File lib/knod/server.rb, line 65 def do_PUT write_to_path(requested_path, request.body) respond(200, "\"Success\"") end
port()
click to toggle source
# File lib/knod/server.rb, line 91 def port server.addr[1] end
start()
click to toggle source
# File lib/knod/server.rb, line 17 def start log "Starting server on port #{port}" loop do Thread.start(server.accept) do |client| dup.accept_request_and_respond(client) end end end
Private Instance Methods
content_type(path)
click to toggle source
# File lib/knod/server.rb, line 166 def content_type(path) ext = file_extension(path) CONTENT_TYPE_MAPPING.fetch(ext) { DEFAULT_CONTENT_TYPE } end
file_response_header(file)
click to toggle source
# File lib/knod/server.rb, line 144 def file_response_header(file) "HTTP/1.1 200 OK\r\n" \ "Content-Type: #{content_type(file)}\r\n" \ "Content-Length: #{file.size}\r\n" \ "Access-Control-Allow-Origin: *\r\n" \ "Connection: close\r\n\r\n" end
log(message)
click to toggle source
# File lib/knod/server.rb, line 114 def log(message) STDERR.puts message if @logging end
max_id_in_path(path)
click to toggle source
# File lib/knod/server.rb, line 103 def max_id_in_path(path) records = Dir.glob(path + '/*.json') records.map { |r| File.basename(r, '.json').to_i }.max || 0 end
merge_json(file, request_body)
click to toggle source
# File lib/knod/server.rb, line 108 def merge_json(file, request_body) file = JSON.parse(file) request_body = JSON.parse(request_body) file.patch_merge(request_body).to_json end
method_missing(method_sym, *args, &block)
click to toggle source
Calls superclass method
# File lib/knod/server.rb, line 186 def method_missing(method_sym, *args, &block) if method_sym.to_s.start_with?('do_') respond(501, '"not implemented"') else super end end
request_line()
click to toggle source
# File lib/knod/server.rb, line 118 def request_line request.request_line end
requested_path()
click to toggle source
# File lib/knod/server.rb, line 171 def requested_path local_path = URI.unescape(URI(request.uri).path) clean = [] parts = local_path.split('/') parts.each do |part| next if part.empty? || part == '.' part == '..' ? clean.pop : clean << part end File.join(@root, *clean) end
respond(status_code, message = '')
click to toggle source
# File lib/knod/server.rb, line 139 def respond(status_code, message = '') client.print response_header(status_code, message) client.print message unless message.empty? end
response_header(status_code, message)
click to toggle source
# File lib/knod/server.rb, line 131 def response_header(status_code, message) header = "HTTP/1.1 #{status_code} #{STATUS_CODE_MAPPINGS.fetch(status_code)}\r\n" header << "Content-Type: application/json\r\n" unless message.empty? header << "Content-Length: #{message.size}\r\n" header << "Access-Control-Allow-Origin: *\r\n" header << "Connection: close\r\n\r\n" end
write_to_path(path, data)
click to toggle source
# File lib/knod/server.rb, line 97 def write_to_path(path, data) directory_name = dirname(path) create_directory(directory_name) write_file(path, data) end