Skip to content

Releases: gofr-dev/gofr

v1.37.0

08 Apr 14:29
c72bc69
Compare
Choose a tag to compare

🚀 Features

1. Dgraph Migration Support

  • Added native migration capabilities for Dgraph through new methods, enabling precise schema evolution:
    // Apply or update the complete Dgraph schema 
    ApplySchema(ctx context.Context, schema string) error
    // Atomically create or update a field definition
    AddOrUpdateField(ctx context.Context, fieldName, fieldType, directives string) error  
    // Permanently remove a field/predicate and its associated data 
    DropField(ctx context.Context, fieldName string) error	 
  • Refer to the official documentation for full usage details.

🛠 Improvements

1. gRPC Server Configuration via AddGRPCServerOptions

  • GoFr now allows configuring advanced gRPC ServerOptions.

  • Example: Enabling TLS and setting a connection timeout

    creds, _ := credentials.NewServerTLSFromFile("server-cert.pem", "server-key.pem")
    
    app.AddGRPCServerOptions(
        grpc.Creds(creds),
        grpc.ConnectionTimeout(10*time.Second),
    )
  • Refer to the official documentation to know more.

2. Add Custom Unary Interceptors

app.AddGRPCUnaryInterceptors(authInterceptor)
  • GoFr already logs, traces and sends default metrics for all gRPC calls. No external interceptor for such features is necessary. Custom server-side UnaryServerInterceptors can now be registered easily for use cases like:

    • Authentication
    • Request validation
  • For guidance on how to define Server UnaryInterceptors that can be added in your GoFr's gRPC server, check out the official documentation.

3. Advanced gRPC Client DialOptions Support

  • Clients can now be customized extensively via grpc.DialOptions.
    This allows to add gRPC services with :
    - Secure TLS communication
    - Load-balanced connections
    - Retry logic
    - Context-aware metadata injection (useful for tracing and auth)

    const serviceConfig = `{
      "loadBalancingPolicy": "round_robin",
      "methodConfig": [{
        "name": [{"service": "HelloService"}],
        "retryPolicy": {
          "maxAttempts": 4,
          "initialBackoff": "0.1s",
          "maxBackoff": "1s",
          "backoffMultiplier": 2.0,
          "retryableStatusCodes": ["UNAVAILABLE", "RESOURCE_EXHAUSTED"]
        }
      }]
    }` 
    
    // Metadata interceptor to add client ID to each request
    func  MetadataUnaryInterceptor(ctx context.Context, method string, req, reply any,
        cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption,
    ) error {
        md := metadata.Pairs("client-id", "f1b1a372-02f5-4065-9ccf-113d34a3d5ed")
        
        ctx = metadata.NewOutgoingContext(ctx, md) 
    
        return invoker(ctx, method, req, reply, cc, opts...)
    } 
    
    func  main() {
        app := gofr.New()
    
        creds, err := credentials.NewClientTLSFromFile("cert.pem", "") if err != nil {
            app.Logger().Errorf("TLS error: %v", err) return }
    
        grpcClient, err := client.NewHelloServiceGoFrClient(
            app.Config.Get("GRPC_SERVER_HOST"),
            app.Metrics(),
            grpc.WithTransportCredentials(creds),
            grpc.WithDefaultServiceConfig(serviceConfig),
            grpc.WithChainUnaryInterceptor(MetadataUnaryInterceptor),
        ) 
    
    	if err != nil {
            app.Logger().Errorf("Failed to create client: %v", err) return 
        }
    
        handler := NewGreetHandler(grpcClient)
        
        app.GET("/hello", handler.Hello)
        
        app.Run()
    }

🛠 Fixes

1. SurrealDB Update Method: Unexpected Behavior Fixed

  • Regardless of the input, the Update method previously inserted an unexpected hardcoded key-value pair. The method now correctly updates only the intended fields as passed by the caller.

v1.36.0

