Documentation ¶
Overview ¶
Goweb - A simple, powerful web framework for Go.
Overview ¶
Goweb follows the MVC pattern where you build controller objects, and map them to routes of URLs using the goweb.MapController function. Controller objects should adhear to one or more of the controllers.Restful* interfaces in order to be mapped correctly.
If you are not following RESTful patterns, you can do custom routing using the goweb.Map function.
See some real world examples of how to use Goweb by checking out the example web app code: https://github.com/stretchr/goweb/blob/master/example_webapp/main.go
Example ¶
Your controllers, following a RESTful pattern, might look like this:
// PeopleController controls the 'people' resources. type PeopleController struct {} // ReadMany reads many people. func (c *PeopleController) ReadMany(ctx context.Context) error { // TODO: show all people } // Read reads one person. func (c *PeopleController) Read(id string, ctx context.Context) error { // TODO: show one person } // Create creates a new person. func (c *PeopleController) Create(ctx context.Context) error { // TODO: create a person, and redirect to the Read method }
In the above controller code, we are providing three RESTful methods, Read, ReadMany and Create.
To map this in Goweb, we use the MapController function like this:
mapErr := goweb.MapController(&PeopleController{})
This will map the two functions (since they follow the standards defined in the controllers package) to the appropriate RESTful URLs:
GET /people - ReadMany GET /people/{id} - Read POST /people - Create
To add more RESTful features (like Update and Delete), you just have to add the relevant methods to the controller and Goweb will do the rest for you.
For a full list of the supported methods, see the MapController function.
Mapping paths ¶
If you want to map specific paths with Goweb, you can use the `goweb.Map` function with the following kinds of paths:
/literals - Normal text will be considered literal, meaning the path would have to match it exactly. {variable} - Curly braces represent a segment of path that can be anything, and which will be made available via the `context.PathParam` method. [optional-variable] - Square braces represent an optional segment. If present, will be made available via the `context.PathParam` method but otherwise the path will still be a match. * - A single `*` is similar to using `{}`, except the value is ignored. *** - Three `*`'s matches anything in this segment, and any subsequent segments. For example, `/people/***` would match `/people`, `/people/123` and `/people/123/books/456`.
For some real examples of mapping paths, see the goweb.Map function, or check out the example_webapp in the code.
Responding ¶
Goweb makes it easy to respond to requests using an extensible Responder pattern.
If you're building an API, you can respond using the `goweb.API` object, if you just need to respond in a normal HTTP manner, you can use the `goweb.Respond` object.
For details on how to make normal HTTP responses, see http://godoc.org/github.com/stretchr/goweb/responders#HTTPResponder
For details on how to make API responses, see http://godoc.org/github.com/stretchr/goweb/responders#APIResponder
Writing tests ¶
Writing unit tests for your Goweb code is made possible via the `goweb.Test` and `goweb.TestOn` functions, and with a little help from the Testify HTTP package, see http://godoc.org/github.com/stretchr/testify/http
For a real example of what tests look like, see the tests in the example web app: https://github.com/stretchr/goweb/blob/master/example_webapp/main_test.go
Working with JSONP ¶
If you are working in an environment that always requires a 200 response, simply do:
uri?always200=true
Additionally, if you need to override the HTTP Method used, simply pass it in a similar manner:
uri?method=GET
Changes from Goweb 1 ¶
Goweb 2 changes two key things about Goweb; mapping and responding.
Instead of `MapFunc`, the `Map` method is now very flexible accepting all sorts of input. See goweb.Map below for more details.
Instead of responding via the context.Context object, we have abstracted it out to responders, that allow you to easily respond in various ways. See Responding above for more information.
We have tried to include relevant panics when you try to use old Goweb style coding to help you update any old code, but if you get stuck please ask us for help on our group: https://groups.google.com/forum/?fromgroups#!forum/golang-goweb
Index ¶
- Variables
- func DefaultHttpHandler() *handlers.HttpHandler
- func Map(options ...interface{}) (handlers.Handler, error)
- func MapAfter(options ...interface{}) (handlers.Handler, error)
- func MapBefore(options ...interface{}) (handlers.Handler, error)
- func MapController(options ...interface{}) error
- func MapFunc(path string, controllerFunc interface{}, matcherFuncs ...interface{}) interface{}
- func MapRest(pathPrefix string, controller interface{})
- func MapStatic(publicPath, systemPath string, matcherFuncs ...handlers.MatcherFunc) (handlers.Handler, error)
- func MapStaticFile(publicPath, staticFilePath string, matcherFuncs ...handlers.MatcherFunc) (handlers.Handler, error)
- func Redirect(response http.ResponseWriter, pathOrURLSegments ...interface{})
- func RedirectPerm(response http.ResponseWriter, pathOrURLSegments ...interface{})
- func RedirectTemp(response http.ResponseWriter, pathOrURLSegments ...interface{})
- func RedirectTo(response http.ResponseWriter, pathOrURLSegments ...interface{})
- func RegexPath(regexpPattern string) handlers.MatcherFunc
- func SetDefaultHttpHandler(handler *handlers.HttpHandler)
- func Status(response http.ResponseWriter, status int)
- func Test(t *testing.T, options ...interface{})
- func TestOn(t *testing.T, handler *handlers.HttpHandler, options ...interface{})
- type RequestBuilderFunc
Constants ¶
This section is empty.
Variables ¶
var ( // TestHttpRequest represents the current http.Request object // that is being tested. TestHttpRequest *http.Request // TestResponseWriter is the ResponseWriter that goweb.Test will // write to, in order to allow for testing. TestResponseWriter *testifyhttp.TestResponseWriter )
var API responders.APIResponder = responders.NewGowebAPIResponder(CodecService, Respond)
API is a responders.APIResponder which provides the ability to make API responses.
This allows a simple interface for making API responses such as the following:
return goweb.API.Respond(ctx, 404, nil, []string{"File not found"})
var CodecService codecsservices.CodecService = codecsservices.NewWebCodecService()
CodecService is the service class that provides codec capabilities to Goweb.
var Respond responders.HTTPResponder = new(responders.GowebHTTPResponder)
Respond is a responders.HTTPResponder which provides the ability to make HTTP responses.
This allows a simple interface for making normal web responses such as the following:
return goweb.Respond.WithStatus(ctx, 404)
Functions ¶
func DefaultHttpHandler ¶
func DefaultHttpHandler() *handlers.HttpHandler
DefaultHttpHandler gets the HttpHandler that can be used to handle requests.
If nothing has been set using SetDefaultHttpHandler(), a fresh one will be created and served each time this function is called.
func Map ¶
Map adds a new mapping to the DefaultHttpHandler.
The Map function has many flavours.
1. Implementing and passing in your own handlers.Handler object will just map the handler directly.
2. The path pattern, and the handler function, followed by any optional matcher funcs will cause the func to be executed when the path pattern matches.
(pathPattern, func [, matcherFuncs])
3. The HTTP method (or an array of HTTP methods), the path pettern, the handler function, followed by optional matcher funcs will cause the func to be executed when the path and HTTP method match.
(method|methods, pathPattern, func [, matcherFuncs])
4. Just the handler function, and any optional matcher funcs will add a catch-all handler. This should be the last call to Map that you make.
(func [, matcherFuncs])
Each matcherFunc argument can be one of three types:
- handlers.MatcherFunc
- []handlers.MatcherFunc
- func(context.Context) (MatcherFuncDecision, error)
Examples ¶
The following code snippets are real examples of how to use the Map function:
// POST /events handler.Map(http.MethodPost, "/events", func(c context.Context) error { // TODO: Add an event // no errors return nil }) // POST|PUT /events handler.Map([]string{http.MethodPost, http.MethodPut}, "/events", func(c context.Context) error { // TODO: Add an event // no errors return nil }) // POST|PUT|DELETE|GET /articles/2013/05/01 handler.Map("/articles/{year}/{month}/{day}", func(c context.Context) error { day := c.PathParams().Get("day") month := c.PathParams().Get("month") year := c.PathParams().Get("year") // show the articles for the specified day // no errors return nil }) // All requests handler.Map(func(c context.Context) error { // everything else is a 404 goweb.Respond.WithStatus(c, http.StatusNotFound) // no errors return nil })
For a full overview of valid paths, see the "Mapping paths" section above.
func MapAfter ¶
MapAfter adds a new mapping to the DefaultHttpHandler that will be executed after other handlers.
The usage is the same as the goweb.Map function.
After handlers are called after the normal processing handlers are finished, and usually after the response has been written. Setting headers or writing additional bytes will have no effect in after handlers.
func MapBefore ¶
MapBefore adds a new mapping to the DefaultHttpHandler that will be executed before other handlers.
The usage is the same as the goweb.Map function.
Before handlers are called before any of the normal handlers, and before any processing has begun. Setting headers is appropriate for before handlers, but be careful not to actually write anything or Goweb will likely end up trying to write the headers twice and headers set in the processing handlers will have no effect.
func MapController ¶
func MapController(options ...interface{}) error
MapController maps a controller in the handler.
A controller is any object that implements one or more of the controllers.Restful* interfaces.
They include:
RestfulController.Path(context.Context) string RestfulCreator.Create(context.Context) error RestfulReader.Read(context.Context) error RestfulManyReader.ReadMany(context.Context) error RestfulDeletor.Delete(id string, context.Context) error RestfulManyDeleter.DeleteMany(context.Context) error RestfulUpdater.Update(id string, context.Context) error RestfulReplacer.Replace(id string, context.Context) error RestfulManyUpdater.UpdateMany(context.Context) error RestfulOptions.Options(context.Context) error RestfulHead.Head(context.Context) error
Optionally, you can map Before and After methods too, to allow controller specific code to run at appropriate times:
BeforeHandler.Before(context.Context) error AfterHandler.After(context.Context) error
To implement any of these methods, you just need to provide a method with the same name and signature. For example, a simple RESTful controller that just provides a simple GET might look like this:
type MyController struct{} func (c *MyController) ReadMany(ctx context.Context) error { // TODO: do something }
The above code would map only `GET /my`.
Controller Paths ¶
This code will map the controller and use the Path() method on the controller to determine the path prefix (or it will try to guess the URL part based on the name of the struct):
MapController(controller)
This code will map the controller to the specified path prefix regardless of what the Path() method returns:
MapController(path, controller)
Optionally, you can pass matcherFuncs as optional additional arguments. See goweb.Map() for details on the types of arguments allowed.
func MapFunc ¶
func MapFunc(path string, controllerFunc interface{}, matcherFuncs ...interface{}) interface{}
MapFunc is no longer supported in Goweb 2.
Use goweb.Map instead.
func MapRest ¶
func MapRest(pathPrefix string, controller interface{})
MapRest is no longer supported in Goweb 2.
Use goweb.MapController instead.
func MapStatic ¶
func MapStatic(publicPath, systemPath string, matcherFuncs ...handlers.MatcherFunc) (handlers.Handler, error)
MapStatic maps static files from the specified systemPath to the specified publicPath.
goweb.MapStatic("/static", "location/on/system/to/files")
Goweb will automatically expand the above public path pattern from `/static` to `/static/***` to ensure subfolders are automatcially mapped.
Paths ¶
The systemPath is relative to where you will actually run your app from, for example if I am doing `go run main.go` inside the `example_webapp` folder, then `./` would refer to the `example_webapp` folder itself. Therefore, to map to the `static-files` subfolder, you just need to specify the name of the directory:
goweb.MapStatic("/static", "static-files")
In some cases, your systemPath might be different for development and production and this is something to watch out for.
Optionally, you can pass arguments of type MatcherFunc after the second argument. Unlike goweb.Map, these can only be of type MatcherFunc.
func MapStaticFile ¶
func MapStaticFile(publicPath, staticFilePath string, matcherFuncs ...handlers.MatcherFunc) (handlers.Handler, error)
MapStaticFile maps a static file from the specified staticFilePath to the specified publicPath.
goweb.MapStaticFile("favicon.ico", "/location/on/system/to/icons/favicon.ico")
Only paths matching exactly publicPath will cause the single file specified in staticFilePath to be delivered to clients.
Optionally, you can pass arguments of type MatcherFunc after the second argument. Unlike goweb.Map, these can only be of type MatcherFunc.
func Redirect ¶
func Redirect(response http.ResponseWriter, pathOrURLSegments ...interface{})
Redirect writes the Location header and sets the http.StatusFound response.
func RedirectPerm ¶
func RedirectPerm(response http.ResponseWriter, pathOrURLSegments ...interface{})
RedirectPerm writes the Location header and sets the http.StatusMovedPermanently response.
func RedirectTemp ¶
func RedirectTemp(response http.ResponseWriter, pathOrURLSegments ...interface{})
RedirectTemp writes the Location header and sets the http.StatusTemporaryRedirect response.
func RedirectTo ¶
func RedirectTo(response http.ResponseWriter, pathOrURLSegments ...interface{})
RedirectTo writes the Location header.
func RegexPath ¶
func RegexPath(regexpPattern string) handlers.MatcherFunc
RegexPath returns a MatcherFunc that mathces the path based on the specified Regex pattern.
To match a path that contains only numbers, you could do:
goweb.Map(executionFunc, goweb.RegexPath(`^[0-9]+$`))
func SetDefaultHttpHandler ¶
func SetDefaultHttpHandler(handler *handlers.HttpHandler)
SetDefaultHttpHandler sets the HttpHandler that will be used to handle requests.
You do not need to call this, as calling DefaultHttpHandler() will create one if none has been set.
Calling `SetDefaultHttpHandler(nil)` will cause a new HttpHandler to be created next time one is needed.
Writing tests ¶
When writing tests for Goweb, you should:
# Create your own HttpHandler, # use SetDefaultHttpHandler() to tell goweb to use it, # call the code being tested (code that presumably calls things like `goweb.Map` etc.) # make assertions against your own HttpHandler # call SetDefaultHttpHandler(nil) to clean things up (not necessary)
func Status ¶
func Status(response http.ResponseWriter, status int)
Status writes the header with the specified status.
func Test ¶
goweb.Test tests some functionality. You will need to include the github.com/stretchr/testify/http package in order to make use of the test functionality.
Argument signatures ¶
The Test function accepts many different signatures, following some simple rules:
- The first argument is always the testing.T object
- The second argument must be either a string, or a function that will build the TestRequest (a RequestBuilderFunc).
- If the second argument is a string, an optional third argument would be either another string or []byte array representing the body.
- The final argument must always be a func of type func(*testing.T, *testifyhttp.TestResponseWriter)
For example:
import ( // import testify testifyhttp "github.com/MG-RAST/golib/stretchr/testify/http" ) // Test(t, string, func(*testing.T, *testifyhttp.TestResponseWriter)) // Makes a request with the specified method and path, and calls // the function to make the appropriate assertions. goweb.Test(t, "METHOD path", func(t *testing.T, response *testifyhttp.TestResponseWriter) { /* assertions on the response go here */ }) // Test(t, RequestBuilderFunc, func(*testing.T, *testifyhttp.TestResponseWriter)) // Makes a request by calling the RequestBuilderFunc, and calls // the function to make the appropriate assertions. goweb.Test(t, func() *http.Request { /* build and return the http.Request */ }, func(t *testing.T, response *testifyhttp.TestResponseWriter) { /* assertions on the response go here */ })
Types ¶
type RequestBuilderFunc ¶
RequestBuilderFunc is a function that builds a TestRequest.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
The context package contains the Context interface definition.
|
The context package contains the Context interface definition. |
The controllers package provides interfaces that should be utilised when building RESTful controller objects.
|
The controllers package provides interfaces that should be utilised when building RESTful controller objects. |
The example_webapp package contains a real working example of Goweb, showing off most of its features.
|
The example_webapp package contains a real working example of Goweb, showing off most of its features. |
The handlers package contains tools for building pipelines of handlers which requests are run through in order to properly respond to requests.
|
The handlers package contains tools for building pipelines of handlers which requests are run through in order to properly respond to requests. |
The http package contains useful web constants.
|
The http package contains useful web constants. |
The paths package provides capabilities for working with paths, which is a key part of Goweb.
|
The paths package provides capabilities for working with paths, which is a key part of Goweb. |
The responders package provides objects capable of making different kinds of responses to requests.
|
The responders package provides objects capable of making different kinds of responses to requests. |
The webcontext package is Goweb's implementation of the Context object.
|
The webcontext package is Goweb's implementation of the Context object. |
test
Package that enables you to write unit tests that rely on a context.Context object.
|
Package that enables you to write unit tests that rely on a context.Context object. |