271 """Serve wiki for development (with hot refresh)."""
272 logging.info('Serving wiki for development')
273 Artifact.build_all()
274
275
276
277 event_handler = ArtifactEventHandler()
278 observer = Observer()
279 observer.schedule(event_handler, TEMPLATES_DIR, recursive=False)
280 observer.schedule(event_handler, WIKI_SOURCE_DIR, recursive=True)
281 observer.schedule(event_handler, STYLES_DIR, recursive=True)
282 observer.start()
283
284 async def on_shutdown(app):
285 for ws in app['websockets']:
286 await ws.close(code=WSCloseCode.GOING_AWAY,
287 message='Server shutdown')
288 observer.stop()
289 observer.join()
290
291 async def handle_artifact(name):
292 source_path = os.path.join(OUTPUT_DIR, name)
293 logging.info('Handling source path %s for %s', source_path, name)
294 if source_path in Artifact.all:
295 return web.FileResponse(source_path)
296 else:
297 return web.HTTPNotFound()
298
299 async def handle_page(request):
300 name = request.match_info.get('name', 'index.html')
301 if name == '' or name.endswith('/'):
302 name = name + 'index.html'
303 return await handle_artifact(name)
304
305 async def handle_css(request):
306 name = request.match_info.get('name')
307 return await handle_artifact('css/' + name)
308
309 async def websocket_handler(request):
310 logging.info('websocket connection open')
311 ws = web.WebSocketResponse()
312 await ws.prepare(request)
313
314 loop = asyncio.get_event_loop()
315
316 def notify():
317 logging.info('requesting reload')
318 asyncio.run_coroutine_threadsafe(ws.send_str('reload'), loop)
319
320 Artifact.listeners.append(notify)
321 request.app[
'websockets'].
append(ws)
322 try:
323 async for msg in ws:
324 if msg.type == WSMsgType.ERROR:
325 logging.error(
326 'websocket connection closed with exception %s',
327 ws.exception())
328 finally:
329 logging.info('websocket connection closing')
330 Artifact.listeners.remove(notify)
331 request.app[
'websockets'].
remove(ws)
332
333 logging.info('websocket connection closed')
334 return ws
335
336 app = web.Application()
337 app['websockets'] = []
339 app.router.add_static('/' + images_dir,
340 os.path.join(WIKI_SOURCE_DIR, images_dir))
341 app.router.add_get('/ws', websocket_handler)
342 app.router.add_get('/css/{name}', handle_css)
343 app.router.add_get('/{name:[^{}]*}', handle_page)
344 app.on_shutdown.append(on_shutdown)
345 web.run_app(app, access_log_format='"%r" %s')
346
347
static void append(char **dst, size_t *count, const char *src, size_t n)