25 Mar 15:02
ab76d66
Compare
Choose a tag to compare

Release - v1.36.0

🚀 Features

1. SurrealDB Migration Support

  • Added support for database migration operations in SurrealDB.
  • Supported methods include:
     // Creates a new namespace in SurrealDB.
     CreateNamespace(ctx context.Context, namespace string) error  
     // Creates a new database in SurrealDB.
     CreateDatabase(ctx context.Context, database string) error 
     // Deletes a namespace from SurrealDB.
     DropNamespace(ctx context.Context, namespace string) error
     // Deletes a database from SurrealDB.  
     DropDatabase(ctx context.Context, database string) error  
  • Refer to our official documentation to know more.

🛠 Improvements

1. Default Metrics for SurrealDB Data Source

  • Introduced default metric collection for SurrealDB at the specified METRICS_PORT, enabling better observability and performance monitoring.

2. JWT Claim Validations

  • EnableOAuth now takes an additional JWT validation options as jwt.ParserOption, allowing fine-grained control over claim validation.
  • Example :
     app.EnableOAuth(
     	"http://jwks-endpoint",
     	20,
     	jwt.WithExpirationRequired(), // to enforce presence of exp claim in every token
     	jwt.WithAudience("https://api.example.com"),
     	jwt.WithIssuer("https://auth.example.com")
     )
  • To know more about the different claim validation options, check out our official documentation.

🛠 Fixes

1. pprof Profiling Enhancements

  • Previously, the pprof endpoint was restricted to being enabled only when the APP_ENV=DEBUG environment variable was set, and it ran on the specified HTTP_PORT. This prevented users from loading their different environments, for e.g. stage or production configurations if we set APP_ENV as DEBUG for profiling.
  • GoFr now automatically enables pprof profiling on METRICS_PORT (default: 2121).
  • Profiling endpoints include :
    • /debug/pprof/cmdline
    • /debug/pprof/profile
    • /debug/pprof/symbol
    • /debug/pprof/trace
    • /debug/pprof/ (index)

For more information on setting up and using profiling in your application, refer to our official documentation.

v1.35.2

18 Mar 14:48
54e02d8
Compare
Choose a tag to compare

Release - v1.35.2

🛠 Improvements

1. Kafka TLS Enhancements

  • Added support for configuring Kafka with TLS parameters, enabling seamless integration with Confluent Kafka SaaS and similar ecosystems.
    Introduced the following configuration options:

    KAFKA_TLS_CERT_FILE            : Path to the TLS certificate file.  
    KAFKA_TLS_KEY_FILE             : Path to the TLS key file.  
    KAFKA_TLS_CA_CERT_FILE         : Path to the TLS CA certificate file.  
    KAFKA_TLS_INSECURE_SKIP_VERIFY : Boolean option to skip TLS certificate verification.  
    

    Note: All provided paths must be absolute. Check out our official documentation to learn more.

2. Static File Server Enhancements

  • If a requested file is missing, the server attempts to serve 404.html with a 404 status code. If 404.html is unavailable, it returns a 404 status code.

  • If the file being accessed lacks read permissions, the error is logged and an appropriate 500 Internal Server Error status code and response body is returned.

🛠 Fixes

1. Middleware Execution Order

  • Restored the original middleware execution order prior to Release v1.35.0. Standard middlewares (logs, traces, metrics, CORS) are now executed before user-defined middlewares, ensuring consistent observability even when responses are handled early for e.g. in custom middlewares.
  • However, WebSocket connection upgrades necessarily take place after all middleware processing, maintaining compatibility with corresponding authentication flows introduced previously.

2. Kafka Security Protocol Configuration Fix

  • Previously, SASL authentication failed in ecosystems like Confluent due to missing security.protocol support, causing errors like:
     SASL handshake failed: EOF
    
  • Introduced KAFKA_SECURITY_PROTOCOL to explicitly define the security protocol for Kafka communication. Supported options include : PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL, ensuring seamless authentication. Check out official documentation to know more.

