Releases: gofr-dev/gofr
v1.37.0
🚀 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() }
- Refer to the official documentation to know more.
🛠 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
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 asjwt.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 theAPP_ENV=DEBUG
environment variable was set, and it ran on the specifiedHTTP_PORT
. This prevented users from loading their different environments, for e.g. stage or production configurations if we setAPP_ENV
asDEBUG
for profiling. - GoFr now automatically enables
pprof
profiling onMETRICS_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
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 a404
status code. If404.html
is unavailable, it returns a404
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
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
- SASL mechanism for authentication (e.g.
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 athost/public/*
- Files in the
static
folder are served athost/static/*
- Files in the
3. ArangoDB Resource Creation Enhanced
CreateDB
,CreateGraph
, andCreateCollection
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
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 thetodo.html
template by injecting the providedTodo
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
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
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
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
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
Release v1.31.0
🚀 Features :
-
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.
-
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 installgofr-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