Source

tales / fan / event / TalesHandler.fan

Full commit
**
** Code that executes your page, dosen't handle any errors
**
class TalesHandler{
		
	**
	** Handle the request. search for pages 
	**
	static Bool handleRequest(){
		pod := Locals.app.mainPod
		request := Locals.request
		response := Locals.response
		
		Method? correctMethod := Locals.routes.eachWhile|Route route, Int index -> Method?|{
			if(route.method != RequestMethod.any){ //check the route
				if(route.method != request.method)
					return null
			}
			
			if(request.fitWith(route))
				return route.toMethod
			else
				return null
		}
		
		
		if(correctMethod == null){
			return false
		}
		else{
			//Find before and after methods
			cls := correctMethod.parent
			beforeMethods := Method[,]
			afterMethods := Method[,]
			
			cls.methods.each|Method method|{
				if(method == correctMethod)
					return
					
				if(method.hasFacet(Before#)){
					Before before := method.facet(Before#)
					echo("$before.include and method name is $correctMethod.name")
					
					if(before.include != null){
						if(before.include.contains(correctMethod.name)){
							beforeMethods.add(method)
						}
					}
					else if(before.exclude != null){
						if(! (before.exclude.contains(correctMethod.name))){
							beforeMethods.add(method)
						}
					}
					else{
						beforeMethods.add(method)
					}
				}
				
				if(method.hasFacet(After#)){
					After after := method.facet(After#)
					if(after.include != null){
						if(after.include.contains(correctMethod.name)){
							afterMethods.add(method)
						}
					}
					else if(after.exclude != null){
						if(! (after.exclude.contains(correctMethod.name))){
							afterMethods.add(method)
						}
					}
					else{
						afterMethods.add(method)
					}
				}
			}
			
			response.statusCode = StatusCode.ok.code
			Page page := correctMethod.parent.make
			
			//invoke every before methods
			Bool? res := beforeMethods.eachWhile|Method method, Int index->Bool?|{
				if(! invokeMethod(method, page, true)){
					return false
				}
					
				return null
			}
			
			
			if(res != false){
				//invoke the actual method
				invokeMethod(correctMethod, page, false)

				//invoke all after methods
				afterMethods.each{
					invokeMethod(it, page, false)
				}
			}
			
			return true
		}
	}
	
	static Bool invokeMethod(Method correctMethod, Page page, Bool isBeforeMethod){
		pod := Locals.app.mainPod
		request := Locals.request
		response := Locals.response
		
		//fill in the args
		args := Obj?[,]
		correctMethod.params.each|p, index|{
			Obj? res
			if(p.type.fits(File#)){
				res = request.file(p.name)
			}
			else if(p.type.fits(WebSocket#)){
				webSocket := Locals.curWebsocket
				if(webSocket == null)
					throw Err("Method $correctMethod is expecting a websocket but none found for this request")
				
				res = webSocket
			}
			else{
				Str? resStr := request.param(p.name)
				if(resStr != null)
					res = TypeConverter.getConvertedFrom(resStr, p.type)
			}
			
			if(res == null && !(p.type.isNullable))
				throw Err("Cannot find parameter matching $p.name of non-nullable type $p.type for route ${request.uri}")
			else
				args.add(res)
		}
		Obj? res := correctMethod.callOn(page, args)
		if(! isBeforeMethod)
			return true
		
		if(res != null && res.typeof.fits(Bool#))
			return res
		
		return true
	}
}