3. Redundant WriteHeader Calls

  • Fixed redundant WriteHeader calls when custom middleware in the static file server set a status code, preventing log spam like:
     http: superfluous response.WriteHeader call  from gofr.dev/pkg/gofr/http/middleware.(*StatusResponseWriter).WriteHeader (logger.go:23)
    
  • Headers are now written once—by either user-defined middleware or the framework handlers.

v1.35.1

11 Mar 13:34
18d39b0
Compare
Choose a tag to compare

Release v1.35.1

🛠 Improvements

1. Kafka Connection & Security Enhancements

  • Added support for configuring Kafka with extra connection and security parameters to seamlessly integrate with Confluent Kafka SaaS and similar platforms.

  • Introduced three new configuration options for SASL authentication:

    🔧 KAFKA_SASL_MECHANISM

    • SASL mechanism for authentication (e.g. PLAIN, SCRAM-SHA-256, SCRAM-SHA-512)
    • Default: None

    🔧 KAFKA_SASL_USERNAME

    • Username for SASL authentication
    • Default: None

    🔧 KAFKA_SASL_PASSWORD

    • Password for SASL authentication
    • Default: None

2. Multiple Static Folders Support

  • Multiple static folders can now be registered and served at different custom endpoints.

  • Example usage:

    package main 
    
    import  "gofr.dev/pkg/gofr"  

	func  main() {
        app := gofr.New()
        app.AddStaticFiles("public", "./public")
        app.AddStaticFiles("static", "./static")
        app.Run()
    }
  • In this example:

    • Files in the public folder are served at host/public/*
    • Files in the static folder are served at host/static/*

3. ArangoDB Resource Creation Enhanced

  • CreateDB, CreateGraph, and CreateCollection methods in Arango, now check for existing resources before creating them. Check out our official documentation to know more.

🛠 Fixes

1. Fixed Static File Server Endpoint Handling

  • Previously, files in the static directory were served by default at /static/. If the same directory was registered at another path, the files were being served at both endpoints, resulting in duplicate serving.
  • This has now been fixed. If a user registers a custom endpoint using app.AddStaticFiles({custom-endpoint}, ./static), GoFr will automatically serve the files only at the specified custom endpoint.
  • Additionally, if any directories are re-registered within the GoFr application, the files will now be served at the latest registered endpoint, ensuring there’s no duplication.

v1.35.0

04 Mar 14:00
763bedb
Compare
Choose a tag to compare

Release v1.35.0

🚀 Features

1. Template Rendering Support

  • GoFr now supports rendering HTML templates directly from handlers using the new response.Template response type.

  • By default, it looks for template files in the templates directory, automatically parsing the specified file and injecting the provided data, allowing developers to serve dynamic HTML content without requiring a separate template rendering mechanism.

  • Usage Example:

    Here's how you can use template rendering in a GoFr handler:

     package main
    
     import (
     	"fmt"
     	"net/http"
    
     	"gofr.dev/pkg/gofr"
     	"gofr.dev/pkg/gofr/response"
     )
    
     type Todo struct {
     	Title       string
     	Description string
     	Done        bool
     }
    
     func main() {
     	app := gofr.New()
    
     	app.GET("/todo", func(ctx *gofr.Context) (interface{}, error) {
     		data := Todo{
     			Title:       "Learn GoFr",
     			Description: "Understand how template rendering works in GoFr",
     			Done:        false,
     		}
     		return response.Template{Name: "todo.html", Data: data}, nil
     	})
    
     	app.Run()
    
     }

    Example Template (templates/todo.html):

     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width, initial-scale=1.0">
         <title>Todo</title>
     </head>
     <body>
         <h1>{{ .Title }}</h1>
         <p>{{ .Description }}</p>
         <p>Status: {{ if .Done }} ✅ Completed {{ else }} ❌ Pending {{ end }}</p>
     </body>
     </html>
    

    When a request is made to /todo, GoFr will render the todo.html template by injecting the provided Todo struct values.

2. Graceful Shutdown Configuration

  • A new environment variable, SHUTDOWN_GRACE_PERIOD, has been introduced to allow customization of the server's shutdown timeout.

  • Default: 30s

  • Purpose: Ensures in-flight requests are served before shutdown.

🛠 Fixes & Improvements

1. Authentication in Websockets

  • Ensured proper authentication for GoFr WebSocket connections by requiring user-defined authentication or middleware to run before upgrading, as WebSockets do not inherently support authentication.

2. Fixed Infinite Write Retry on Closed WebSocket

  • Previously, if a WebSocket connection was only writing and then closed, it would result in infinite retries without properly closing. This issue has now been resolved.

v1.34.1

25 Feb 17:41
2edea0f
Compare
Choose a tag to compare

Release - v1.34.1

🛠 Fixes & Improvements

1. GoFr Now Runs on Go 1.24

GoFr is now powered by the latest Golang version 1.24, ensuring compatibility with the newest features and improvements.

2. Improved Retry Mechanism for MQTT Default Client

The MQTT Default Client now includes automatic retries and seamless reconnection, enhancing reliability and stability.

3. Fixed Command Routing in CLI Applications

CLI applications built with GoFr now correctly resolve the intended commands typed in the terminal, preventing unintended command execution.

v1.34.0

18 Feb 14:30
50dd67e
Compare
Choose a tag to compare

Release - v1.34.0

🚀 Features

1. NATS-KV Store Support

GoFr now supports NATS-KV Store as a datastore. The supported methods include:

type KVStore interface {
    Get(ctx context.Context, key string) (string, error)
    Set(ctx context.Context, key, value string) error
    Delete(ctx context.Context, key string) error
    HealthCheck(ctx context.Context) (any, error)
}

To integrate NATSKV Store as a datastore, add the following configuration:

app.AddKVStore(nats.New(nats.Configs{
        Server: "nats://localhost:4222",
        Bucket: "persons",
    }))

Refer to the documentation for more details.

2. ArangoDB Migrations

Added migration support for ArangoDB, allowing users to perform schema changes seamlessly. The following methods are now available in migration:

// CreateDB creates a new database in ArangoDB.
CreateDB(ctx context.Context, database string) error

// DropDB deletes an existing database in ArangoDB.
DropDB(ctx context.Context, database string) error

// CreateCollection creates a new collection in a database.
CreateCollection(ctx context.Context, database, collection string, isEdge bool) error

// DropCollection deletes an existing collection from a database.
DropCollection(ctx context.Context, database, collection string) error

// CreateGraph creates a new graph in a database.
//
// Parameters:
//   - ctx: Request context for tracing and cancellation.
//   - database: Name of the database where the graph will be created.
//   - graph: Name of the graph to be created.
//   - edgeDefinitions: Pointer to EdgeDefinition struct containing edge definitions.
//
// Returns an error if edgeDefinitions is not of type *EdgeDefinition or is nil.
CreateGraph(ctx context.Context, database, graph string, edgeDefinitions any) error

// DropGraph deletes an existing graph from a database.
DropGraph(ctx context.Context, database, graph string) error

🛠 Fixes & Improvements

1. Automatic PubSub Reconnection

Fixed automatic retries and reconnection in PubSub. It now reconnects immediately upon connection availability.

2. Added go.work

Simplifies dependency handling and development with better multi-module management.

3. Telemetry for Active GoFr Servers

GoFr now includes telemetry to track the number of running GoFr servers, helping us understand adoption and usage trends.

To disable telemetry, set:

GOFR_TELEMETRY=false

v1.33.0

06 Feb 06:37
d6cd85a
Compare
Choose a tag to compare

Release v1.33.0

🚀 Features

1. ArangoDB Support as a Datasource

Users can now integrate ArangoDB as a datasource within their GoFr applications. Supported Methods include :

type ArangoDB interface {
    // CreateDocument creates a new document in the specified collection.
	CreateDocument(ctx context.Context, dbName, collectionName string, document any) (string, error)
	// GetDocument retrieves a document by its ID from the specified collection.
	GetDocument(ctx context.Context, dbName, collectionName, documentID string, result any) error
	// UpdateDocument updates an existing document in the specified collection.
	UpdateDocument(ctx context.Context, dbName, collectionName, documentID string, document any) error
	// DeleteDocument deletes a document by its ID from the specified collection.
	DeleteDocument(ctx context.Context, dbName, collectionName, documentID string) error
	// GetEdges retrieves all the edge documents connected to a specific vertex in an ArangoDB graph.
	GetEdges(ctx context.Context, dbName, graphName, edgeCollection, vertexID string, resp any) error
	// Query executes an AQL query and binds the results
	Query(ctx context.Context, dbName string, query string, bindVars map[string]any, result any) error
    HealthCheck(context.Context) (any, error)
}

Refer to our official documentation to know more.

2. Default HealthCheck Support for gRPC Servers and Clients

This release introduces built-in HealthCheck support for both gRPC servers and clients.

  • Prerequisites:
    To use the new health check features, ensure that gofr-cli v0.5.0 is installed. Use it to generate your gRPC client and server templates.

  • gRPC Servers
    After running the existing command:

      gofr wrap grpc server -proto=path/to/your/proto/file
    

    A new file named health_gofr.go will be generated. This file contains the health functionality for your gRPC server. The health methods are embedded within the GoFr gRPC server struct, which looks like this:

     type {serviceName}GoFrServer struct {
         health *healthServer
     }

    Supported HealthCheck Methods:

     // Check checks if the service is healthy.
     func (h *healthServer) Check(ctx *gofr.Context, req *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error)
     // Watch watches for any changes in the service’s health status.
     func (h *healthServer) Watch(ctx *gofr.Context, in *grpc_health_v1.HealthCheckRequest, stream grpc_health_v1.Health_WatchServer) error
     // SetServingStatus allows you to set the health status of the service (healthy, unhealthy, etc.).
     func (h *healthServer) SetServingStatus(ctx *gofr.Context, service string, status grpc_health_v1.HealthCheckResponse_ServingStatus)
     // Shutdown gracefully shuts down the service.
     func (h *healthServer) Shutdown(ctx *gofr.Context)
     // Resume resumes the service after it has been shut down.
     func (h *healthServer) Resume(ctx *gofr.Context)

    To integrate these health features, register your gRPC server in main.go as follows:

     func main() {
         app := gofr.New()
    
         packageName.Register{serviceName}ServerWithGofr(app, &{packageName}.New{serviceName}GoFrServer())
    
         app.Run()
     }
  • For gRPC Clients
    HealthCheck calls are now supported on all gRPC clients generated through the gofr-cli command i.e :

     gofr wrap grpc client -proto=path/to/your/proto/file
    

    Supported HealthCheck methods include :

     // Check checks the service health.
     func (c *{serviceName}GoFrClient) Check(ctx *gofr.Context, in *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error)
     // Watch allows the client to watch for health status changes.
     func (c *{serviceName}GoFrClient) Watch(ctx *gofr.Context, in *grpc_health_v1.HealthCheckRequest) (grpc.ServerStreamingClient[grpc_health_v1.HealthCheckResponse], error)

For a deeper understanding, check out our official documentation and refer to our example repo.

🛠️ Fix

Resolved an issue with the AddRESTHandlers support where PUT requests were not updating records in the database when we have autoincrement tag added in our entity struct. The issue has now been fixed.

v1.32.0

27 Jan 08:59
aae7488
Compare
Choose a tag to compare

Release v1.32.0

🚀 Features :

1. Support for SurrealDB as a Data Source
SurrealDB is now supported as a data source in GoFr. The following methods are supported:

type SurrealDB interface  {
	Query(ctx context.Context, query string, vars map[string]any) ([]any, error)
	Create(ctx context.Context, table string, data any) (map[string]any, error)
	Update(ctx context.Context, table string, id string, data any) (any, error)
	Delete(ctx context.Context, table string, id string) (any, error)
	Select(ctx context.Context, table string) ([]map[string]any, error)
	HealthCheck(context.Context) (any, error)
}

To integrate SurrealDB into your application, use the AddSurrealDB method in your main.go :

client := surrealdb.New(&surrealdb.Config{
    Host:       "localhost",
    Port:       8000,
    Username:   "root",
    Password:   "root",
    Namespace:  "test_namespace",
    Database:   "test_database",
    TLSEnabled: false,
})

app.AddSurrealDB(client)

For more details, refer to our official documentation.

2. Built-in Metrics for gRPC Services

GoFr now includes in-built metrics for all gRPC server executions and interservice gRPC calls. We automatically capture metrics to measure the response time of gRPC server/clients.

  • Prerequisites : gofr-cli version v0.4.0 must be installed.
  • Use the following commands :
    • gofr wrap grpc server --proto=<path/to/proto/file> to generate GoFr's gRPC handlers.
    • gofr wrap grpc client -proto=<path/to/proto/file> to generate GoFr's gRPC client.
  • Refer the official documentation & examples to set up gRPC server/clients with in built logging, tracing and metrics support.

🛠️ Fixes :

1. Enhanced gRPC Logging

  • Improved logs for interservice gRPC calls, now including:
    • Trace ID: For better tracking of distributed requests.
    • Status Code: Logs the response status of gRPC calls for easy debugging and issue resolution.

v1.31.0

20 Jan 11:18
fc8616b
Compare
Choose a tag to compare

Release v1.31.0

🚀 Features :

  1. Support for ScyllaDB as a Data Source
    ScyllaDB is now supported as a data source in GoFr. The following methods are supported:

    Query(dest any, stmt string, values ...any) error  
    QueryWithCtx(ctx context.Context, dest any, stmt string, values ...any) error  
    Exec(stmt string, values ...any) error  
    ExecWithCtx(ctx context.Context, stmt string, values ...any) error  
    ExecCAS(dest any, stmt string, values ...any) (bool, error)  
    NewBatch(name string, batchType int) error  
    NewBatchWithCtx(ctx context.Context, name string, batchType int) error  
    BatchQuery(name, stmt string, values ...any) error  
    BatchQueryWithCtx(ctx context.Context, name, stmt string, values ...any) error  
    ExecuteBatchWithCtx(ctx context.Context, name string) error  

    To integrate ScyllaDB into your application, use the AddScyllaDB method:

    client := scylladb.New(scylladb.Config{
        Host:     app.Config.Get("SCYLLADB_HOST"),
        Keyspace: app.Config.Get("SCYLLADB_KEYSPACE"),
        Port:     app.Config.GetInt("SCYLLADB_PORT"),
        Username: app.Config.Get("SCYLLADB_USERNAME"),
        Password: app.Config.Get("SCYLLADB_PASSWORD"),
    })
    app.AddScyllaDB(client)

    For detailed instructions, refer to the ScyllaDB documentation.

  2. Built-in Tracing for Interservice gRPC Calls
    All interservice gRPC calls in GoFr now include in-built tracing support.

    • Prerequisite: Ensure gofr-cli v0.3.0 is installed. To install gofr-cli, run:

      go install gofr.dev/cli/gofr@latest
    • To generate the gRPC client, run:

      gofr wrap grpc client -proto=path/to/your/proto/file

    For detailed instructions on setting up the gRPC Client in GoFr, refer to the documentation. You can also explore an example gRPC client implementation in the examples folder.

Full Changelog: v1.30.0...v1.31.0