@@ -5,39 +5,33 @@ local utf8 = require("utf8")
55-- lib Path
66local PATH = (... ):gsub (" %.init$" , " " )
77
8- local inspect = require (PATH .. " .lib.inspect" )
9- local json = require (PATH .. " .lib.json" )
108local Class = require (PATH .. " .lib.class" )
119local errorhandler = require (PATH .. " .error_handler" )
12- local get_current_dir = require (PATH .. " .utils" ).get_current_dir
1310local Performance = require (PATH .. " .plugins.performance" )
1411local FeatherPluginManager = require (PATH .. " .plugin_manager" )
12+ local FeatherLogger = require (PATH .. " .plugins.logger" )
13+ local get_current_dir = require (PATH .. " .utils" ).get_current_dir
14+ local format = require (PATH .. " .utils" ).format
15+ local serverUtils = require (PATH .. " .server_utils" )
1516
1617local performance = Performance ()
1718
18- local logs = {}
1919local FEATHER_VERSION = " 0.2.0"
2020
2121--- @class Feather : FeatherConfig
2222--- @field lastDelivery number
2323--- @field lastError number
2424--- @field debug boolean
25+ --- @field featherLogger FeatherLogger
2526--- @field protected server any
2627--- @field observe fun ( self : Feather , key : string , value : table | string | number | boolean ) Updates value in the observers tab
27- --- @field log fun ( self : Feather , line : FeatherLine ) Logs a line
2828--- @field finish fun ( self : Feather ) Logs a finish line
2929--- @field print fun ( self : Feather , ... ) Prints a log
3030--- @field trace fun ( self : Feather , ... ) Prints a trace
3131--- @field error fun ( self : Feather , msg : string ) Prints an error
3232--- @field update fun ( self : Feather , dt : number ) Updates the Feather instance
33- --- @field protected __print fun (self : Feather , type : string , str : string )
34- --- @field protected __countOnRepeat fun (self : Feather , type : LogType , ... : unknown )
3533--- @field protected __onerror fun (self : Feather , msg : string , finish : boolean )
3634--- @field protected __getConfig fun (self : Feather ): FeatherConfig
37- --- @field protected __buildResponse fun (self : Feather , body : table | string | number ): string
38- --- @field protected __buildRequest fun (self : Feather , request : table ): table
39- --- @field protected __format fun (self : Feather , ... : any ): string
40- --- @field protected __isInWhitelist fun (self : Feather , addr : string ): boolean
4135--- @field protected __defaultObservers fun (self : Feather )
4236--- @field protected __errorTraceback fun (self : Feather , msg : string ): string
4337local Feather = Class ({})
@@ -92,6 +86,9 @@ function Feather:init(config)
9286 print (" Listening on " .. self .addr .. " :" .. self .port )
9387 self .server :settimeout (0 )
9488
89+ --- @type FeatherLogger
90+ self .featherLogger = FeatherLogger (self )
91+
9592 if self .autoRegisterErrorHandler then
9693 local selfRef = self -- capture `self` to avoid upvalue issues
9794
@@ -115,34 +112,7 @@ function Feather:init(config)
115112 end
116113 end
117114
118- -- Wrap print
119- self .logger = print
120- if self .wrapPrint then
121- local logger = print
122-
123- local selfRef = self -- capture `self` to avoid upvalue issues
124-
125- --
126- print = function (...)
127- logger (... )
128- selfRef .print (self , ... )
129- end
130- end
131-
132- self .pluginManager = FeatherPluginManager (self , logs )
133- end
134-
135- function Feather :__buildResponse (body )
136- local response = table.concat ({
137- " HTTP/1.1 200 OK" ,
138- " Content-Type: application/json" ,
139- " Access-Control-Allow-Origin: *" ,
140- " Content-Length: " .. # body ,
141- " " ,
142- body ,
143- }, " \r\n " )
144-
145- return response
115+ self .pluginManager = FeatherPluginManager (self , self .featherLogger )
146116end
147117
148118function Feather :__getConfig ()
@@ -152,58 +122,15 @@ function Feather:__getConfig()
152122 root_path = root_path .. " /" .. self .baseDir
153123 end
154124
155- local pluginKeys = {}
156-
157- for _ , plugin in ipairs (self .plugins ) do
158- table.insert (pluginKeys , plugin .identifier )
159- end
160-
161125 local config = {
162- plugins = pluginKeys ,
126+ plugins = self . pluginManager : getConfig () ,
163127 root_path = root_path ,
164128 version = FEATHER_VERSION ,
165129 }
166130
167131 return config
168132end
169133
170- --- Builds a request object from a raw request string
171- --- @param request string
172- --- @return table
173- function Feather :__buildRequest (request )
174- local method , pathWithQuery = request :match (" ^(%u+)%s+([^%s]+)" )
175- local path , queryString = pathWithQuery :match (" ^([^?]+)%??(.*)$" )
176- local function parseQuery (qs )
177- local params = {}
178- for key , val in qs :gmatch (" ([^&=?]+)=([^&=?]+)" ) do
179- params [key ] = val
180- end
181- return params
182- end
183-
184- local params = parseQuery (queryString )
185-
186- return {
187- method = method ,
188- path = path ,
189- params = params ,
190- }
191- end
192-
193- function Feather :__format (...)
194- return inspect (... , { newline = " \n " , indent = " \t " })
195- end
196-
197- function Feather :__isInWhitelist (addr )
198- for _ , a in pairs (self .whitelist ) do
199- local ptn = " ^" .. a :gsub (" %." , " %%." ):gsub (" %*" , " %%d*" ) .. " $"
200- if addr :match (ptn ) then
201- return true
202- end
203- end
204- return false
205- end
206-
207134function Feather :__defaultObservers ()
208135 self :observe (" Global" , _G )
209136 self :observe (" Lua Version" , _VERSION )
@@ -250,9 +177,9 @@ function Feather:__onerror(msg, finish)
250177 end
251178
252179 local err = self :__errorTraceback (msg )
253- self :log ({ type = " error" , str = self :__errorTraceback (msg ) })
180+ self . featherLogger :log ({ type = " error" , str = self :__errorTraceback (msg ) })
254181 if self .wrapPrint then
255- self .logger (" [Feather] ERROR: " .. err )
182+ self .featherLogger . logger (" [Feather] ERROR: " .. err )
256183 end
257184 self .lastError = os.time ()
258185 self .pluginManager :onerror (msg , self )
@@ -272,7 +199,7 @@ function Feather:observe(key, value)
272199
273200 self .observers = self .observers or {}
274201
275- local curr = self : __format (value )
202+ local curr = format (value )
276203
277204 for _ , observer in ipairs (self .observers ) do
278205 if observer .key == key then
@@ -287,13 +214,13 @@ end
287214--- @alias FeatherClear fun ( self : Feather )
288215--- @type FeatherClear
289216function Feather :clear ()
290- logs = {}
217+ self . featherLogger : clear ()
291218end
292219
293220--- @alias FeatherFinish fun ( self : Feather )
294221--- @type FeatherFinish
295222function Feather :finish ()
296- self :log ({ type = " feather:finish" })
223+ self . featherLogger :log ({ type = " feather:finish" })
297224
298225 self .pluginManager :finish (self )
299226end
@@ -312,57 +239,46 @@ function Feather:update(dt)
312239
313240 local client = self .server :accept ()
314241 if client then
315- if # logs == 0 then
316- self :log ({ type = " feather:start" })
242+ if # self . featherLogger . logs == 0 then
243+ self . featherLogger :log ({ type = " feather:start" })
317244 end
318245
319246 client :settimeout (1 )
320247
321248 local rawRequest = client :receive ()
322- local request = self : __buildRequest (rawRequest )
249+ local request = serverUtils . buildRequest (rawRequest )
323250
324251 local addr = client :getsockname ()
325-
326- self .logger (request )
327- if not self :__isInWhitelist (addr ) then
252+ if not serverUtils .isInWhitelist (addr , self .whitelist ) then
328253 self :trace (" non-whitelisted connection attempt: " , addr )
329254 client :close ()
330255 end
331-
332- self .logger (request .method )
333256 if request and request .method == " GET" then
334257 local response = " "
335-
336- self .logger (request .path )
337258 if request .path == " /config" then
338- local body = json .encode (self :__getConfig ())
339- response = self :__buildResponse (body )
259+ response = serverUtils .createResponse (self :__getConfig ())
340260 end
341261
342262 if request .path == " /logs" then
343- local body = json .encode (logs )
344- response = self :__buildResponse (body )
263+ response = serverUtils .createResponse (self .featherLogger .logs )
345264 self .lastDelivery = os.time ()
346265 end
347266
348267 if request .path == " /performance" then
349- local body = json .encode (performance :getResponseBody (dt ))
350- response = self :__buildResponse (body )
268+ response = serverUtils .createResponse (performance :getResponseBody (dt ))
351269 end
352270
353271 if request .path == " /observers" then
354272 if self .defaultObservers then
355273 self :__defaultObservers ()
356274 end
357- local body = json .encode (self .observers )
358- response = self :__buildResponse (body )
275+ response = serverUtils .createResponse (self .observers )
359276 end
360277
361278 if request .path == " /plugins" then
362279 local pluginResponse = self .pluginManager :handleRequest (request , self )
363280
364- local body = json .encode (pluginResponse )
365- response = self :__buildResponse (body )
281+ response = serverUtils .createResponse (pluginResponse )
366282 end
367283
368284 client :send (response )
@@ -380,64 +296,10 @@ function Feather:trace(...)
380296 return
381297 end
382298
383- local str = " [Feather] " .. self :__format (... )
384-
385- self .logger (str )
386- self :__print (" trace" , str )
387- end
388-
389- --- @alias LogType " output" | " trace" | " error" | " feather:finish" | " feather:start" | " output" | " error"
390- --- @class FeatherLine
391- --- @field type LogType
392- --- @field str ? string
393- --- @field id ? string
394- --- @field time ? number
395- --- @field count ? number
396- --- @field trace ? string
397- --- @alias FeatherLog fun ( self : Feather , line : FeatherLine )
398- --- @type FeatherLog
399- function Feather :log (line )
400- if not self .debug then
401- return
402- end
403-
404- line .id = tostring (os.time ()) .. " -" .. tostring (# logs + 1 )
405- line .time = os.time ()
406- line .count = 1
407- line .trace = debug.traceback ()
408-
409- table.insert (logs , line )
410-
411- --- Find a way to avoid deleting incoming logs
412- if # logs > self .maxTempLogs then
413- table.remove (logs , 1 )
414- end
415- end
416-
417- --- @alias FeatherPrint fun ( self : Feather , ... )
418- --- @type FeatherPrint
419- function Feather :print (...)
420- self :__countOnRepeat (" output" , ... )
421- end
422-
423- --- Manages the print function internally
424- --- @param self Feather
425- --- @param type LogType
426- --- @param ... unknown
427- function Feather :__countOnRepeat (type , ...)
428- if not self .debug then
429- return
430- end
299+ local str = " [Feather] " .. format (... )
431300
432- local str = self :__format (... )
433- local last = logs [# logs ]
434- if last and str == last .str then
435- -- Update last line if this line is a duplicate of it
436- last .time = os.time ()
437- last .count = last .count + 1
438- else
439- self :log ({ type = type , str = str })
440- end
301+ self .featherLogger .logger (str )
302+ self .featherLogger :print (" trace" , str )
441303end
442304
443305--- @type fun ( config : FeatherConfig ): Feather
0 commit comments