Skip to content

Commit 378b51d

Browse files
authored
fix: return 400 instead of 500 for idempotency key reuse with different body (#921)
1 parent cf6e6bb commit 378b51d

27 files changed

+622
-57
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ dumps
99
.env
1010
!.envrc
1111
Pulumi.*.yaml
12+
coverage.txt

docs/api/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@ Authorization ( Scopes: ledger:write )
966966
DELETE http://localhost:8080/v2/{ledger}/transactions/{id}/metadata/{key} HTTP/1.1
967967
Host: localhost:8080
968968
Accept: application/json
969+
Idempotency-Key: string
969970
970971
```
971972

@@ -980,6 +981,7 @@ Delete metadata by key
980981
|ledger|path|string|true|Name of the ledger.|
981982
|id|path|integer(bigint)|true|Transaction ID.|
982983
|key|path|string|true|The key to remove.|
984+
|Idempotency-Key|header|string|false|Use an idempotency key|
983985

984986
> Example responses
985987

internal/api/common/errors.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package common
22

33
import (
44
"errors"
5+
"net/http"
6+
57
"github.com/formancehq/go-libs/v3/api"
68
"github.com/formancehq/go-libs/v3/logging"
79
"github.com/formancehq/go-libs/v3/otlp"
810
"github.com/formancehq/go-libs/v3/platform/postgres"
9-
"net/http"
11+
ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger"
1012
)
1113

1214
const (
@@ -37,6 +39,19 @@ func HandleCommonErrors(w http.ResponseWriter, r *http.Request, err error) {
3739
}
3840
}
3941

42+
func HandleCommonWriteErrors(w http.ResponseWriter, r *http.Request, err error) {
43+
switch {
44+
case errors.Is(err, ledgercontroller.ErrIdempotencyKeyConflict{}):
45+
api.WriteErrorResponse(w, http.StatusConflict, ErrConflict, err)
46+
case errors.Is(err, ledgercontroller.ErrInvalidIdempotencyInput{}):
47+
api.BadRequest(w, ErrValidation, err)
48+
case errors.Is(err, ledgercontroller.ErrNotFound):
49+
api.NotFound(w, err)
50+
default:
51+
HandleCommonErrors(w, r, err)
52+
}
53+
}
54+
4055
func InternalServerError(w http.ResponseWriter, r *http.Request, err error) {
4156
otlp.RecordError(r.Context(), err)
4257
logging.FromContext(r.Context()).Error(err)

internal/api/v1/controllers_accounts_add_metadata.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package v1
22

33
import (
44
"encoding/json"
5-
"github.com/formancehq/ledger/internal/controller/ledger"
6-
"github.com/formancehq/ledger/pkg/accounts"
75
"net/http"
86
"net/url"
97

8+
"github.com/formancehq/ledger/internal/controller/ledger"
9+
"github.com/formancehq/ledger/pkg/accounts"
10+
1011
"errors"
12+
1113
"github.com/formancehq/go-libs/v3/api"
1214
"github.com/formancehq/go-libs/v3/metadata"
1315
"github.com/formancehq/ledger/internal/api/common"
@@ -38,7 +40,7 @@ func addAccountMetadata(w http.ResponseWriter, r *http.Request) {
3840
Metadata: m,
3941
}))
4042
if err != nil {
41-
common.HandleCommonErrors(w, r, err)
43+
common.HandleCommonWriteErrors(w, r, err)
4244
return
4345
}
4446

internal/api/v1/controllers_accounts_delete_metadata.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package v1
22

33
import (
4-
"github.com/formancehq/ledger/internal/controller/ledger"
54
"net/http"
65
"net/url"
76

7+
"github.com/formancehq/ledger/internal/controller/ledger"
8+
89
"github.com/formancehq/go-libs/v3/api"
910
"github.com/formancehq/ledger/internal/api/common"
1011
"github.com/go-chi/chi/v5"
@@ -25,7 +26,7 @@ func deleteAccountMetadata(w http.ResponseWriter, r *http.Request) {
2526
Key: chi.URLParam(r, "key"),
2627
}),
2728
); err != nil {
28-
common.HandleCommonErrors(w, r, err)
29+
common.HandleCommonWriteErrors(w, r, err)
2930
return
3031
}
3132

internal/api/v1/controllers_transactions_add_metadata.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger"
99

1010
"errors"
11+
1112
"github.com/formancehq/go-libs/v3/api"
1213
"github.com/formancehq/go-libs/v3/metadata"
1314
"github.com/formancehq/ledger/internal/api/common"
@@ -37,7 +38,7 @@ func addTransactionMetadata(w http.ResponseWriter, r *http.Request) {
3738
case errors.Is(err, ledgercontroller.ErrNotFound):
3839
api.NotFound(w, err)
3940
default:
40-
common.HandleCommonErrors(w, r, err)
41+
common.HandleCommonWriteErrors(w, r, err)
4142
}
4243
return
4344
}

internal/api/v1/controllers_transactions_create.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger"
1010

1111
"errors"
12+
1213
"github.com/formancehq/go-libs/v3/api"
1314
"github.com/formancehq/go-libs/v3/metadata"
1415
"github.com/formancehq/go-libs/v3/time"
@@ -100,7 +101,7 @@ func createTransaction(w http.ResponseWriter, r *http.Request) {
100101
case errors.Is(err, ledgercontroller.ErrTransactionReferenceConflict{}):
101102
api.WriteErrorResponse(w, http.StatusConflict, common.ErrConflict, err)
102103
default:
103-
common.HandleCommonErrors(w, r, err)
104+
common.HandleCommonWriteErrors(w, r, err)
104105
}
105106
return
106107
}
@@ -135,7 +136,7 @@ func createTransaction(w http.ResponseWriter, r *http.Request) {
135136
case errors.Is(err, ledgercontroller.ErrTransactionReferenceConflict{}):
136137
api.WriteErrorResponse(w, http.StatusConflict, common.ErrConflict, err)
137138
default:
138-
common.HandleCommonErrors(w, r, err)
139+
common.HandleCommonWriteErrors(w, r, err)
139140
}
140141
return
141142
}

internal/api/v1/controllers_transactions_delete_metadata.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger"
88

99
"errors"
10+
1011
"github.com/formancehq/go-libs/v3/api"
1112
"github.com/formancehq/ledger/internal/api/common"
1213
"github.com/go-chi/chi/v5"
@@ -27,12 +28,7 @@ func deleteTransactionMetadata(w http.ResponseWriter, r *http.Request) {
2728
TransactionID: transactionID,
2829
Key: metadataKey,
2930
})); err != nil {
30-
switch {
31-
case errors.Is(err, ledgercontroller.ErrNotFound):
32-
api.NotFound(w, err)
33-
default:
34-
common.HandleCommonErrors(w, r, err)
35-
}
31+
common.HandleCommonWriteErrors(w, r, err)
3632
return
3733
}
3834

internal/api/v2/controllers_accounts_add_metadata.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package v2
22

33
import (
44
"encoding/json"
5-
"github.com/formancehq/ledger/internal/controller/ledger"
65
"net/http"
76
"net/url"
87

8+
"github.com/formancehq/ledger/internal/controller/ledger"
9+
910
"errors"
11+
1012
"github.com/formancehq/go-libs/v3/api"
1113
"github.com/formancehq/go-libs/v3/metadata"
1214
"github.com/formancehq/ledger/internal/api/common"
@@ -33,7 +35,7 @@ func addAccountMetadata(w http.ResponseWriter, r *http.Request) {
3335
Metadata: m,
3436
}))
3537
if err != nil {
36-
common.HandleCommonErrors(w, r, err)
38+
common.HandleCommonWriteErrors(w, r, err)
3739
return
3840
}
3941

internal/api/v2/controllers_accounts_delete_metadata.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package v2
22

33
import (
4-
"github.com/formancehq/ledger/internal/controller/ledger"
54
"net/http"
65
"net/url"
76

7+
"github.com/formancehq/ledger/internal/controller/ledger"
8+
89
"github.com/go-chi/chi/v5"
910

1011
"github.com/formancehq/go-libs/v3/api"
@@ -26,7 +27,7 @@ func deleteAccountMetadata(w http.ResponseWriter, r *http.Request) {
2627
Key: chi.URLParam(r, "key"),
2728
}),
2829
); err != nil {
29-
common.HandleCommonErrors(w, r, err)
30+
common.HandleCommonWriteErrors(w, r, err)
3031
return
3132
}
3233

0 commit comments

Comments
 (0)