Goyave Web Framework

repository·master·Indexed 23 days ago

https://github.com/go-goyave/goyave

An opinionated, all-in-one Golang web framework optimized for building enterprise-grade REST APIs. Goyave focuses on clean architecture, reliability, and developer experience, providing built-in features for routing, middleware, request validation, DTO conversion, database persistence, and structured logging.

Tokens
7.6K
Snippets
10
Records
59
Agent score
83%

What's inside Goyave

  1. Overview of the Goyave REST API framework

    master

    Goyave is an opinionated, all-in-one Golang web framework specifically designed for building REST APIs. It focuses on enterprise-level clean architecture, reliability, and maintainability, making it suitable for medium to large-scale projects.

    Key Characteristics:

    • Focus: Business logic over technical boilerplate.
    • Philosophy: Provides a complete package with minimal setup friction, avoiding unnecessary 'magic' while remaining extensible.
    • Best For: Enterprise applications requiring robust, resilient code and structured development.
    • Not For: Hyper-optimized performance tuning, small prototypes, low-level networking control, or front-end development.
  2. Goyave framework features

    master

    Goyave provides a comprehensive suite of built-in features for professional API development, including:

    • Core Web: Routing, Controllers, Middleware, and CORS.
    • Data Handling: Request parsing, Advanced validation, DTO conversion, and Model mapping.
    • Persistence: Database support, ORM integration, and Business transactions.
    • API Capabilities: Dynamic filtering and pagination via query parameters, Websockets, and File system support.
    • Infrastructure: Authentication, Configuration management, Structured logging, and Advanced error handling.
    • Utilities: Testing utilities and Localization.
  3. How Route metadata and inheritance works

    master
    Goyave routes support a hierarchical metadata system. When you call LookupMeta(key), the system first checks the current route's Meta map. If the key is not found, it recursively asks the parent Router for the value. This allows you to define default behaviors (like CORS or authentication requirements) at a router level and override them specifically on individual routes.
  4. Apply Global and Route-specific Middleware

    master

    Goyave supports three levels of middleware execution:

    1. Global Middleware: Applied via router.GlobalMiddleware(middleware ...Middleware). These are executed for every request, including those that don't match a route or result in 405 Method Not Allowed. They are always executed first.
    2. Router/Subrouter Middleware: Applied via router.Middleware(middleware ...Middleware). These apply to the router and all its subrouters/routes.
    3. Route Middleware: Applied to specific routes (usually via the subrouter pattern). These are executed after the router-level middleware.
  5. Implement a custom StatusHandler

    master

    A StatusHandler is a component executed during the finalization step of a request's lifecycle. It is triggered if the response body is empty but a status code has already been set. This is primarily used to implement custom behaviors for user errors (4xx) or server errors (5xx).

    To create a custom status handler, implement the StatusHandler interface, which requires the Handle(response *Response, request *Request) method and the Composable interface.

  6. Use Request.Extra for custom request data

    master

    The Extra field is a map[any]any used to store additional information related to the request. This is commonly used by middleware (e.g., a JWT middleware storing token claims).

    Best Practice: To avoid collisions and unnecessary allocations when using interface{} keys, use concrete struct{} types as keys. Avoid using built-in types like string as keys in the Extra map.

  7. Use `CommonWriter` for composing custom writers

    master

    CommonWriter is a utility component designed to be used with composition. It helps avoid boilerplate when implementing chained writers that need to satisfy interfaces like PreWriter, io.Writer, io.Closer, and Flusher.

    It wraps an underlying io.Writer and delegates calls to it, handling type assertions for PreWriter, io.Closer, and Flusher (including http.Flusher) automatically.

  8. Use the Request object to access HTTP metadata

    master

    The Request type is a wrapper around the standard *http.Request that provides access to HTTP metadata such as the method, protocol, URL, headers, and body. While you can access the raw request via .Request(), it is preferred to use the provided Goyave accessors.

    Key accessors include:

    • Method(): Returns the HTTP method (e.g., GET, POST).
    • Protocol(): Returns the protocol used (e.g., HTTP/1.1).
    • URL(): Returns the *url.URL of the request.
    • Header(): Returns the http.Header map (case-insensitive).
    • Body(): Returns the io.ReadCloser for the request body. The server handles closing this body.
    • ContentLength(): Returns the length of the content.
    • RemoteAddress(): Returns the network address of the sender.
    • Referrer(): Returns the referring URL.
    • UserAgent(): Returns the client's User-Agent string.
  9. Manage request context with WithContext

    master
    The Context() method returns the request's context.Context. This context is canceled when the client connection closes or the request lifecycle ends. To attach a new context to the request, use WithContext(ctx). This method creates a shallow copy of the underlying *http.Request with the new context and returns the *Request pointer.
  10. Define custom Status Handlers

    master

    A StatusHandler is executed if a request's lifecycle ends with an empty response body and a specific HTTP status code. This is useful for defining custom error responses.

    Use router.StatusHandler(handler StatusHandler, status int, additionalStatuses ...int) to register a handler for one or more status codes. Status handlers are inherited as copies by subrouters.

  11. Database Access and Transactions

    master

    If a database connection is configured (i.e., database.connection is not none), you can interact with it via the *gorm.DB instance.

    • HasDB() bool: Checks if a database connection is active.
    • DB() *gorm.DB: Returns the root database instance. Panics if no connection is set up.
    • Transaction(opts ...*sql.TxOptions) func(): Wraps all subsequent DB requests in a transaction. It returns a rollback function that must be called to complete/rollback the transaction and restore the original DB state. Note: This is intended for testing and is not concurrently safe.
    • CloseDB() error: Closes the database connection.