Lifecycle
The life cycle of Response defines the period during which the HTTP response can be modified.
As a general rule, Response must be configured before return of a gox.Page or one gox.ActionDuring the generation of the temperate the response is no longer modifiable to ensure the consistency of the content sent to the client.
If you want to know all the APIs available to modify the response, see the documentation for Response.
What is the lifecycle?
Each HTTP request creates a new instance of ctx.Response.
During the execution of a gox.Page or one gox.Action It is possible to configure the status code, the headers, cookies and the other properties of the response.
However, once GOX begins to generate the template returned by the page or action, Response no longer modifiable.
When can Response be modified?
Response remains modifiable throughout the execution of a gox.Page or one gox.Actionuntil the return.
For this reason, the entire response configuration must be done before the result is returned.
func GET(ctx *gox.Context) gox.Page {
// Response es modificable.
ctx.Response.Status.SetCode(200)
ctx.Response.Headers.Set("Cache-Control", "no-cache")
// Response se cierra para modificaciones.
return <h1>Hola George</h1>
} In this example all the configuration of Response occurs before return, so all operations are valid.
When can Response no longer be modified?
Response is no longer modifiable during the return of a gox.Page or one gox.Action.
func GET(ctx *gox.Context) gox.Page {
// Response es modificable.
ctx.Response.Status.SetCode(200)
// Response se cierra para modificaciones.
return <>
// Response ya no es modificable.
<h1>Hola George</h1>
</>
} Once GOX begins to generate the template returned by the page or action, any attempt to modify Response It will make a mistake.
Common errors
Modify Response from a component
The components can be executed when Response It has already ceased to be modifiable.
func IsLogin(ctx *gox.Context, user string) gox.Component {
if !validate.IsLogin(ctx) {
ctx.Response.DoneWith(403) // Error: Response ya no es modificable.
}
return <h1>Bienvenido {{ user }}</h1>
}
func GET(ctx *gox.Context) gox.Page {
// Response es modificable.
name := "George"
// Response se cierra para modificaciones.
return <div>
// Response ya no es modificable.
<&IsLogin ctx={{ ctx }} name={{ name }}/>
</div>
} Although this code may seem correct, the component is run during the generation of the temperate, when Response It no longer supports any changes.
For this reason, it is not recommended to amend Response from components.
Modify Response from an expression
The same problem can occur within an expression used by the temperate.
func LoginClass(ctx *gox.Context) string {
if !validate.IsLogin(ctx) {
ctx.Response.Status.SetCode(403) // Error: Response ya no es modificable.
return "fg-red"
}
return "fg-green"
}
func GET(ctx *gox.Context) gox.Page {
// Response es modificable.
name := "George"
// Response se cierra para modificaciones.
return <h1 class={{ LoginClass(ctx) }}>
Hola {{ name }}
</h1>
} Although the function is called from the temperate, its execution occurs during the generation of the response, when Response It can no longer be changed.
Modify Response from a deferred function
The functions recorded through defer are executed after the gox.Page or gox.Action sets its return value.
func GET(ctx *gox.Context) gox.Page {
// Response es modificable.
defer func() {
// Response ya no es modificable.
ctx.Response.Headers.Set("Cache-Control", "no-cache")
}()
// Response es modificable.
// Response se cierra para modificaciones.
return <h1>Hola George</h1>
} In this example, the deferred function tries to modify the headers after Response it has been closed for modifications, so the operation makes a mistake.
For this reason, it should not be amended. Response from functions performed by defer. Use these functions only for cleaning operations that do not alter the HTTP response.
What's the right way?
The entire configuration of Response should be done before return of a gox.Page or one gox.Action.
func GET(ctx *gox.Context) gox.Page {
if !validate.IsLogin(ctx) {
ctx.Response.DoneWith(403)
}
ctx.Response.Headers.Set("Cache-Control", "no-cache")
return <h1>Hola George</h1>
} This pattern keeps all the response settings in one place, facilitates the reading of the code and avoids ambiguous behaviors.
If you need to finish an request immediately, check the documentation of DoneWith.
Best practices
- Configure
Responsebeforereturnof agox.Pageor onegox.Action. - Keep the entire response configuration grouped at the beginning of the function.
- Avoid changing
Responsefrom reusable components. - Avoid changing
Responsefrom functions performed as part of the temperate. - Avoid changing
Responsefrom functions performed bydefer. - Use
DoneWith()where the request is to be completed immediately.