Caution
This repository either is the template for new microservices or this repository has been generated from the template repository.
This repository contains a template for new microservices inside the WISdoM
architecture.
It already handles the connection to the database using the internal/db
package and the included init
function in that package.
To start writing a new microservice you only need to create the new routes in
the routes
directory and add them to the gin-gonic/gin
router used in
the project.
The microservice automatically disables the authorization in local development
scenarios to reduce the hassle with needing a living access token for each
request.
However, the authorization is enabled when building the Docker Image as it
uses the docker
build tag which triggers the inclusion of
internal/config/docker.go
and the exclusion of internal/config/debug.go
into
the binary.
Tip
To test the authorization you need to manually add the build tag to your build
command -tags docker
and populate the OIDC_AUTHORITY
environment variable
which should contain the issuer of the access tokens used in your WISdoM
platform, otherwise the startup of the microservice will fail or you may be
unable to access the microservice
Important
You need to set the following environment variables for a successful connection to the database:
PGUSER
PGPASSWORD
PGHOST
PGDATABASE
and optionally the following variables
PGPORT
As the database is automatically connected, you don't need to handle this by
yourself.
To use the database in your code either request a single connection from the
connection pool (db.Pool.Acquire
) or pass the pool into a supported function
(recommended)
Furthermore, all queries stored in the resources
folder are embedded into
the built executable and available in the db.Queries
object, which is a
qustavo/dotsql
DotSql
object which allows recalling queries by their name.
Since the router already comes pre-configured with some error handling
middleware, sending errors generated by other functions back to an end-user is
easy.
Just call c.Abort()
and c.Error()
in your handler and return from the
function.
The end-user will automatically receive a RFC 9457-compliant error message
generated from your output.
The following example shows how to output an error and what the expected output
should look like on the end-users side:
package routes
import "github.com/gin-gonic/gin"
func BasicHandler(c *gin.Context) {
// ... your other code which generated an error
if err != nil {
c.Abort()
_ = c.Error(err)
return
}
}
HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json; charset=utf-8
X-Request-Id: 6215ec23-45f9-4182-b848-64a969e7d0c5
Content-Length: 319
[
{
"type": "https://www.rfc-editor.org/rfc/rfc9110#section-15.6.1",
"status": 500,
"title": "Internal Server Error",
"detail": "The service encountered an internal error during the handling of your request",
"instance": "tag:xxxxxxxx,2024-10-15:InternalServerError:1728985891",
"errors": [
"error"
],
"host": "xxxxxxxx"
}
]
If you want to send errors that are generated by your code and are predictable
(for example, an object isn't found) should create a types.ServiceError
for
the error message and send that one back using .Emit()
on the created
ServiceError
object
package routes
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/wisdom-oss/common-go/v2/types"
)
var ObjectNotFoundError types.ServiceError = types.ServiceError{
Type: "https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.5",
Status: http.StatusNotFound,
Title: "Object Not Found",
Detail: "The requested object does not exist. Please check the object id",
}
func BasicHandler(c *gin.Context) {
// ... your other code possibly populating the object
if object == nil {
c.Abort()
ObjectNotFoundError.Emit(c)
return
}
}
HTTP/1.1 404 Not Found
Content-Type: application/problem+json; charset=utf-8
X-Request-Id: 82f0e83e-f485-4aca-8706-d0d57ee1585d
Content-Length: 317
{
"type": "https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.5",
"status": 404,
"title": "Object Not Found",
"detail": "The requested object does not exist. Please check the object id",
"instance": "tag:xxxxxxxx,2024-10-15:ObjectNotFound:1728986473",
"host": "xxxxxxxx"
}