Documentation ¶
Overview ¶
Package httputils provides HTTP utility functions.
Index ¶
- func CatchingMiddleware(logger log.Logger) mux.MiddlewareFunc
- func CatchingRedirect(writer http.ResponseWriter, request *http.Request, url string, statusCode int) error
- func RunServer(shutdownCtx context.Context, server Server, logger log.Logger, ...) (ok bool)
- func SPAFallbackMiddleware() mux.MiddlewareFunc
- func StaticAssetHandler(fileSystem http.FileSystem, logger log.Logger) http.Handler
- type CatchingResponseWriter
- type File
- type FileInfo
- type FileSystem
- type HTTPClient
- type Handler
- type Logger
- type ResponseWriter
- type Server
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CatchingMiddleware ¶
func CatchingMiddleware(logger log.Logger) mux.MiddlewareFunc
CatchingMiddleware ...
It's a middleware that captures the last error from the Write() method of the http.ResponseWriter interface and logs it via the provided log.Logger interface.
Example ¶
// use the standard logger for error handling logger := stdlog.New(os.Stderr, "", stdlog.LstdFlags) catchingMiddleware := CatchingMiddleware( // wrap the standard logger via the github.com/go-log/log package print.New(logger), ) var handler http.Handler // nolint: staticcheck handler = http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) { // writing error will be handled by the catching middleware fmt.Fprintln(writer, "Hello, world!") // nolint: errcheck }) handler = catchingMiddleware(handler) http.Handle("/", handler) logger.Fatal(http.ListenAndServe(":8080", nil))
Output:
func CatchingRedirect ¶
func CatchingRedirect( writer http.ResponseWriter, request *http.Request, url string, statusCode int, ) error
CatchingRedirect ...
It's a complete analog of the http.Redirect() function with capturing the last error from the Write() method of the http.ResponseWriter interface.
func RunServer ¶
func RunServer( shutdownCtx context.Context, server Server, logger log.Logger, interruptSignals ...os.Signal, ) (ok bool)
RunServer ...
It runs the provided Server interface via its ListenAndServe() method, then waits for specified signals. If there're no signals specified, the function will wait for any possible signals.
After receiving the signal, the function will stop the server via its Shutdown() method. The provided context will be used for calling this method, and just for that.
Attention! The function will return only after completing of ListenAndServe() and Shutdown() methods of the server.
Errors that occurred when calling ListenAndServe() and Shutdown() methods of the server will be processed by the provided log.Logger interface. (Use the github.com/go-log/log package to wrap the standard logger.) The fact that an error occurred will be reflected in the boolean flag returned by the function.
Example ¶
server := &http.Server{Addr: ":8080"} // use the standard logger for error handling logger := stdlog.New(os.Stderr, "", stdlog.LstdFlags) if ok := RunServer( context.Background(), server, // wrap the standard logger via the github.com/go-log/log package print.New(logger), os.Interrupt, ); !ok { // the error is already logged, so just end the program with the error status os.Exit(1) }
Output:
func SPAFallbackMiddleware ¶
func SPAFallbackMiddleware() mux.MiddlewareFunc
SPAFallbackMiddleware ...
A SPA often manages its routing itself, so all relevant requests must be handled by an index.html file. A backend, in turn, must be responsible for an API and distribution of static files.
To separate these types of requests, the following heuristic is used. If the request uses the GET method and contains the text/html value in the Accept header, the index.html file is returned (more precisely, a path part of a request URL is replaced to "/"). All other requests are processed as usual. The fact is that any routing requests sent from a modern browser meet described requirements.
This solution is based on the proxy implementation in the development server of the Create React App project. See: https://create-react-app.dev/docs/proxying-api-requests-in-development/
Example ¶
staticAssetHandler := http.FileServer(http.Dir("/var/www/example.com")) staticAssetHandler = SPAFallbackMiddleware()(staticAssetHandler) http.Handle("/", staticAssetHandler) log.Fatal(http.ListenAndServe(":8080", nil))
Output:
func StaticAssetHandler ¶
StaticAssetHandler ...
It's a complete analog of the http.FileServer() function with applied SPAFallbackMiddleware() and CatchingMiddleware() middlewares.
Example ¶
// use the standard logger for error handling logger := stdlog.New(os.Stderr, "", stdlog.LstdFlags) staticAssetHandler := StaticAssetHandler( http.Dir("/var/www/example.com"), // wrap the standard logger via the github.com/go-log/log package print.New(logger), ) http.Handle("/", staticAssetHandler) stdlog.Fatal(http.ListenAndServe(":8080", nil))
Output:
Types ¶
type CatchingResponseWriter ¶
type CatchingResponseWriter struct { http.ResponseWriter // contains filtered or unexported fields }
CatchingResponseWriter ...
It wraps the http.ResponseWriter interface to save the last error that occurred while calling the http.ResponseWriter.Write() method.
Errors of writing via the http.ResponseWriter interface are important to handle. See for details: https://stackoverflow.com/a/43976633
Attention! The CatchingResponseWriter structure only supports methods that are declared directly in the http.ResponseWriter interface. Any optional interfaces (http.Flusher, http.Hijacker, etc.) aren't supported.
Example ¶
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { catchingWriter := NewCatchingResponseWriter(writer) // use the catchingWriter object as the usual http.ResponseWriter interface http.Redirect( catchingWriter, request, "http://example.com/", http.StatusMovedPermanently, ) if err := catchingWriter.LastError(); err != nil { log.Printf("unable to write the HTTP response: %v", err) } })
Output:
func NewCatchingResponseWriter ¶
func NewCatchingResponseWriter( writer http.ResponseWriter, ) *CatchingResponseWriter
NewCatchingResponseWriter ...
It allocates and returns a new CatchingResponseWriter object wrapping the provided http.ResponseWriter interface.
func (CatchingResponseWriter) LastError ¶
func (writer CatchingResponseWriter) LastError() error
LastError ...
It returns the last saved error from the Write() method of the wrapped http.ResponseWriter interface.
type FileSystem ¶
type FileSystem interface { http.FileSystem }
FileSystem ...
It's used only for mock generating.
type HTTPClient ¶
HTTPClient ...
It represents the simplified interface of the http.Client structure (the primary method only). It is useful for mocking the latter.
See for details: https://www.thegreatcodeadventure.com/mocking-http-requests-in-golang/
type ResponseWriter ¶
type ResponseWriter interface { http.ResponseWriter }
ResponseWriter ...
It's used only for mock generating.