app
packagemoduleThis package is not in the latest version of its module.
Details
Validgo.mod file
The Go module system was introduced in Go 1.11 and is the official dependency management solution for Go.
Redistributable license
Redistributable licenses place minimal restrictions on how software can be used, modified, and redistributed.
Tagged version
Modules with tagged versions give importers more predictable builds.
Stable version
When a project reaches major version v1 it is considered stable.
- Learn more about best practices
Repository
Links
README¶
gowww/app is a full featured HTTP framework for any web app.
It greatly increases productivity by providing helpers at all levels while maintaining best performance.
Start
Install gowww/app:
go get github.com/gowww/app
Import it in your new app:
import "github.com/gowww/app"
Routing
There are methods for common HTTP methods:
app.Get("/", func(c *app.Context) {// Write response for GET /})app.Post("/", func(c *app.Context) {// Write response for POST /})app.Put("/", func(c *app.Context) {// Write response for PUT /})app.Patch("/", func(c *app.Context) {// Write response for PATCH /})app.Delete("/", func(c *app.Context) {// Write response for DELETE /})
Path parameters
Named
A named parameter begins with:
and matches any value until the next/
in path.
To retrieve the value, askContext.PathValue.
It will return the value as a string (empty if the parameter doesn't exist).
Example, with a parameterid
:
app.Get("/users/:id", func(c *app.Context) {id := c.PathValue("id")fmt.Fprintf(w, "Page of user #%s", id)}))
Regular expressions
If a parameter must match an exact pattern (digits only, for example), you can also set aregular expression constraint just after the parameter name and another:
:
app.Get(`/users/:id:^\d+$`, func(c *app.Context) {id := c.PathValue("id")fmt.Fprintf(w, "Page of user #%s", id)}))
If you don't need to retrieve the parameter value but only use a regular expression, you can omit the parameter name.
Wildcard
A trailing slash behaves like a wildcard by matching the beginning of the request path and keeping the rest as a parameter value, under*
:
rt.Get("/files/", func(c *app.Context) {filepath := c.PathValue("*")fmt.Fprintf(w, "Get file %s", filepath)}))
For more details, seegowww/router.
Groups
A routing group works like the top-level router but prefixes all subroute paths:
api := app.Group("/api"){v1 := api.Group("/v1"){v1.Get("/user", func(c *app.Context) { /* Write response for GET /api/v1/user */ })v1.Get("/item", func(c *app.Context) { /* Write response for GET /api/v1/item */ })}v2 := api.Group("/v2"){v2.Get("/user", func(c *app.Context) { /* Write response for GET /api/v2/user */ })v2.Get("/item", func(c *app.Context) { /* Write response for GET /api/v2/item */ })}}
Errors
You can set a custom "not found" handler withNotFound:
app.NotFound(func(c *app.Context) {c.Status(http.StatusNotFound)c.View("notFound")})
The app is also recovered from panics so you can set a custom "serving error" handler (which is used only when the response is not already written) withError and retrieve the recovered error value withContext.Error:
app.Error(func(c *app.Context) {c.Status(http.StatusInternalServerError)if c.Error() == ErrCannotOpenFile {c.View("errorStorage")return}c.View("error")})
Context
AContext is always used inside aHandler.
It contains the original request and response writer but provides all the necessary helpers to access them:
Request
UseContext.Req to access the original request:
app.Get("/", func(c *app.Context) {r := c.Req})
UseContext.FormValue to access a value from URL or body.
You can also useContext.HasFormValue to check its existence:
app.Get("/", func(c *app.Context) {if c.HasFormValue("id") {id := c.FormValue("id")}})
Response
UseContext.Res to access the original response writer:
app.Get("/", func(c *app.Context) {w := c.Res})
UseContext.Text orContext.Bytes to send a string:
app.Get("/", func(c *app.Context) {c.Text("Hello")c.Bytes([]byte("World"))})
UseContext.JSON to send a JSON formatted response (if implemented by argument,JSON() interface{}
will be used):
app.Get(`/users/:id:^\d+$/files/`, func(c *app.Context) {c.JSON(map[string]interface{}{"userID": c.PathValue("id"),"filepath": c.PathValue("*"),})})
UseContext.Status to set the response status code:
app.Get("/", func(c *app.Context) {c.Status(http.StatusCreated)})
UseContext.NotFound to send a "not found" response:
app.Get("/", func(c *app.Context) {c.NotFound()})
UseContext.Panic to log an error and send a "serving error" response:
app.Get("/", func(c *app.Context) {c.Panic("database connection failed")})
UseContext.Redirect to redirect the client:
app.Get("/old", func(c *app.Context) {c.Redirect("/new", http.StatusMovedPermanently)})
UseContext.Push to initiate an HTTP/2 server push:
app.Get("/", func(c *app.Context) {c.Push("/static/main.css", nil)})
Values
You can use context values kept inside the context for future usage downstream (like views or subhandlers).
UseContext.Set to set a value:
app.Get("/", func(c *app.Context) {c.Set("clientCountry", "UK")})
UseContext.Get to retrieve a value:
app.Get("/", func(c *app.Context) {clientCountry := c.Get("clientCountry")})
Views
Views are standardGo HTML templates and must be stored inside theviews
directory.
They are automatically parsed during launch.
UseContext.View to send a view:
app.Get("/", func(c *app.Context) {c.View("home")})
Data
Use aViewData map to pass data to a view.
You can also useGlobalViewData to set data for all views:
app.GlobalViewData(app.ViewData{"appName": "My app",})app.Get("/", func(c *app.Context) {user := &User{ID: 1,Name: "John Doe",}c.View("home", app.ViewData{"user": user,})})
Inviews/home.gohtml:
{{define "home"}}<h1>Hello {{.user.Name}} ({{.c.Req.RemoteAddr}}) and welcome on {{.appName}}!</h1>{{end}}
Built-in
This data is always passed to the views, out of the box:
Data | Description |
---|---|
.c | The currentContext. |
.envProduction | Tells if the app is run with the production flag. |
.errors | Seevalidation. |
Functions
UseGlobalViewFuncs to set functions for all views:
app.GlobalViewFuncs(app.ViewFuncs{"pathescape": url.PathEscape,})app.Get("/posts/new", func(c *app.Context) {c.View("postsNew")})
Inviews/posts.gohtml:
{{define "postsNew"}}<a href="/sign-in?return-to={{pathescape "/posts/new"}}">Sign in</a>{{end}}
Built-in
In addition to the functions provided by the standardtemplate package, these function are also available out of the box:
Function | Description | Usage |
---|---|---|
asset | Appends the file hash to the name of a static file from thestatic directory. | {{asset "videos/loop.mp4"}} |
googlefonts | Sets HTML tag forGoogle Fonts stylesheet and given font(s). | {{googlefonts "Open+Sans:400,700|Spectral"}} |
nl2br | Converts\n to HTML<br> . | {{nl2br "line one\nline two"}} |
safehtml | Prevents string to be escaped. Be careful. | {{safehtml "<strong>word</strong>"}} |
script | Sets HTML tag for a script from thestatic/script directory. | {{script "main.js"}} |
style | Sets HTML tag for a stylesheet from thestatic/style directory. | {{style "main.css"}} |
Validation
Validation is handled bygowww/check.
Firstly, make aChecker withrules for keys:
userChecker := check.Checker{"email": {check.Required, check.Email, check.Unique(db, "users", "email", "?")},"phone": {check.Phone},"picture": {check.MaxFileSize(5000000), check.Image},}
The rules order is significant so for example, it's smarter to check the format of a value before its uniqueness, avoiding some useless database requests.
UseContext.Check to check the request against a checker:
errs := c.Check(userChecker)
UseErrors.Empty orErrors.NotEmpty to know if there are errors and handle them like you want.
You can also translate error messages withContext.TErrors:
if errs.NotEmpty() {c.Status(http.StatusBadRequest)c.View(view, app.ViewData{"errors": errs})return}
But usually, when a check fails, you only want to send a response with error messages.
Here comes theBadRequest shortcut which receives a checker and a view name.
If you don't provide a view name (empty string), the response will be a JSON errors map.
If the check fails, it sets the status to "400 Bad Request", sends the response (view or JSON) and returnstrue
, allowing you to exit from the handler:
app.Post("/join", func(c *app.Context) {if c.BadRequest(userChecker, "join") {return}// Handle request confidently})
In views, you can retrieve theTranslatedErrors map under keyerrors
which is nevernil
in view data:
<input type="email" name="email" value="{{.email}}">{{if .errors.Has "email"}}<div class="error">{{.errors.First "email"}}</div>{{end}}
Internationalization
Internationalization is handled bygowww/i18n.
Firstly, make your translations map (string to string, for each language):
locales := i18n.Locales{language.English: {"hello": "Hello!",},language.French: {"hello": "Bonjour !",},}
UseLocalize to register it and set the default locale (used as a fallback):
app.Localize(locales, language.English)
MethodsContext.T,Context.Tn,Context.THTML andContext.TnHTML are now operational.
As theContext is always part of the view data, you can use these methods in views:
<h1>{{.c.T "hello"}}</h1>
Static files
Static files must be stored inside thestatic
directory.
They are automatically accessible from the/static/
path prefix.
Running
CallRun at the end of your main function:
app.Run()
By default, your app will listen and serve on:8080
.
But you can change this address by using flag-a
when running your app:
./myapp -a :1234
Middlewares
Custom middlewares can be used if they are compatible with standard interfacenet/http.Handler.
They can be set for:
The entire app:
app.Run(hand1, hand2, hand3)
A group:
api := app.Group("/api", hand1, hand2, hand3)
A single route:
api := app.Get("/", func(c *app.Context) {// Write response for GET /}, hand1, hand2, hand3)
First handler wraps the second and so on.
Documentation¶
Overview¶
Package app provides a full featured framework for any web app.
Example¶
package mainimport ("log""net/http""github.com/gowww/app""github.com/gowww/i18n""golang.org/x/text/language")func main() {var locales = i18n.Locales{language.English: {"hello": "Hello!",},language.French: {"hello": "Bonjour !",},}app.Localize(locales, language.English)app.Get("/", func(c *app.Context) {c.View("home")})app.Post("/user/:id/files/", func(c *app.Context) {c.Status(http.StatusCreated)c.JSON(map[string]interface{}{"id": c.PathValue("id"),"filepath": c.PathValue("*"),})})v1 := app.Group("/v1"){v1.Get("/user", func(c *app.Context) { c.Text("User for V1") })v1.Get("/item", func(c *app.Context) { c.Text("Item for V1") })}v2 := app.Group("/v2"){v2.Get("/user", func(c *app.Context) { c.Text("User for V2") })v2.Get("/item", func(c *app.Context) { c.Text("Item for V2") })}if !app.EnvProduction() {log.Printf("Developing app on %s\n", app.Address())}app.Run()}
Index¶
- func Address() string
- func Delete(path string, handler Handler, middlewares ...Middleware)
- func Encrypter() crypto.Encrypter
- func EnvProduction() bool
- func Error(handler Handler)
- func Get(path string, handler Handler, middlewares ...Middleware)
- func GlobalViewData(data ViewData)
- func GlobalViewFuncs(funcs ViewFuncs)
- func Localize(locs i18n.Locales, fallback language.Tag, parsers ...i18n.Parser)
- func NotFound(handler Handler)
- func Patch(path string, handler Handler, middlewares ...Middleware)
- func Post(path string, handler Handler, middlewares ...Middleware)
- func Put(path string, handler Handler, middlewares ...Middleware)
- func Route(method, path string, handler Handler, middlewares ...Middleware)
- func Run(mm ...Middleware)
- func Secret(key string)
- func Secure(o *secure.Options)
- type Context
- func (c *Context) BadRequest(checker check.Checker, view string, data ...ViewData) bool
- func (c *Context) Bytes(b []byte)
- func (c *Context) Check(checker check.Checker) check.Errors
- func (c *Context) Cookie(name string) string
- func (c *Context) DeleteCookie(name string)
- func (c *Context) Error() error
- func (c *Context) FmtNumber(n interface{}) string
- func (c *Context) FormValue(key string) string
- func (c *Context) Get(key interface{}) interface{}
- func (c *Context) HasFormValue(key string) bool
- func (c *Context) JSON(v interface{})
- func (c *Context) Locale() language.Tag
- func (c *Context) Log(msg string)
- func (c *Context) NotFound()
- func (c *Context) Panic(err error)
- func (c *Context) PathValue(key string) string
- func (c *Context) Push(target string, opts *http.PushOptions)
- func (c *Context) Redirect(url string, status int)
- func (c *Context) Set(key, val interface{})
- func (c *Context) SetCookie(cookie *http.Cookie)
- func (c *Context) Status(code int) *Context
- func (c *Context) T(key string, a ...interface{}) string
- func (c *Context) TErrors(errs check.Errors) check.TranslatedErrors
- func (c *Context) THTML(key string, a ...interface{}) template.HTML
- func (c *Context) Text(s string)
- func (c *Context) Textf(s string, a ...interface{})
- func (c *Context) Tn(key string, n int, args ...interface{}) string
- func (c *Context) TnHTML(key string, n int, args ...interface{}) template.HTML
- func (c *Context) View(name string, data ...ViewData)
- func (c *Context) Write(b []byte) (int, error)
- type Handler
- type Middleware
- type RouterGroup
- func (rg *RouterGroup) Delete(path string, handler Handler, middlewares ...Middleware)
- func (rg *RouterGroup) Get(path string, handler Handler, middlewares ...Middleware)
- func (rg *RouterGroup) Group(path string, middlewares ...Middleware) *RouterGroup
- func (rg *RouterGroup) Patch(path string, handler Handler, middlewares ...Middleware)
- func (rg *RouterGroup) Post(path string, handler Handler, middlewares ...Middleware)
- func (rg *RouterGroup) Put(path string, handler Handler, middlewares ...Middleware)
- func (rg *RouterGroup) Route(method, path string, handler Handler, middlewares ...Middleware)
- type ViewData
- type ViewFuncs
Examples¶
Constants¶
This section is empty.
Variables¶
This section is empty.
Functions¶
funcAddress¶
func Address()string
Address gives the address on which the app is running.It ensures that flags are parsed so don't use this function before setting your own flags with gowww/cli or they will be ignored.
funcDelete¶
func Delete(pathstring, handlerHandler, middlewares ...Middleware)
Delete makes a route for DELETE method.
funcEnvProduction¶
func EnvProduction()bool
EnvProduction tells if the app is run with the production flag.It ensures that flags are parsed so don't use this function before setting your own flags with gowww/cli or they will be ignored.
funcError¶
func Error(handlerHandler)
Error registers the "internal error" handler.
Using Context.Error, you can retrieve the error value stored in request's context during recovering.
funcGet¶
func Get(pathstring, handlerHandler, middlewares ...Middleware)
Get makes a route for GET method.
funcGlobalViewData¶
func GlobalViewData(dataViewData)
GlobalViewData adds global data for view templates.
funcGlobalViewFuncs¶
func GlobalViewFuncs(funcsViewFuncs)
GlobalViewFuncs adds functions for view templates.
funcLocalize¶
Localize sets app locales with fallback and client locale parsers.Order is mandatory and defaults are: ParseCookie, ParseFormValue, ParseAcceptLanguage.
funcPatch¶
func Patch(pathstring, handlerHandler, middlewares ...Middleware)
Patch makes a route for PATCH method.
funcPost¶
func Post(pathstring, handlerHandler, middlewares ...Middleware)
Post makes a route for POST method.
funcPut¶
func Put(pathstring, handlerHandler, middlewares ...Middleware)
Put makes a route for PUT method.
funcRoute¶
func Route(method, pathstring, handlerHandler, middlewares ...Middleware)
Route makes a route for method and path.
funcRun¶
func Run(mm ...Middleware)
Run ensures that flags are parsed, sets the middlewares and starts the server.
Types¶
typeContext¶
type Context struct {Reshttp.ResponseWriterReq *http.Request}
A Context contains the data for a handler.
func (*Context)BadRequest¶
BadRequest uses a check.Checker to validate request form data, and a view name to execute on fail.If you don't provide a view name (empty string), the response will be a JSON errors map.
If the check fails, it sets the status to "400 Bad Request" and returns true, allowing you to exit from the handler.
Example¶
package mainimport ("net/http""github.com/gowww/app""github.com/gowww/check")func main() {userChecker := check.Checker{"email": {check.Required, check.Email},"phone": {check.Phone},}app.Post("/users", func(c *app.Context) {if c.BadRequest(userChecker, "") {return}c.Status(http.StatusCreated)})}
func (*Context)Check¶
Check uses a check.Checker to validate request's data and always returns the non-nil errors map.
func (*Context)Cookie¶
Cookie returns the value of the named cookie.If multiple cookies match the given name, only one cookie value will be returned.If the secret key is set for app, value will be decrypted before returning.If cookie is not found or the decryption fails, an empty string is returned.
func (*Context)DeleteCookie¶
DeleteCookie removes a cookie from the client.
func (*Context)Error¶
Error returns the error value stored in request's context after a recovering or a Context.Error call.
func (*Context)HasFormValue¶
HasFormValue checks if the form value exists in the request.
func (*Context)JSON¶
func (c *Context) JSON(v interface{})
JSON writes the response with a marshalled JSON.If v has a JSON() interface{} method, it will be used.
func (*Context)Push¶
func (c *Context) Push(targetstring, opts *http.PushOptions)
Push initiates an HTTP/2 server push if supported.See net/http.Pusher for documentation.
func (*Context)SetCookie¶
SetCookie sets a cookie to the response.If the secret key is set for app, value will be encrypted.If the app is not in a production environment, the "secure" flag will be set to false.
func (*Context)TErrors¶
func (c *Context) TErrors(errscheck.Errors)check.TranslatedErrors
TErrors returns translated checking errors.
func (*Context)THTML¶
THTML works like T but returns an HTML unescaped translation. An "nl2br" function is applied to the result.
func (*Context)Tn¶
Tn returns the translation associated to key, for the client locale.If the translation defines plural forms (zero, one, other), it uses the most appropriate.All i18n.TnPlaceholder in the translation are replaced with number n.If translation is not found, an empty string is returned.
func (*Context)TnHTML¶
TnHTML works like Tn but returns an HTML unescaped translation. An "nl2br" function is applied to the result.
typeMiddleware¶
A Middleware is a handler that wraps another one.
typeRouterGroup¶
type RouterGroup struct {// contains filtered or unexported fields}
RouterGroup contains the first path part for a routes group.
funcGroup¶
func Group(pathstring, middlewares ...Middleware) *RouterGroup
Group initiates a routing group.All subroutes paths will be prefixed with the group path.
func (*RouterGroup)Delete¶
func (rg *RouterGroup) Delete(pathstring, handlerHandler, middlewares ...Middleware)
Delete makes a route for DELETE method.
func (*RouterGroup)Get¶
func (rg *RouterGroup) Get(pathstring, handlerHandler, middlewares ...Middleware)
Get makes a route for GET method.
func (*RouterGroup)Group¶
func (rg *RouterGroup) Group(pathstring, middlewares ...Middleware) *RouterGroup
Group contains the first path part for a routes subgroup.
func (*RouterGroup)Patch¶
func (rg *RouterGroup) Patch(pathstring, handlerHandler, middlewares ...Middleware)
Patch makes a route for PATCH method.
func (*RouterGroup)Post¶
func (rg *RouterGroup) Post(pathstring, handlerHandler, middlewares ...Middleware)
Post makes a route for POST method.
func (*RouterGroup)Put¶
func (rg *RouterGroup) Put(pathstring, handlerHandler, middlewares ...Middleware)
Put makes a route for PUT method.
func (*RouterGroup)Route¶
func (rg *RouterGroup) Route(method, pathstring, handlerHandler, middlewares ...Middleware)
Route makes a route for method and path.