• v0.4.0 77a1f3b11d

    Beta 4 Pre-Release

    xdrm-brackets released this 2021-06-20 08:35:45 +00:00 | 28 commits to 0.4.0 since this release

    Going a bit deeper in the idiomatic go direction.

    Service handlers

    Service handler signature has changed in favor of:

    func(context.Context, in) (*out, api.Err)
    
    • the context.Context argument is the current http request's context. It contains pre-filled information accessible through api.GetRequest(ctx), api.GetResponseWriter(ctx) and api.GetAuth(ctx)
    • the in argument is the input struct (unchanged)
    • the out argument is the output struct (unchanged)
    • the api.Err argument is the handler's error status (unchanged)

    Middlewares

    Custom middleware types have been dropped in favor of using func(api.Handler) api.Handler.

    standard

    Standard http middlewares are added with builder.With() and wrap the full http connection as you would expect an http middleware would. It can be used for logging, recovering requests, etc.

    contextual

    Authentication middlewares have been dropped in favor of a less specific type: contextual middlewares.

    They only wrap the call to the service handler. The http request argument has a context pre-filled with useful information that is accessible through api.GetRequest(ctx), api.GetResponseWriter(ctx) and api.GetAuth(ctx).

    Migration example

    Handlers before:

    type Services struct{}
    
    func (s Services) GetUsers(api.Ctx) (*[]UserModel, api.Err) {}
    func (s Services) GetUserByID(api.Ctx, struct{ ID int }) (*UserModel, api.Err) {}
    func (s Services) CreateUser(struct{ Name string }) (*UserModel, api.Err) {}
    

    Handler after:

    type Services struct{}
    
    func (s Services) GetUsers(context.Context) (*[]UserModel, api.Err) {}
    func (s Services) GetUserByID(context.Context, struct{ ID int }) (*UserModel, api.Err) {}
    func (s Services) CreateUser(context.Context, struct{ Name string }) (*UserModel, api.Err) {}
    

    Standard middlewares before:

    builder := &aicra.Builder{}
    err := builder.Setup(configReader)
    if err != nil {
    	log.Fatalf("cannot setup aicra: %s", err)
    }
    
    builder.With(func(next api.AdapterFunc) api.AdapterFunc {
    	return func(w http.ResponseWriter, r *http.Request) {
        	next(r, w)
        }
    }
    

    Standard middlewares after:

    builder := &aicra.Builder{}
    err := builder.Setup(configReader)
    if err != nil {
    	log.Fatalf("cannot setup aicra: %s", err)
    }
    
    builder.With(func(next http.Handler) http.Handler {
    	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        	next.ServeHTTP(r, w)
        })
    }
    

    Authentication middlewares before:

    err := builder.Setup(configReader)
    if err != nil {
    	log.Fatalf("cannot setup aicra: %s", err)
    }
    
    builder.WithAuth(func(next api.AuthHandlerFunc) api.AuthHandlerFunc {
    	return func(a api.Auth, w http.ResponseWriter, r *http.Request) {
    		// add active request permission
    		a.Active = append(a.Active, "admin");
        	next(r, w)
        }
    }
    

    Authentication middlewares after:

    builder := &aicra.Builder{}
    err := builder.Setup(configReader)
    if err != nil {
    	log.Fatalf("cannot setup aicra: %s", err)
    }
    
    builder.WithContext(func(next http.Handler) http.Handler {
    	return http.Handlerfunc(func(w http.ResponseWriter, r *http.Request) {
    		// get auth from context
    		auth := api.GetAuth(r.Context());
    
    		// add active request permission
    		auth.Active = append(auth.Active, "admin");
    		
        	next.ServeHTTP(r, w)
        })
    }
    
    Downloads