func (g *Group) Endpoint(prefix string) http.Handler {
	// trim prefix
	prefix = strings.Trim(prefix, "/")

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// create tracer
		tracer := NewTracerFromRequest(r, "fire/Group.Endpoint")
		defer tracer.Finish(true)

		// continue any previous aborts
		defer stack.Resume(func(err error) {
			// directly write jsonapi errors
			if jsonapiError, ok := err.(*jsonapi.Error); ok {
				_ = jsonapi.WriteError(w, jsonapiError)
				return
			}

			// set critical error on last span
			tracer.Tag("error", true)
			tracer.Log("error", err.Error())
			tracer.Log("stack", stack.Trace())

			// report critical errors if possible
			if g.Reporter != nil {
				g.Reporter(err)
			}

			// ignore errors caused by writing critical errors
			_ = jsonapi.WriteError(w, jsonapi.InternalServerError(""))
		})

		// trim path
		path := strings.Trim(r.URL.Path, "/")
		path = strings.TrimPrefix(path, prefix)
		path = strings.Trim(path, "/")

		// check path
		if path == "" {
			stack.Abort(jsonapi.NotFound("resource not found"))
		}

		// split path
		s := strings.Split(path, "/")

		// prepare context
		ctx := &Context{
			Data:           Map{},
			HTTPRequest:    r,
			ResponseWriter: w,
			Group:          g,
			Tracer:         tracer,
		}

		// get controller
		controller, ok := g.controllers[s[0]]
		if ok {
			// set controller
			ctx.Controller = controller

			// call controller with context
			controller.generalHandler(prefix, ctx)

			return
		}

		// get action
		action, ok := g.actions[s[0]]
		if ok {
			// check if action is allowed
			if Contains(action.Action.Methods, r.Method) {
				// check if action matches the context
				if action.Action.Callback.Matcher(ctx) {
					// run authorizers and handle errors
					for _, cb := range action.Authorizers {
						// check if callback should be run
						if !cb.Matcher(ctx) {
							continue
						}

						// call callback
						err := cb.Handler(ctx)
						if IsSafe(err) {
							stack.Abort(&jsonapi.Error{
								Status: http.StatusUnauthorized,
								Detail: err.Error(),
							})
						} else if err != nil {
							stack.Abort(err)
						}
					}

					// limit request body size
					LimitBody(ctx.ResponseWriter, ctx.HTTPRequest, int64(action.Action.BodyLimit))

					// call action with context
					stack.AbortIf(action.Action.Callback.Handler(ctx))

					return
				}
			}
		}

		// otherwise return error
		stack.Abort(jsonapi.NotFound("resource not found"))
	})
}
func (g *Group) Endpoint(prefix string) http.Handler {
	
	prefix = strings.Trim(prefix, "/")

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		
		tracer := NewTracerFromRequest(r, "fire/Group.Endpoint")
		defer tracer.Finish(true)

		
		defer stack.Resume(func(err error) {
			
			if jsonapiError, ok := err.(*jsonapi.Error); ok {
				_ = jsonapi.WriteError(w, jsonapiError)
				return
			}

			
			tracer.Tag("error", true)
			tracer.Log("error", err.Error())
			tracer.Log("stack", stack.Trace())

			
			if g.Reporter != nil {
				g.Reporter(err)
			}

			
			_ = jsonapi.WriteError(w, jsonapi.InternalServerError(""))
		})

		
		path := strings.Trim(r.URL.Path, "/")
		path = strings.TrimPrefix(path, prefix)
		path = strings.Trim(path, "/")

		
		if path == "" {
			stack.Abort(jsonapi.NotFound("resource not found"))
		}

		
		s := strings.Split(path, "/")

		
		ctx := &Context{
			Data:           Map{},
			HTTPRequest:    r,
			ResponseWriter: w,
			Group:          g,
			Tracer:         tracer,
		}

		
		controller, ok := g.controllers[s[0]]
		if ok {
			
			ctx.Controller = controller

			
			controller.generalHandler(prefix, ctx)

			return
		}

		
		action, ok := g.actions[s[0]]
		if ok {
			
			if Contains(action.Action.Methods, r.Method) {
				
				if action.Action.Callback.Matcher(ctx) {
					
					for _, cb := range action.Authorizers {
						
						if !cb.Matcher(ctx) {
							continue
						}

						
						err := cb.Handler(ctx)
						if IsSafe(err) {
							stack.Abort(&jsonapi.Error{
								Status: http.StatusUnauthorized,
								Detail: err.Error(),
							})
						} else if err != nil {
							stack.Abort(err)
						}
					}

					
					LimitBody(ctx.ResponseWriter, ctx.HTTPRequest, int64(action.Action.BodyLimit))

					
					stack.AbortIf(action.Action.Callback.Handler(ctx))

					return
				}
			}
		}

		
		stack.Abort(jsonapi.NotFound("resource not found"))
	})
}
func ( g * Group ) Endpoint ( prefix string ) http . Handler { // trim prefix prefix = strings . Trim ( prefix , " " ) return http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) { // create tracer tracer := NewTracerFromRequest ( r , " " ) defer tracer . Finish ( true ) // continue any previous aborts defer stack . Resume ( func ( err error ) { // directly write jsonapi errors if jsonapiError , ok := err . ( * jsonapi . Error ) ; ok { _ = jsonapi . WriteError ( w , jsonapiError ) return } // set critical error on last span tracer . Tag ( " " , true ) tracer . Log ( " " , err . Error ( ) ) tracer . Log ( " " , stack . Trace ( ) ) // report critical errors if possible if g . Reporter != nil { g . Reporter ( err ) } // ignore errors caused by writing critical errors _ = jsonapi . WriteError ( w , jsonapi . InternalServerError ( " " ) ) } ) // trim path path := strings . Trim ( r . URL . Path , " " ) path = strings . TrimPrefix ( path , prefix ) path = strings . Trim ( path , " " ) // check path if path == " " { stack . Abort ( jsonapi . NotFound ( " " ) ) } // split path s := strings . Split ( path , " " ) // prepare context ctx := & Context { Data : Map { } , HTTPRequest : r , ResponseWriter : w , Group : g , Tracer : tracer , } // get controller controller , ok := g . controllers [ s [ 0 ] ] if ok { // set controller ctx . Controller = controller // call controller with context controller . generalHandler ( prefix , ctx ) return } // get action action , ok := g . actions [ s [ 0 ] ] if ok { // check if action is allowed if Contains ( action . Action . Methods , r . Method ) { // check if action matches the context if action . Action . Callback . Matcher ( ctx ) { // run authorizers and handle errors for _ , cb := range action . Authorizers { // check if callback should be run if ! cb . Matcher ( ctx ) { continue } // call callback err := cb . Handler ( ctx ) if IsSafe ( err ) { stack . Abort ( & jsonapi . Error { Status : http . StatusUnauthorized , Detail : err . Error ( ) , } ) } else if err != nil { stack . Abort ( err ) } } // limit request body size LimitBody ( ctx . ResponseWriter , ctx . HTTPRequest , int64 ( action . Action . BodyLimit ) ) // call action with context stack . AbortIf ( action . Action . Callback . Handler ( ctx ) ) return } } } // otherwise return error stack . Abort ( jsonapi . NotFound ( " " ) ) } ) }
// Endpoint will return an http handler that serves requests for this group. The
// specified prefix is used to parse the requests and generate urls for the
// resources.
Endpoint will return an http handler that serves requests for this group . The specified prefix is used to parse the requests and generate urls for the resources .