httpapi/

directory
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2026 License: MIT

README

API di esempio

Backend Echo con una struttura per funzionalità e separazione fra dominio, servizi applicativi e adapter. È una scelta di questo esempio: Palma non richiede cartelle, nomi o architetture specifiche.

httpapi/
├── cmd/api/main.go                 # entry point e lifecycle
└── internal/
    ├── bootstrap/                  # composizione dei moduli e wiring generato
    │   ├── compose.go
    │   ├── generate.go
    │   └── pfw_gen.go
    ├── config/                     # configurazione fornita dall'entry point
    ├── platform/http/              # router principale e server HTTP
    └── user/                       # funzionalità utenti
        ├── domain/                 # tipi, invarianti ed errori
        ├── application/            # operazioni e port Repository
        └── adapter/
            ├── http/               # controller Echo, DTO e mapping degli errori
            ├── memory/             # repository concorrente in memoria
            └── postgres/           # repository persistente e pool con cleanup

Il dominio non importa Palma, Echo o lo storage. L'application dipende dal dominio e dichiara l'interfaccia dello storage. Gli adapter implementano i confini applicativi. bootstrap collega tutto con registrazioni esplicite e wiring automatico; i moduli dichiarativi restano nello stesso package. Il modulo Users usa pfw.Discover("../user/..."): i costruttori di storage, servizio e controller sono marcati //pfw:coconut. Router e server restano registrati manualmente. Users abilita pfw.AutoBind() per il mapper HTTP; il repository viene selezionato con un binding esplicito, diverso per local rispetto a staging/uat/production. Il codice applicativo dipende dall'interfaccia.

Una nuova funzionalità può affiancare internal/user, con i propri servizi e adapter. platform/http raccoglie le route; bootstrap raccoglie i provider. Non serve creare nuovi livelli o interfacce per ogni struct.

Esecuzione

Dalla root del repository:

go run ./cmd/pfw generate -env local ./examples/httpapi/internal/bootstrap
go run ./cmd/pfw generate -env local -check ./examples/httpapi/internal/bootstrap
go run ./cmd/pfw inspect ./examples/httpapi/internal/bootstrap
go test -race ./examples/httpapi/...
go run ./cmd/pfw run -env local ./examples/httpapi/cmd/api

In alternativa alla prima riga: go generate ./examples/httpapi/internal/bootstrap. In locale l'API ascolta su :8080, con un utente iniziale Ada (ID 1). Indirizzo e nome sono caricati da environment o .env in config.Config, con default e validazione prima di costruire il server. Le sottostruct sono HTTP e Seed. Il prefisso è HTTPAPI_: HTTP_ADDRESS, SEED_USER_NAME, HTTP_READ_HEADER_TIMEOUT e HTTP_SHUTDOWN_TIMEOUT. I timeout hanno default 5s e devono essere positivi.

cp examples/httpapi/.env.example .env
HTTPAPI_HTTP_ADDRESS=:9090 HTTPAPI_HTTP_SHUTDOWN_TIMEOUT=10s go run ./cmd/pfw run -env local ./examples/httpapi/cmd/api

La guida configurazione descrive parsing, default e validazione. Il file .env viene letto dalla directory corrente se presente, con precedenza all'environment del processo. La configurazione viene caricata dall'entry point prima del wiring.

Endpoint

Richiesta Esito
GET /users 200, elenco utenti in ordine di creazione.
POST /users con JSON {"name":"Grace"} 201, utente creato e header Location.
GET /users/:id 200, utente trovato; 404 se non esiste.

Il nome viene ripulito dagli spazi iniziali/finali e deve contenere da 1 a 100 caratteri Unicode. La validazione appartiene al dominio e vale anche senza HTTP. Il repository assegna ID incrementali e protegge letture/scritture concorrenti. I dati vengono persi alla chiusura del processo; nomi duplicati sono consentiti.

curl http://localhost:8080/users
curl -i -X POST http://localhost:8080/users -H 'Content-Type: application/json' -d '{"name":"Grace"}'
curl http://localhost:8080/users/2

Gli errori applicativi degli endpoint hanno forma:

{
  "code": "validation_failed",
  "message": "invalid input",
  "fields": {"name": "name is required"}
}

JSON malformato o tipi errati producono 400; Content-Type diverso da JSON produce 415; input semanticamente invalido produce 422; utente mancante 404. Campi JSON sconosciuti o più valori JSON nello stesso body producono 400; body oltre 1 MiB produce 413. Il decoder e le risposte sono forniti dal package HTTP di Palma. NewErrorMapper viene scoperto e iniettato nel controller: la traduzione degli errori di dominio rimane configurata nell'adapter HTTP.

Ambienti e Postgres

Una sola discovery include i provider della funzionalità. Il binding comune di application.Repository seleziona Postgres; ForEnv("local", Bind[...]) seleziona memory. generate -env local genera soltanto il grafo locale; per staging/uat/production occorre rigenerare il wiring con il relativo -env. La connessione DB non viene aperta in locale.

In staging/uat/production impostare HTTPAPI_DB_DSN (DSN pgx/PostgreSQL) e, se necessario, HTTPAPI_DB_CONNECT_TIMEOUT (default 5s). La configurazione DB è obbligatoria soltanto fuori da local. Creare la tabella applicando schema.sql al database scelto prima dell'avvio: il framework non applica migrazioni implicite. L'adapter usa pgx tramite database/sql. Le query usano parametri; il cleanup del pool viene eseguito dopo lo shutdown HTTP. Il provider internal/platform/database.OpenMainDatabase usa il componente database e fornisce MainDB al repository tramite DI. Il repository seleziona il primary; la guida database mostra anche database indipendenti e scelta delle repliche a runtime. Postgres conserva i dati e non aggiunge automaticamente l'utente di seed locale.

go run ./cmd/pfw run -env staging ./examples/httpapi/cmd/api
go run ./cmd/pfw inspect -env staging ./examples/httpapi/internal/bootstrap

run legge i file dalla root del modulo; -env-dir può selezionare un'altra directory. In particolare .env.staging e .env.production possono avere DSN diversi con la stessa implementazione. I test unitari del repository SQL usano un driver locale: non richiedono né modificano un database Postgres esterno. Gli errori interni producono 500 senza esporre la causa al client. Gli errori di routing fuori da questi endpoint restano gestiti da Echo.

I test passano attraverso il composition root generato e verificano il flusso creazione/ricerca/elenco, validazione, errori e concorrenza del repository. SIGINT/SIGTERM attivano il lifecycle e lo shutdown con timeout di 5 secondi.

I controller registrano rotte locali su gruppi Echo; internal/platform/http/server.go sceglie i prefissi. I middleware usano le API native di Echo. Gli errori applicativi sono restituiti dagli handler e gestiti dal router con mapper e logger iniettati. Vedi la guida al routing.

Il repository Postgres usa sqltx.Executor(ctx, db): partecipa automaticamente a una transazione applicativa quando riceve il context di transaction.Runner.Within, e usa il pool negli altri casi. Il servizio corrente non apre transazioni implicite. La guida alle transazioni mostra il provider DI e come coordinare più operazioni.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL