Documentation ¶
Index ¶
- type ContentFileNameReader
- type ContentReader
- type ContentTypeReader
- type ErrorWithCode
- type ErrorWithStatus
- type ErrorWithStatusCode
- type Redirector
- type Responder
- func (r Responder) Accepted(value interface{}, errs ...error)
- func (r Responder) BadGateway(msg string, args ...interface{})
- func (r Responder) BadRequest(msg string, args ...interface{})
- func (r Responder) Conflict(msg string, args ...interface{})
- func (r Responder) Created(value interface{}, errs ...error)
- func (r Responder) Download(fileName string, data io.Reader, errs ...error)
- func (r Responder) DownloadBytes(fileName string, data []byte, errs ...error)
- func (r Responder) Fail(err error)
- func (r Responder) Forbidden(msg string, args ...interface{})
- func (r Responder) GatewayTimeout(msg string, args ...interface{})
- func (r Responder) Gone(msg string, args ...interface{})
- func (r Responder) HTML(markup string, errs ...error)
- func (r Responder) HTMLTemplate(htmlTemplate *template.Template, ctxValue interface{}, errs ...error)
- func (r Responder) InternalServerError(msg string, args ...interface{})
- func (r Responder) MethodNotAllowed(msg string, args ...interface{})
- func (r Responder) NoContent(errs ...error)
- func (r Responder) NotFound(msg string, args ...interface{})
- func (r Responder) NotImplemented(msg string, args ...interface{})
- func (r Responder) NotModified(errs ...error)
- func (r Responder) Ok(value interface{}, errs ...error)
- func (r Responder) Redirect(uriFormat string, args ...interface{})
- func (r Responder) RedirectPermanent(uriFormat string, args ...interface{})
- func (r Responder) RedirectPermanentTo(redirector Redirector, errs ...error)
- func (r Responder) RedirectTo(redirector Redirector, errs ...error)
- func (r Responder) Reply(status int, value interface{}, errs ...error)
- func (r Responder) Serve(fileName string, data io.Reader, errs ...error)
- func (r Responder) ServeBytes(fileName string, data []byte, errs ...error)
- func (r Responder) ServiceUnavailable(msg string, args ...interface{})
- func (r Responder) TooManyRequests(msg string, args ...interface{})
- func (r Responder) Unauthorized(msg string, args ...interface{})
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ContentFileNameReader ¶ added in v0.4.1
type ContentFileNameReader interface { // ContentFileName triggers an attachment-style value for the Content-Disposition header when writing // raw HTTP responses. When this returns an empty string, the response's disposition should // be "inline". When it's any other value, it will be "attachment; filename=" with this value. // // This only applies when the result is a ContentReader, so you're returning raw results. ContentFileName() string }
ContentFileNameReader provides the 'filename' details to use when filling out the HTTP Content-Disposition header. Any io.Reader that 'respond' comes across will be treated as raw bytes, not a JSON-marshaled payload. By default, 'respond' will specify "inline" for all raw responses (great for images and scripts you want to display inline in your UI).
If you implement this interface, you can change the behavior to have the browser/client trigger a download of this asset instead. The file name you return here will dictate the default file name proposed by the save dialog.
type ContentReader ¶ added in v0.4.1
type ContentReader interface { // Content supplies the raw data that should be sent to the caller when responding. Content() io.ReadCloser }
ContentReader indicates that the value you're responding with is actually raw byte content and not something that should be JSON-marshaled. The data read from the resulting io.Reader is what we will send back to the caller.
type ContentTypeReader ¶ added in v0.4.1
type ContentTypeReader interface { // ContentType returns the "Content-Type" header you want to apply to the HTTP response. This // only applies when the result is a ContentReader, so you're returning raw results. ContentType() string }
ContentTypeReader provides details about a file-based response to indicate what we should use as the "Content-Type" header. Any io.Reader that 'respond' comes across will be treated as raw bytes, not a JSON-marshaled payload. By default, the Content-Type of the response will be "application/octet-stream", but if your result implements this interface, you can tell the responder what type to use instead. For instance, if the result is a JPG, you can have your result return "image/jpeg" and 'respond' will use that in the header instead of octet-stream.
type ErrorWithCode ¶
ErrorWithCode is a type of error that contains a Code() function which indicates the HTTP 4XX/5XX status code this type of failure should respond with.
type ErrorWithStatus ¶
ErrorWithStatus is a type of error that contains a Status() function which indicates the HTTP 4XX/5XX status code this type of failure should respond with.
type ErrorWithStatusCode ¶
ErrorWithStatusCode is a type of error that contains a StatusCode() function which indicates the HTTP 4XX/5XX status code this type of failure should respond with.
type Redirector ¶
type Redirector interface { // Redirect returns the URL that you want the response to redirect to. Redirect() string }
Redirector defines a type that your handler can "return" to one of the responder functions to indicate that this should be a redirect response instead of the standard 2XX style response you intended. This can also be used in general purpose Reply() calls to trigger redirects as well.
type Responder ¶
type Responder struct {
// contains filtered or unexported fields
}
Responder provides helper functions for marshaling Go values/streams to send back to the user as well as applying the correct status code and headers. It's the core data structure for this package.
func To ¶
func To(w http.ResponseWriter, req *http.Request) Responder
To creates a "Responder" that replies to the inputs for the given HTTP request. For style/consistency purposes, this should be the first line of your HTTP handler: `response := responder.To(w, req)`
Example (Basic) ¶
A simple example. Format the string "Hello World" as JSON and respond to the caller with a 200 status code. We create a "Responder" for this request and then use it to respond with that result.
package main import ( "net/http" "github.com/monadicstack/respond" ) func main() { _ = func(w http.ResponseWriter, req *http.Request) { respond.To(w, req).Ok("Hello World") } }
Output:
Example (BusinessLogic) ¶
You can return any primitive or complex value to the caller as JSON and respond with a 200. You focus on your business logic and responders offload the burden of marshalling, setting status code, and basic header application.
package main import ( "net/http" "github.com/monadicstack/respond" ) func param(req *http.Request, name string) string { return "" } func findUser(id string) (map[string]interface{}, bool) { return nil, true } func main() { _ = func(w http.ResponseWriter, req *http.Request) { response := respond.To(w, req) userId := param(req, "user") user, ok := findUser(userId) if !ok { response.NotFound("user not found: %s", userId) return } response.Ok(user) } }
Output:
Example (Error) ¶
There are responder functions to support most of the common HTTP failures you typically encounter when building APIs/Services.
package main import ( "errors" "net/http" "github.com/monadicstack/respond" ) var ErrNotFound = errors.New("not found") var ErrBadCredentials = errors.New("bad credentials") var ErrAuthorization = errors.New("authorization") func doTask() (interface{}, error) { return nil, nil } func main() { _ = func(w http.ResponseWriter, req *http.Request) { response := respond.To(w, req) result, err := doTask() switch err { case nil: response.Ok(result) case ErrNotFound: response.NotFound("task not found") case ErrBadCredentials: response.Unauthorized("bad username/password") case ErrAuthorization: response.Forbidden("you don't have rights to do that") default: response.InternalServerError("unexpected error: %v", err) } } }
Output:
Example (ErrorShorthand) ¶
Success functions like Ok(), Accept(), etc optionally take an error (admittedly by bastardizing variadic arguments). If the error you pass is nil, the request will result in the 2XX status that you wanted w/ the return value. If the error is NOT nil then we'll respond with a 4XX/5XX status and the error's message instead.
We will attempt to assign a meaningful HTTP status code by unwrapping your non-nil error and look for one of three functions:
* Status() int * StatusCode() int * Code() int
We'll assume that the resulting int is the HTTP status code you want to fail with.
package main import ( "net/http" "github.com/monadicstack/respond" ) func doTask() (interface{}, error) { return nil, nil } func main() { _ = func(w http.ResponseWriter, req *http.Request) { response := respond.To(w, req) // Option 1: pass the values separately result, err := doTask() response.Ok(result, err) // Option 2: pass the return values directly to your responder function response.Ok(doTask()) } }
Output:
Example (Middleware) ¶
You can use respond with any standard middleware you want.
package main import ( "net/http" "github.com/monadicstack/respond" ) func authenticate(req *http.Request) (*http.Request, error) { return nil, nil } func main() { _ = func(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) { response := respond.To(w, req) req, err := authenticate(req) if err != nil { response.Unauthorized(err.Error()) return } next(w, req) } }
Output:
func (Responder) Accepted ¶
Accepted writes a 202 style response to the caller by marshalling the given raw value. If you provided an error, we'll ignore the value and return the appropriate 4XX/5XX response instead.
func (Responder) BadGateway ¶
BadGateway responds w/ a 502 status and a body that contains the status/message.
func (Responder) BadRequest ¶
BadRequest responds w/ a 400 status and a body that contains the status/message.
func (Responder) Conflict ¶
Conflict responds w/ a 409 status and a body that contains the status/message.
func (Responder) Created ¶
Created writes a 201 style response to the caller by marshalling the given raw value. If you provided an error, we'll ignore the value and return the appropriate 4XX/5XX response instead.
func (Responder) Download ¶
Download delivers the file data to the client/caller in a way that indicates that it should be given a download prompt (if using a browser or some other UI-based client). The file name determines the Content-Type header we'll use in the response as well as be the default download name that the caller will be presented with in their client/browser.
It will read your 'data' stream to completion but it will still be up to you to Close() it afterwards if need be.
func (Responder) DownloadBytes ¶
DownloadBytes delivers the file data to the client/caller in a way that indicates that it should be given a download prompt (if using a browser or some other UI-based client). The file name determines the Content-Type header we'll use in the response as well as be the default download name that the caller will be presented with in their client/browser.
func (Responder) Fail ¶
Fail accepts the error generated by your handler and responds with the most appropriate 4XX/5XX status code and message for that error. It tries to unwrap the error looking for an error with either a Status(), StatusCode(), or Code() function (see the ErrorXXX interfaces in this package) to determine what HTTP status code we will try to fail with.
func (Responder) Forbidden ¶
Forbidden responds w/ a 403 status and a body that contains the status/message.
func (Responder) GatewayTimeout ¶
GatewayTimeout responds w/ a 504 status and a body that contains the status/message.
func (Responder) HTML ¶
HTML returns 200 status code with the given "text/html" response body. If you provided an error, we'll ignore the value and return the appropriate 4XX/5XX response instead.
func (Responder) HTMLTemplate ¶
func (r Responder) HTMLTemplate(htmlTemplate *template.Template, ctxValue interface{}, errs ...error)
HTMLTemplate accepts your pre-parsed html template and evaluates it using the given context value. All of the bytes generated by the template will be written directly to the response writer. If you provided an error, we'll return the appropriate 4XX/5XX response instead.
func (Responder) InternalServerError ¶
InternalServerError responds w/ a 500 status and a body that contains the status/message.
func (Responder) MethodNotAllowed ¶
MethodNotAllowed responds w/ a 405 status and a body that contains the status/message.
func (Responder) NoContent ¶
NoContent writes a 204 style response to the caller. This will not write any bytes to the response other than the status code. If you provided an error, we'll ignore the 204 and return the appropriate 4XX/5XX response instead.
func (Responder) NotFound ¶
NotFound responds w/ a 404 status and a body that contains the status/message.
func (Responder) NotImplemented ¶
NotImplemented responds w/ a 501 status and a body that contains the status/message.
func (Responder) NotModified ¶
NotModified writes a 304 response with no content. You typically will use this when performing ETag staleness checks and the like.
func (Responder) Ok ¶
Ok writes a 200 style response to the caller by marshalling the given raw value. If you provided an error, we'll ignore the value and return the appropriate 4XX/5XX response instead.
func (Responder) Redirect ¶
Redirect performs a 307-style TEMPORARY redirect to the given resource. You can use printf-style formatting to make it easier to build the location you're redirecting to.
func (Responder) RedirectPermanent ¶
RedirectPermanent performs a 308-style PERMANENT redirect to the given resource. You can use printf-style formatting to make it easier to build the location you're redirecting to.
func (Responder) RedirectPermanentTo ¶
func (r Responder) RedirectPermanentTo(redirector Redirector, errs ...error)
RedirectPermanentTo performs a 308-style PERMANENT redirect to the URL returned by calling Redirect() on your value.
func (Responder) RedirectTo ¶
func (r Responder) RedirectTo(redirector Redirector, errs ...error)
RedirectTo performs a 307-style TEMPORARY redirect to the URL returned by calling Redirect() on your value.
func (Responder) Reply ¶
Reply lets you respond with the custom status code of your choice and a JSON-marshaled version of your value.
func (Responder) Serve ¶
Serve responds with some sort of file data in an inline fashion. This lets you deliver things like inline images or videos or any other content that you want your callers/clients to embed directly in the client. The file name in this case case is simply used to determine the proper Content-Type to include in the response.
It will read your 'data' stream to completion but it will still be up to you to Close() it afterwards if need be.
func (Responder) ServeBytes ¶
ServeBytes responds with some sort of file data in an inline fashion. This lets you deliver things like inline images or videos or any other content that you want your callers/clients to embed directly in the client. The file name in this case case is simply used to determine the proper Content-Type to include in the response.
func (Responder) ServiceUnavailable ¶
ServiceUnavailable responds w/ a 503 status and a body that contains the status/message.
func (Responder) TooManyRequests ¶
TooManyRequests responds w/ a 429 status and a body that contains the status/message.
func (Responder) Unauthorized ¶
Unauthorized responds w/ a 401 status and a body that contains the status/message.