9 | 9 |
require 'mmm'
|
10 | 10 |
|
11 | 11 |
import Key, dir_base, load_tree from require 'mmm.mmmfs.fileder'
|
|
12 |
import convert from require 'mmm.mmmfs.conversion'
|
12 | 13 |
import get_store from require 'mmm.mmmfs.stores'
|
13 | 14 |
import decodeURI from require 'http.util'
|
14 | 15 |
|
15 | 16 |
lfs = require 'lfs'
|
16 | 17 |
server = require 'http.server'
|
17 | 18 |
headers = require 'http.headers'
|
18 | |
|
19 | |
tojson = (obj) ->
|
20 | |
switch type obj
|
21 | |
when 'string'
|
22 | |
string.format '%q', obj
|
23 | |
when 'table'
|
24 | |
if obj[1] or not next obj
|
25 | |
"[#{table.concat [tojson c for c in *obj], ','}]"
|
26 | |
else
|
27 | |
"{#{table.concat ["#{tojson k}: #{tojson v}" for k,v in pairs obj], ', '}}"
|
28 | |
when 'number'
|
29 | |
tostring obj
|
30 | |
when 'boolean'
|
31 | |
tostring obj
|
32 | |
when nil
|
33 | |
'null'
|
34 | 19 |
|
35 | 20 |
class Server
|
36 | 21 |
new: (@store, opts={}) =>
|
|
51 | 36 |
|
52 | 37 |
handle: (method, path, facet) =>
|
53 | 38 |
fileder = load_tree @store, path -- @tree\walk path
|
|
39 |
|
|
40 |
if not fileder
|
|
41 |
-- fileder not found
|
|
42 |
404, "fileder '#{path}' not found"
|
|
43 |
|
54 | 44 |
switch method
|
55 | 45 |
when 'GET', 'HEAD'
|
56 | |
if fileder and facet
|
57 | |
-- fileder and facet given
|
58 | |
if not fileder\has_facet facet.name
|
59 | |
return 404, "facet '#{facet.name}' not found in fileder '#{path}'"
|
|
46 |
val = switch facet.name
|
|
47 |
when '?index', '?tree'
|
|
48 |
-- serve fileder index
|
|
49 |
-- '?index': one level deep
|
|
50 |
-- '?tree': recursively
|
|
51 |
index = fileder\get_index facet.name == '?tree'
|
|
52 |
convert 'table', facet.type, index
|
|
53 |
else
|
|
54 |
-- fileder and facet given
|
|
55 |
if not fileder\has_facet facet.name
|
|
56 |
return 404, "facet '#{facet.name}' not found in fileder '#{path}'"
|
60 | 57 |
|
61 | |
val = fileder\get facet
|
62 | |
if val
|
63 | |
200, val
|
64 | |
else
|
65 | |
406, "cant convert facet '#{facet.name}' to '#{facet.type}'"
|
66 | |
elseif fileder
|
67 | |
-- no facet given
|
68 | |
facets = [{k.name, k.type} for k,v in pairs fileder.facets]
|
69 | |
children = [f.path for f in *fileder.children]
|
70 | |
contents = tojson :facets, :children
|
71 | |
200, contents
|
|
58 |
fileder\get facet
|
|
59 |
|
|
60 |
if val
|
|
61 |
200, val
|
72 | 62 |
else
|
73 | |
-- fileder not found
|
74 | |
404, "fileder '#{path}' not found"
|
|
63 |
406, "cant convert facet '#{facet.name}' to '#{facet.type}'"
|
75 | 64 |
else
|
76 | 65 |
501, "not implemented"
|
77 | 66 |
|
|
85 | 74 |
path_facet or= path
|
86 | 75 |
path, facet = path_facet\match '(.*)/([^/]*)'
|
87 | 76 |
|
88 | |
if facet ~= '?index'
|
89 | |
type or= 'text/html'
|
90 | |
type = type\match '%s*(.*)'
|
91 | |
facet = Key facet, type
|
92 | |
else
|
93 | |
facet = nil
|
|
77 |
type or= 'text/html'
|
|
78 |
type = type\match '%s*(.*)'
|
|
79 |
facet = Key facet, type
|
94 | 80 |
|
95 | |
status, body = @handle method, path, facet
|
|
81 |
ok, status, body = pcall @.handle, @, method, path, facet
|
|
82 |
if not ok
|
|
83 |
warn status, body
|
|
84 |
body = "Internal Server Error: #{status}"
|
|
85 |
status = 500
|
96 | 86 |
|
97 | 87 |
res = headers.new!
|
98 | 88 |
response_type = if status > 299 then 'text/plain'
|
|
108 | 98 |
error: (sv, ctx, op, err, errno) =>
|
109 | 99 |
msg = "#{op} on #{tostring ctx} failed"
|
110 | 100 |
msg = "#{msg}: #{err}" if err
|
111 | |
print msg
|
112 | 101 |
|
113 | 102 |
-- usage:
|
114 | 103 |
-- moon server.moon [STORE] [host] [port]
|