Skip to content
/ cherry Public

🚨Cherry🍒 is a web framework for Go language.

License

Notifications You must be signed in to change notification settings

pooulad/cherry

Repository files navigation

Cherry🍒 Go

🚨Cherry🍒 is a web framework for Go language.

Installation

go get github.com/pooulad/cherry

Features

  • fast route dispatching backed by http-router
  • easy to add middleware handlers
  • sub-routing with separated middleware handlers
  • central based error handling
  • build in template engine
  • fast, lightweight and extendable

Basic usage

package main
import "github.com/pooulad/cherry"

func main() {
    app := cherry.New()

    app.Get("/foo", fooHandler)
    app.Post("/bar", barHandler)
    app.Use(middleware1, middleware2)

    friends := app.Group("/friends")
    friends.Get("/profile", profileHandler)
    friends.Use(middleware3, middleware4)
    
    app.Serve(8080)
}

More complete examples can be found in the examples folder

Routes

app := cherry.New()

app.Get("/", func(ctx *cherry.Context) error {
   .. do something .. 
})
app.Post("/", func(ctx *cherry.Context) error {
   .. do something .. 
})
app.Put("/", func(ctx *cherry.Context) error {
   .. do something .. 
})
app.Delete("/", func(ctx *cherry.Context) error {
   .. do something .. 
})

get named url parameters

app.Get("/hello/:name", func(ctx *cherry.Context) error {
    name := ctx.Param("name")
})

Group (subrouting)

Group lets you manage routes, contexts and middleware separate from each other.

Create a new cherry object and attach some middleware and context to it.

app := cherry.New()
app.BindContext(context.WithValue(context.Background(), "foo", "bar")
app.Get("/", somHandler)
app.Use(middleware1, middleware2)

Create a group and attach its own middleware and context to it

friends := app.Group("/friends")
app.BindContext(context.WithValue(context.Background(), "friend1", "john")
friends.Post("/create", someHandler)
friends.Use(middleware3, middleware4)

In this case group friends will inherit middleware1 and middleware2 from its parent app. We can reset the middleware from its parent by calling Reset()

friends := app.Group("/friends").Reset()
friends.Use(middleware3, middleware4)

Now group friends will have only middleware3 and middleware4 attached.

Static files

Make our assets are accessible trough /assets/styles.css

app := cherry.New()
app.Static("/assets", "public/assets")

Handlers

A definition of a cherry.Handler

func(ctx *cherry.Context) error

Cherry only accepts handlers of type cherry.Handler to be passed as functions in routes. You can convert any type of handler to a cherry.Handler.

func myHandler(name string) cherry.Handler{
    .. do something ..
   return func(ctx *cherry.Context) error {
        return ctx.Text(w, http.StatusOK, name)
   }
}

Returning errors

Each handler requires an error to be returned. This is personal idiom but it brings some benefits for handling your errors inside request handlers.

func someHandler(ctx *cherry.Context) error {
    // simple error handling by returning all errors 
    err := someFunc(); err != nil {
        return err
    }
    ...
    req, err := http.NewRequest(...)
    if err != nil {
        return err
    }
}

A cherry ErrorHandlerFunc

func(ctx *cherry.Context, err error)

Handle all errors returned by adding a custom errorHandler for our application.

app := cherry.New()
errHandler := func(ctx *cherry.Context, err error) {
    .. handle the error ..
}
app.SetErrorHandler(errHandler)

Context

Context is a request based object helping you with a series of functions performed against the current request scope.

Passing values around middleware functions

Context provides a context.Context for passing request scoped values around middleware functions.

Create a new context and pass some values

func someMiddleware(ctx *cherry.Context) error {
    ctx.Context = context.WithValue(ctx.Context, "foo", "bar")
    return someMiddleware2(ctx)
}

Get the value back from the context in another middleware function

func someMiddleware2(ctx *cherry.Context) error {
    value := ctx.Context.Value("foo").(string)
    ..
}

Binding a context

In some cases you want to initialize a context from the the main function, like a datastore for example. You can set a context out of a request scope by calling BindContext().

app.BindContext(context.WithValue(context.Background(), "foo", "bar"))

As mentioned in the Group section, you can add different contexts to different groups.

myGroup := app.Group("/foo", ..)
myGroup.BindContext(..)

Helper functions

Context also provides a series of helper functions like responding JSON en text, JSON decoding etc..

func createUser(ctx *cherry.Context) error {
    user := model.User{}
    if err := ctx.DecodeJSON(&user); err != nil {
        return errors.New("failed to decode the response body")
    }
    ..
    return ctx.JSON(http.StatusCreated, user)
}

func login(ctx *cherry.Context) error {
    token := ctx.Header("x-hmac-token")
    if token == "" {
        ctx.Redirect("/login", http.StatusMovedPermanently)
        return nil
    }
    ..
}

Logging

Access Log

Cherry provides an access-log in an Apache log format for each incoming request. The access-log is disabled by default, to enable the access-log set app.HasAccessLog = true.

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326

Server

Cherry HTTP server is a wrapper around the default std HTTP server, the only difference is that it provides a graceful shutdown. Cherry provides both HTTP and HTTPS (TLS).

app := cherry.New()
app.ServeTLS(8080, cert, key)
// or 
app.Serve(8080)

Gracefull stopping a cherry app

Gracefull stopping a cherry app is done by sending one of these signals to the process.

  • SIGINT
  • SIGQUIT
  • SIGTERM

You can also force-quit your app by sending it SIGKILL signal

SIGUSR2 signal is not yet implemented. Reloading a new binary by forking the main process is something that wil be implemented when the need for it is there. Feel free to give some feedback on this feature if you think it can provide a bonus to the package.

Screenshots

App Screenshot

App Screenshot

Support

If you like Cherry🍒 buy me a coffee☕ or star project🌟