Request and Response
HTTP web applications work in request-response mode and Gkernel uses certain objects to represent and work with that requests and responses.
Request
Gkernel uses standard net/http Request type to represent HTTP request received by a server.
Response
Response represents result of request processing that should be sent to user. Response can be of any type that implements next interface:
type Response interface {
GetHttpStatus() int
GetHeaders() http.Header
GetBodyBytes() *bytes.Buffer
}
Gkernel framework provides a bunch of ready to use Response types:
BytesResponse
Represents simples response - slices of bytes.
BytesResponse has next fields:
Body *bytes.Buffer
- stores response bytes, that should be sent to user.
BytesResponse has next methods:
func (r *basicResponse) GetHeaders() http.Header
func (r *basicResponse) HeaderSet(key, value string)
- intended to simplify adding new headers to response. You can call
r.GetHeaders().Set("MyHeader", "my header value")
or just
r.HeaderSet("MyHeader", "my header value")
func (r *basicResponse) GetHttpStatus() int
- returns response's HTTP statusfunc (r *basicResponse) SetHttpStatus(status int)
- sets response's HTTP status.func (r *BytesResponse) ClearBody()
- removes old Body bytes buffer, creates new and emptyfunc (r *BytesResponse) GetBodyBytes() *bytes.Buffer
- returns a pointer to the Body bytes buffer
To create new BytesResponse you can use factory method NewBytesResponse()
:
import (
"github.com/bassbeaver/gkernel/web/response"
)
responseObj := response.NewBytesResponse()
BytesResponseWriter
Is a simple wrapper around BytesResponse
to use in case when you need to use Gkernel's BytesResponse as http.ResponseWriter
.
For example, adding pprof endpoints to Gkernel's routing:
package main
import (
webKernel "github.com/bassbeaver/gkernel/web"
kernelResponse "github.com/bassbeaver/gkernel/web/response"
"net/http"
"net/http/pprof"
)
...
kernelObj, kernelError := webKernel.NewKernel("/path/to/config")
if nil != kernelError {
panic(kernelError)
}
...
registerPprofRoute := func(name, url string, handlerFunc http.HandlerFunc) {
kernelObj.RegisterRoute(&webKernel.Route{
Name: name,
Url: url,
Methods: []string{http.MethodGet},
Controller: func(request *http.Request) kernelResponse.Response {
w := kernelResponse.NewBytesResponseWriter()
handlerFunc(w, request)
return w
},
})
}
registerPprofRoute("pprof:index", "/debug/pprof/", pprof.Index)
registerPprofRoute("pprof:cmdline", "/debug/pprof/cmdline", pprof.Cmdline)
registerPprofRoute("pprof:profile", "/debug/pprof/profile", pprof.Profile)
registerPprofRoute("pprof:symbol", "/debug/pprof/profile", pprof.Symbol)
registerPprofRoute("pprof:trace", "/debug/pprof/trace", pprof.Trace)
registerPprofRoute("pprof:heap", "/debug/pprof/heap", pprof.Index)
RedirectResponse
Represents response that should be sent to useragent to perform redirect.
To create new BytesResponse you can use factory method:
NewRedirectResponse(request *http.Request, url string, httpStatus int) *RedirectResponse
Where:
request
is current Request objecturl
- URL to redirect tohttpStatus
HTTP status to set for this response. As default status you can usehttp.StatusSeeOther
(303)
status.
ViewResponse
You can use ViewResponse when you need to return rendered template (usually html template).
ViewResponse has next methods:
func (r *basicResponse) GetHeaders() http.Header
func (r *basicResponse) HeaderSet(key, value string)
- sets request's header valuefunc (r *basicResponse) GetHttpStatus() int
- returns response's HTTP statusfunc (r *basicResponse) SetHttpStatus(status int)
- sets response's HTTP status.func (r *BytesResponse) GetBodyBytes() *bytes.Buffer
- returns a pointer to the Body bytes bufferfunc (r *ViewResponse) SetData(data interface{})
- sets template's data (variables used for templates rendering)func (r *ViewResponse) SetTemplate(tpl *template.Template)
- is used with Gkernel and usually you do not need this method.
In most cases, to return rendered template (view) as a Response you will be enough to use factory method:
NewViewResponse(templateName string) *ViewResponse
Example (from bassbeaver/gkernel-skeleton IndexController):
func (c *IndexController) PageWithParam(request *http.Request) kernelResponse.Response {
var viewData struct {
CsrfToken string
User auth.UserInterface
Header struct {
Title string
}
H1 string
Param string
}
viewData.Header.Title = "gkernel skeleton site"
viewData.H1 = "This is page with URL parameter"
viewData.CsrfToken = csrfService.GetTokenFromRequestContext(request)
if auth.GetUser(request) != nil {
viewData.User = auth.GetUser(request).(*user_provider.UserStub)
}
viewData.Param = request.URL.Query().Get(":parameterValue")
response := kernelResponse.NewViewResponse("index/page-with-param.gohtml")
response.SetData(viewData)
return response
}
Notice: templateName
from NewViewResponse(templateName string) *ViewResponse
is relative path to template file.
Full path to template file Gkernel determines according to the following algorithm:
<path to application Config file>/<templates_path>/<templateName>
Where:
<path to application Config file>
- path to application's configuration file<templates_path>
- value application's configuration file<templateName>
- template's name fromNewViewResponse(templateName string)
factory method
Access to Gkernels html/template object and registration of custom template functions
To work with templates Gkernel uses html/template library.
Templates parsing happens during templates during application startup after Gkernel's Run()
method call.
Sometimes you need access to template.Template object (to register custom template functions or make other configuration).
Gkernel provides appropriate method GetTemplates()
.
Example of custom template functions registration:
kernelObj, kernelError := webKernel.NewKernel("/path/to/config")
...
kernelObj.GetTemplates().Funcs(template.FuncMap{
"sequence": func(size int) []int {
sequence := make([]int, size)
for i := 0; i < size; i++ {
sequence[i] = i
}
return sequence
},
"addInt": func(a, b int) int {
return a + b
},
"subInt": func(a, b int) int {
return a - b
},
})
After that you can use these functions in templates:
{{range $i := sequence $pagination.TotalPages}}
{{$pageNum := addInt $i 1}}
<a href="{{$pagination.CurrentUrl}}?page={{$pageNum}}">{{$pageNum}}</a>
{{end}}
JsonResponse
Represents json encoded response.
JsonResponse has next fields:
Body interface{}
- response value, that should be json encoded and sent to user
JsonResponse has next methods:
func (r *basicResponse) GetHeaders() http.Header
func (r *basicResponse) HeaderSet(key, value string)
- sets request's header valuefunc (r *basicResponse) GetHttpStatus() int
- returns response's HTTP statusfunc (r *basicResponse) SetHttpStatus(status int)
- sets response's HTTP status.func (r *BytesResponse) GetBodyBytes() *bytes.Buffer
- returns a pointer to the Body bytes buffer
To create new JsonResponse you can use factory method:
NewJsonResponse() *JsonResponse
this factory method sets
Content-Type
header to application/json
for created Response object.
Also, Gkernel provides factory method to create Json Api Response:
NewJsonApiResponse() *JsonResponse
It is similar to NewJsonResponse()
except that sets Content-Type
header to application/json
.
WebsocketUpgradeResponse
Represents Response used to upgrade protocol to WebSocket.
To create new WebsocketUpgradeResponse you can use factory method
NewWebsocketUpgradeResponse(upgrader *websocket.Upgrader, controller WebSocketController) *WebsocketUpgradeResponse
Where:
upgrader
- instance ofgorilla/websocket.Upgrader
controller
- function with signature:func(*websocket.Conn)