git.s-ol.nu mmm / b36a1a6
?index and ?tree as real facets with typecasting to application/json s-ol 3 years ago
4 changed file(s) with 82 addition(s) and 41 deletion(s). Raw diff Collapse all Expand all
99 require 'mmm'
1010
1111 import Key, dir_base, load_tree from require 'mmm.mmmfs.fileder'
12 import convert from require 'mmm.mmmfs.conversion'
1213 import get_store from require 'mmm.mmmfs.stores'
1314 import decodeURI from require 'http.util'
1415
1516 lfs = require 'lfs'
1617 server = require 'http.server'
1718 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'
3419
3520 class Server
3621 new: (@store, opts={}) =>
5136
5237 handle: (method, path, facet) =>
5338 fileder = load_tree @store, path -- @tree\walk path
39
40 if not fileder
41 -- fileder not found
42 404, "fileder '#{path}' not found"
43
5444 switch method
5545 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}'"
6057
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
7262 else
73 -- fileder not found
74 404, "fileder '#{path}' not found"
63 406, "cant convert facet '#{facet.name}' to '#{facet.type}'"
7564 else
7665 501, "not implemented"
7766
8574 path_facet or= path
8675 path, facet = path_facet\match '(.*)/([^/]*)'
8776
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
9480
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
9686
9787 res = headers.new!
9888 response_type = if status > 299 then 'text/plain'
10898 error: (sv, ctx, op, err, errno) =>
10999 msg = "#{op} on #{tostring ctx} failed"
110100 msg = "#{msg}: #{err}" if err
111 print msg
112101
113102 -- usage:
114103 -- moon server.moon [STORE] [host] [port]
5454
5555 value
5656
57 -- find and apply a conversion path from 'have' to 'want'
58 -- * have - start type string or list of type strings
59 -- * want - stop type pattern
60 -- * value - value or map from have-types to values
61 -- returns converted value
62 convert = (have, want, value, ...) ->
63 conversions, start = get_conversions want, have
64
65 if not conversions
66 warn "couldn't convert from '#{have}' to '#{want}'"
67 return
68
69 if 'string' ~= type have
70 value = value[start]
71
72 apply_conversions conversions, value, ...
73
5774 {
5875 :converts
5976 :get_conversions
6077 :apply_conversions
78 :convert
6179 }
210210 out: 'URL -> %1',
211211 transform: (_, fileder, key) => "#{fileder.path}/#{key.name}:#{@from}"
212212 },
213 {
214 inp: 'table',
215 out: 'application/json',
216 transform: do
217 tojson = (obj) ->
218 switch type obj
219 when 'string'
220 string.format '%q', obj
221 when 'table'
222 if obj[1] or not next obj
223 "[#{table.concat [tojson c for c in *obj], ','}]"
224 else
225 "{#{table.concat ["#{tojson k}: #{tojson v}" for k,v in pairs obj], ', '}}"
226 when 'number'
227 tostring obj
228 when 'boolean'
229 tostring obj
230 when 'nil'
231 'null'
232 else
233 error "unknown type '#{type obj}'"
234
235 (val) => tojson val
236 }
213237 }
214238
215239 if MODE == 'SERVER'
121121
122122 [name for name in pairs names]
123123
124 get_index: (recursive=false) =>
125 {
126 path: @path
127 facets: [{k.name, k.type} for k,v in pairs @facets]
128 children: if recursive
129 [child\get_index true for child in *@children]
130 else
131 [{ :path } for { :path } in *@children]
132 }
133
124134 -- check whether a facet is directly available
125135 -- when passing a Key, set type to false to check for name only
126136 has: (...) =>