Un servizio in Goa rappresenta una collezione di metodi correlati che lavorano insieme per fornire funzionalità specifiche. I servizi aiutano a organizzare la tua API in raggruppamenti logici.
Il DSL dei Servizi supporta diverse opzioni per configurare e documentare il tuo servizio:
var _ = Service("users", func() {
// Documentazione base
Description("Servizio di gestione utenti")
// Documentazione dettagliata
Docs(func() {
Description("Documentazione dettagliata per il servizio utenti")
URL("https://example.com/docs/users")
})
// Definizioni di errore a livello di servizio
Error("unauthorized", String, "Autenticazione fallita")
Error("not_found", NotFound, "Risorsa non trovata")
// Metadati a livello di servizio
Meta("swagger:tag", "Utenti")
Meta("rpc:package", "usersvc")
// Requisiti di sicurezza
Security(OAuth2, func() {
Scope("read:users")
Scope("write:users")
})
// Variabili a livello di servizio
Variable("version", String, func() {
Description("Versione API")
Default("v1")
Enum("v1", "v2")
})
// Metodi
Method("create", func() {
// ... definizione metodo
})
Method("list", func() {
// ... definizione metodo
})
// File serviti dal servizio
Files("/docs", "./swagger", func() {
Description("Documentazione API")
})
})
Definisci errori che possono essere restituiti da tutti i metodi nel servizio:
var _ = Service("orders", func() {
// Tutti i metodi nel servizio restituiranno questo errore
Error("unauthorized")
})
Nota: Il DSL
Error
è usato per definire errori che possono essere restituiti da tutti i metodi nel servizio. Non è appropriato per definire errori che sono specifici per un sottoinsieme di metodi. Invece, usa il DSLError
all’interno della definizione del metodo o dell’API per questo scopo.
Usa il DSL Docs per fornire documentazione dettagliata:
var _ = Service("payments", func() {
Description("Servizio di elaborazione pagamenti")
Docs(func() {
Description(`Il servizio pagamenti gestisce tutte le operazioni relative ai pagamenti.
Fornisce metodi per:
- Elaborare pagamenti
- Rimborsare transazioni
- Interrogare lo stato dei pagamenti
- Gestire metodi di pagamento`)
URL("https://example.com/docs/payments")
// Metadati di documentazione aggiuntivi
Meta("doc:section", "Servizi Finanziari")
Meta("doc:category", "API Core")
})
})
API complesse possono essere organizzate in servizi multipli:
var _ = Service("users", func() {
Description("Servizio di gestione utenti")
// ... metodi relativi agli utenti
})
var _ = Service("billing", func() {
Description("Servizio di fatturazione e pagamento")
// ... metodi relativi alla fatturazione
})
I metodi definiscono le operazioni che possono essere eseguite all’interno di un servizio. Ogni metodo specifica il suo input (payload), output (risultato) e condizioni di errore.
Method("add", func() {
Description("Somma due numeri insieme")
// Parametri di input
Payload(func() {
Field(1, "a", Int32, "Primo operando")
Field(2, "b", Int32, "Secondo operando")
Required("a", "b")
})
// Risposta di successo
Result(Int32)
// Risposte di errore
Error("overflow")
})
I metodi possono accettare diversi tipi di payload:
// Payload semplice usando tipo esistente
Method("getUser", func() {
Payload(String, "ID Utente")
Result(User)
})
// Payload strutturato definito inline
Method("createUser", func() {
Payload(func() {
Field(1, "name", String, "Nome completo dell'utente")
Field(2, "email", String, "Indirizzo email", func() {
Format(FormatEmail)
})
Field(3, "role", String, "Ruolo utente", func() {
Enum("admin", "user", "guest")
})
Required("name", "email", "role")
})
Result(User)
})
// Riferimento a tipo di payload predefinito
Method("updateUser", func() {
Payload(UpdateUserPayload)
Result(User)
})
I metodi possono restituire diversi tipi di risultati:
// Risultato primitivo semplice
Method("count", func() {
Result(Int64)
})
// Risultato strutturato definito inline
Method("search", func() {
Result(func() {
Field(1, "items", ArrayOf(User), "Utenti corrispondenti")
Field(2, "total", Int64, "Conteggio totale")
Required("items", "total")
})
})
Definisci condizioni di errore attese per i metodi:
Method("divide", func() {
Payload(func() {
Field(1, "a", Float64, "Dividendo")
Field(2, "b", Float64, "Divisore")
Required("a", "b")
})
Result(Float64)
// Errori specifici del metodo
Error("division_by_zero", func() {
Description("Tentativo di divisione per zero")
})
})
Goa supporta lo streaming sia per i payload che per i risultati:
Method("streamNumbers", func() {
Description("Stream di una sequenza di numeri")
// Stream di interi come input
StreamingPayload(Int32)
// Stream di interi come output
StreamingResult(Int32)
})
Method("processEvents", func() {
Description("Elabora uno stream di eventi")
// Stream di dati strutturati
StreamingPayload(func() {
Field(1, "event_type", String)
Field(2, "data", Any)
Required("event_type", "data")
})
// Restituisce risultato riepilogativo
Result(func() {
Field(1, "processed", Int64, "Numero di eventi elaborati")
Field(2, "errors", Int64, "Numero di errori")
Required("processed", "errors")
})
})