Return parsable error codes instead of just a string.
Also - Check if VSP is closed before /payfee
This commit is contained in:
parent
b50615bc6f
commit
9f48bae78e
12
docs/api.md
12
docs/api.md
@ -4,8 +4,16 @@
|
||||
|
||||
- Success responses use HTTP status 200 and a JSON encoded body.
|
||||
|
||||
- Error responses use either HTTP status 500 or 400, and a JSON encoded error
|
||||
in the body, e.g. `{"error":"Description"}`.
|
||||
- Error responses use HTTP status 500 to indicate a server error or 400 to
|
||||
indiciate a client error, and will include a JSON body describing the error.
|
||||
For example:
|
||||
|
||||
```json
|
||||
{"code": 9, "message":"invalid vote choices"}
|
||||
```
|
||||
|
||||
A full list of error codes can be looked up in
|
||||
[webapi/errors.go](../webapi/errors.go)
|
||||
|
||||
- Requests which reference specific tickets need to be properly signed as
|
||||
described in [two-way-accountability.md](./two-way-accountability.md).
|
||||
|
||||
84
webapi/errors.go
Normal file
84
webapi/errors.go
Normal file
@ -0,0 +1,84 @@
|
||||
package webapi
|
||||
|
||||
import "net/http"
|
||||
|
||||
type apiError int
|
||||
|
||||
const (
|
||||
errBadRequest apiError = iota
|
||||
errInternalError
|
||||
errVspClosed
|
||||
errFeeAlreadyReceived
|
||||
errInvalidFeeTx
|
||||
errFeeTooSmall
|
||||
errUnknownTicket
|
||||
errTicketCannotVote
|
||||
errFeeExpired
|
||||
errInvalidVoteChoices
|
||||
errBadSignature
|
||||
errInvalidPrivKey
|
||||
)
|
||||
|
||||
// httpStatus maps application error codes to HTTP status codes.
|
||||
func (e apiError) httpStatus() int {
|
||||
switch e {
|
||||
case errBadRequest:
|
||||
return http.StatusBadRequest
|
||||
case errInternalError:
|
||||
return http.StatusInternalServerError
|
||||
case errVspClosed:
|
||||
return http.StatusBadRequest
|
||||
case errFeeAlreadyReceived:
|
||||
return http.StatusBadRequest
|
||||
case errInvalidFeeTx:
|
||||
return http.StatusBadRequest
|
||||
case errFeeTooSmall:
|
||||
return http.StatusBadRequest
|
||||
case errUnknownTicket:
|
||||
return http.StatusBadRequest
|
||||
case errTicketCannotVote:
|
||||
return http.StatusBadRequest
|
||||
case errFeeExpired:
|
||||
return http.StatusBadRequest
|
||||
case errInvalidVoteChoices:
|
||||
return http.StatusBadRequest
|
||||
case errBadSignature:
|
||||
return http.StatusBadRequest
|
||||
case errInvalidPrivKey:
|
||||
return http.StatusBadRequest
|
||||
default:
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
}
|
||||
|
||||
// defaultMessage returns a descriptive error string for a given error code.
|
||||
func (e apiError) defaultMessage() string {
|
||||
switch e {
|
||||
case errBadRequest:
|
||||
return "bad request"
|
||||
case errInternalError:
|
||||
return "internal error"
|
||||
case errVspClosed:
|
||||
return "vsp is closed"
|
||||
case errFeeAlreadyReceived:
|
||||
return "fee tx already received"
|
||||
case errInvalidFeeTx:
|
||||
return "invalid fee transaction"
|
||||
case errFeeTooSmall:
|
||||
return "fee too small"
|
||||
case errUnknownTicket:
|
||||
return "unknown ticket"
|
||||
case errTicketCannotVote:
|
||||
return "ticket not eligible to vote"
|
||||
case errFeeExpired:
|
||||
return "fee has expired"
|
||||
case errInvalidVoteChoices:
|
||||
return "invalid vote choices"
|
||||
case errBadSignature:
|
||||
return "bad request signature"
|
||||
case errInvalidPrivKey:
|
||||
return "invalid private key"
|
||||
default:
|
||||
return "unknown error"
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
package webapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -70,14 +69,14 @@ func feeAddress(c *gin.Context) {
|
||||
dcrdClient := c.MustGet("DcrdClient").(*rpc.DcrdRPC)
|
||||
|
||||
if cfg.VspClosed {
|
||||
sendErrorResponse("pool is not accepting new tickets", http.StatusBadRequest, c)
|
||||
sendError(errVspClosed, c)
|
||||
return
|
||||
}
|
||||
|
||||
var feeAddressRequest FeeAddressRequest
|
||||
if err := binding.JSON.BindBody(rawRequest, &feeAddressRequest); err != nil {
|
||||
log.Warnf("Bad feeaddress request from %s: %v", c.ClientIP(), err)
|
||||
sendErrorResponse(err.Error(), http.StatusBadRequest, c)
|
||||
sendErrorWithMsg(err.Error(), errBadRequest, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -86,7 +85,7 @@ func feeAddress(c *gin.Context) {
|
||||
// Respond early if we already have the fee tx for this ticket.
|
||||
if ticket.FeeTxHex != "" {
|
||||
log.Warnf("Fee tx already received from %s: ticketHash=%s", c.ClientIP(), ticket.Hash)
|
||||
sendErrorResponse("fee tx already received", http.StatusBadRequest, c)
|
||||
sendError(errFeeAlreadyReceived, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -94,7 +93,7 @@ func feeAddress(c *gin.Context) {
|
||||
rawTicket, err := dcrdClient.GetRawTransaction(ticketHash)
|
||||
if err != nil {
|
||||
log.Errorf("Could not retrieve tx %s for %s: %v", ticketHash, c.ClientIP(), err)
|
||||
sendErrorResponse(err.Error(), http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -102,12 +101,12 @@ func feeAddress(c *gin.Context) {
|
||||
canVote, err := dcrdClient.CanTicketVote(rawTicket, ticketHash, cfg.NetParams)
|
||||
if err != nil {
|
||||
log.Errorf("canTicketVote error: %v", err)
|
||||
sendErrorResponse("error validating ticket", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
if !canVote {
|
||||
log.Warnf("Unvotable ticket %s from %s", ticketHash, c.ClientIP())
|
||||
sendErrorResponse("ticket not eligible to vote", http.StatusBadRequest, c)
|
||||
sendError(errTicketCannotVote, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -120,7 +119,7 @@ func feeAddress(c *gin.Context) {
|
||||
newFee, err := getCurrentFee(dcrdClient)
|
||||
if err != nil {
|
||||
log.Errorf("getCurrentFee error: %v", err)
|
||||
sendErrorResponse("fee error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
ticket.FeeExpiration = now.Add(feeAddressExpiration).Unix()
|
||||
@ -129,7 +128,7 @@ func feeAddress(c *gin.Context) {
|
||||
err = db.UpdateTicket(ticket)
|
||||
if err != nil {
|
||||
log.Errorf("UpdateTicket error: %v", err)
|
||||
sendErrorResponse("database error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
log.Debugf("Expired fee updated for ticket: newFeeAmt=%f, ticketHash=%s",
|
||||
@ -152,7 +151,7 @@ func feeAddress(c *gin.Context) {
|
||||
fee, err := getCurrentFee(dcrdClient)
|
||||
if err != nil {
|
||||
log.Errorf("getCurrentFee error: %v", err)
|
||||
sendErrorResponse("fee error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -180,7 +179,7 @@ func feeAddress(c *gin.Context) {
|
||||
err = db.InsertNewTicket(dbTicket)
|
||||
if err != nil {
|
||||
log.Errorf("InsertTicket error: %v", err)
|
||||
sendErrorResponse("database error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -54,7 +54,7 @@ func withDcrdClient() gin.HandlerFunc {
|
||||
client, err := dcrd.Client(c, cfg.NetParams)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
sendErrorResponse("dcrd RPC error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ func withWalletClients() gin.HandlerFunc {
|
||||
clients, failedConnections := wallets.Clients(c, cfg.NetParams)
|
||||
if len(clients) == 0 {
|
||||
log.Error("Could not connect to any wallets")
|
||||
sendErrorResponse("dcrwallet RPC error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
if failedConnections > 0 {
|
||||
@ -93,7 +93,7 @@ func vspAuth() gin.HandlerFunc {
|
||||
reqBytes, err := c.GetRawData()
|
||||
if err != nil {
|
||||
log.Warnf("Error reading request from %s: %v", c.ClientIP(), err)
|
||||
sendErrorResponse(err.Error(), http.StatusBadRequest, c)
|
||||
sendErrorWithMsg(err.Error(), errBadRequest, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ func vspAuth() gin.HandlerFunc {
|
||||
var request ticketHashRequest
|
||||
if err := binding.JSON.BindBody(reqBytes, &request); err != nil {
|
||||
log.Warnf("Bad request from %s: %v", c.ClientIP(), err)
|
||||
sendErrorResponse(err.Error(), http.StatusBadRequest, c)
|
||||
sendErrorWithMsg(err.Error(), errBadRequest, c)
|
||||
return
|
||||
}
|
||||
hash := request.TicketHash
|
||||
@ -113,7 +113,7 @@ func vspAuth() gin.HandlerFunc {
|
||||
ticket, ticketFound, err := db.GetTicketByHash(hash)
|
||||
if err != nil {
|
||||
log.Errorf("GetTicketByHash error: %v", err)
|
||||
sendErrorResponse("database error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ func vspAuth() gin.HandlerFunc {
|
||||
commitmentAddress, err = dcrdClient.GetTicketCommitmentAddress(hash, cfg.NetParams)
|
||||
if err != nil {
|
||||
log.Errorf("GetTicketCommitmentAddress error: %v", err)
|
||||
sendErrorResponse(err.Error(), http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -136,7 +136,7 @@ func vspAuth() gin.HandlerFunc {
|
||||
err = validateSignature(reqBytes, commitmentAddress, c)
|
||||
if err != nil {
|
||||
log.Warnf("Bad signature from %s: %v", c.ClientIP(), err)
|
||||
sendErrorResponse("bad signature", http.StatusBadRequest, c)
|
||||
sendError(errBadSignature, c)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ package webapi
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/decred/dcrd/dcrec"
|
||||
@ -24,23 +23,28 @@ func payFee(c *gin.Context) {
|
||||
knownTicket := c.MustGet("KnownTicket").(bool)
|
||||
dcrdClient := c.MustGet("DcrdClient").(*rpc.DcrdRPC)
|
||||
|
||||
if cfg.VspClosed {
|
||||
sendError(errVspClosed, c)
|
||||
return
|
||||
}
|
||||
|
||||
if !knownTicket {
|
||||
log.Warnf("Invalid ticket from %s", c.ClientIP())
|
||||
sendErrorResponse("invalid ticket", http.StatusBadRequest, c)
|
||||
log.Warnf("Unknown ticket from %s", c.ClientIP())
|
||||
sendError(errUnknownTicket, c)
|
||||
return
|
||||
}
|
||||
|
||||
var payFeeRequest PayFeeRequest
|
||||
if err := binding.JSON.BindBody(rawRequest, &payFeeRequest); err != nil {
|
||||
log.Warnf("Bad payfee request from %s: %v", c.ClientIP(), err)
|
||||
sendErrorResponse(err.Error(), http.StatusBadRequest, c)
|
||||
sendErrorWithMsg(err.Error(), errBadRequest, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Respond early if we already have the fee tx for this ticket.
|
||||
if ticket.FeeTxHex != "" {
|
||||
log.Warnf("Fee tx already received from %s: ticketHash=%s", c.ClientIP(), ticket.Hash)
|
||||
sendErrorResponse("fee tx already received", http.StatusBadRequest, c)
|
||||
sendError(errFeeAlreadyReceived, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -48,7 +52,7 @@ func payFee(c *gin.Context) {
|
||||
rawTicket, err := dcrdClient.GetRawTransaction(ticket.Hash)
|
||||
if err != nil {
|
||||
log.Errorf("Could not retrieve tx %s for %s: %v", ticket.Hash, c.ClientIP(), err)
|
||||
sendErrorResponse(err.Error(), http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -56,19 +60,19 @@ func payFee(c *gin.Context) {
|
||||
canVote, err := dcrdClient.CanTicketVote(rawTicket, ticket.Hash, cfg.NetParams)
|
||||
if err != nil {
|
||||
log.Errorf("canTicketVote error: %v", err)
|
||||
sendErrorResponse("error validating ticket", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
if !canVote {
|
||||
log.Warnf("Unvotable ticket %s from %s", ticket.Hash, c.ClientIP())
|
||||
sendErrorResponse("ticket not eligible to vote", http.StatusBadRequest, c)
|
||||
sendError(errTicketCannotVote, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Respond early if the fee for this ticket is expired.
|
||||
if ticket.FeeExpired() {
|
||||
log.Warnf("Expired payfee request from %s", c.ClientIP())
|
||||
sendErrorResponse("fee has expired", http.StatusBadRequest, c)
|
||||
sendError(errFeeExpired, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -77,7 +81,7 @@ func payFee(c *gin.Context) {
|
||||
votingWIF, err := dcrutil.DecodeWIF(votingKey, cfg.NetParams.PrivateKeyID)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to decode WIF: %v", err)
|
||||
sendErrorResponse("error decoding WIF", http.StatusBadRequest, c)
|
||||
sendError(errInvalidPrivKey, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -86,7 +90,7 @@ func payFee(c *gin.Context) {
|
||||
err = isValidVoteChoices(cfg.NetParams, currentVoteVersion(cfg.NetParams), voteChoices)
|
||||
if err != nil {
|
||||
log.Warnf("Invalid votechoices from %s: %v", c.ClientIP(), err)
|
||||
sendErrorResponse(err.Error(), http.StatusBadRequest, c)
|
||||
sendErrorWithMsg(err.Error(), errInvalidVoteChoices, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -94,14 +98,14 @@ func payFee(c *gin.Context) {
|
||||
feeTxBytes, err := hex.DecodeString(payFeeRequest.FeeTx)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to decode tx: %v", err)
|
||||
sendErrorResponse("failed to decode transaction", http.StatusBadRequest, c)
|
||||
sendError(errInvalidFeeTx, c)
|
||||
return
|
||||
}
|
||||
|
||||
feeTx := wire.NewMsgTx()
|
||||
if err = feeTx.FromBytes(feeTxBytes); err != nil {
|
||||
log.Warnf("Failed to deserialize tx: %v", err)
|
||||
sendErrorResponse("unable to deserialize transaction", http.StatusBadRequest, c)
|
||||
sendError(errInvalidFeeTx, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -113,14 +117,14 @@ func payFee(c *gin.Context) {
|
||||
findAddress:
|
||||
for _, txOut := range feeTx.TxOut {
|
||||
if txOut.Version != scriptVersion {
|
||||
sendErrorResponse("invalid script version", http.StatusBadRequest, c)
|
||||
sendErrorWithMsg("invalid script version", errInvalidFeeTx, c)
|
||||
return
|
||||
}
|
||||
_, addresses, _, err := txscript.ExtractPkScriptAddrs(scriptVersion,
|
||||
txOut.PkScript, cfg.NetParams)
|
||||
if err != nil {
|
||||
log.Errorf("Extract PK error: %v", err)
|
||||
sendErrorResponse("extract PK error", http.StatusBadRequest, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
for _, addr := range addresses {
|
||||
@ -133,7 +137,7 @@ findAddress:
|
||||
|
||||
if feePaid == 0 {
|
||||
log.Warnf("FeeTx for ticket %s did not include any payments for address %s", ticket.Hash, ticket.FeeAddress)
|
||||
sendErrorResponse("feetx did not include any payments for fee address", http.StatusBadRequest, c)
|
||||
sendErrorWithMsg("feetx did not include any payments for fee address", errInvalidFeeTx, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -141,7 +145,7 @@ findAddress:
|
||||
dcrec.STEcdsaSecp256k1)
|
||||
if err != nil {
|
||||
log.Errorf("NewAddressPubKeyHash: %v", err)
|
||||
sendErrorResponse("failed to deserialize voting wif", http.StatusInternalServerError, c)
|
||||
sendError(errInvalidPrivKey, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -149,13 +153,13 @@ findAddress:
|
||||
ticketBytes, err := hex.DecodeString(rawTicket.Hex)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to decode tx: %v", err)
|
||||
sendErrorResponse("failed to decode transaction", http.StatusBadRequest, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
ticketTx := wire.NewMsgTx()
|
||||
if err = ticketTx.FromBytes(ticketBytes); err != nil {
|
||||
log.Errorf("Failed to deserialize tx: %v", err)
|
||||
sendErrorResponse("unable to deserialize transaction", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -163,12 +167,12 @@ findAddress:
|
||||
_, votingAddr, _, err := txscript.ExtractPkScriptAddrs(scriptVersion, ticketTx.TxOut[0].PkScript, cfg.NetParams)
|
||||
if err != nil {
|
||||
log.Errorf("ExtractPK error: %v", err)
|
||||
sendErrorResponse("extract PK error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
if len(votingAddr) == 0 {
|
||||
log.Error("No voting address found for ticket %s", ticket.Hash)
|
||||
sendErrorResponse("no voting address found", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -176,21 +180,21 @@ findAddress:
|
||||
if votingAddr[0].Address() != wifAddr.Address() {
|
||||
log.Warnf("Voting address does not match provided private key: "+
|
||||
"votingAddr=%+v, wifAddr=%+v", votingAddr[0], wifAddr)
|
||||
sendErrorResponse("voting address does not match provided private key",
|
||||
http.StatusBadRequest, c)
|
||||
sendErrorWithMsg("voting address does not match provided private key",
|
||||
errInvalidPrivKey, c)
|
||||
return
|
||||
}
|
||||
|
||||
minFee, err := dcrutil.NewAmount(ticket.FeeAmount)
|
||||
if err != nil {
|
||||
log.Errorf("dcrutil.NewAmount: %v", err)
|
||||
sendErrorResponse("fee error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
if feePaid < minFee {
|
||||
log.Warnf("Fee too small from %s: was %v, expected %v", c.ClientIP(), feePaid, minFee)
|
||||
sendErrorResponse("fee too small", http.StatusInternalServerError, c)
|
||||
sendError(errFeeTooSmall, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -205,7 +209,7 @@ findAddress:
|
||||
err = db.UpdateTicket(ticket)
|
||||
if err != nil {
|
||||
log.Errorf("InsertTicket failed: %v", err)
|
||||
sendErrorResponse("database error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -216,7 +220,7 @@ findAddress:
|
||||
feeTxHash, err := dcrdClient.SendRawTransaction(payFeeRequest.FeeTx)
|
||||
if err != nil {
|
||||
log.Errorf("SendRawTransaction failed: %v", err)
|
||||
sendErrorResponse("dcrwallet RPC error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
ticket.FeeTxHash = feeTxHash
|
||||
@ -224,7 +228,7 @@ findAddress:
|
||||
err = db.UpdateTicket(ticket)
|
||||
if err != nil {
|
||||
log.Errorf("InsertTicket failed: %v", err)
|
||||
sendErrorResponse("database error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package webapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/decred/vspd/database"
|
||||
@ -20,8 +19,8 @@ func setVoteChoices(c *gin.Context) {
|
||||
walletClients := c.MustGet("WalletClients").([]*rpc.WalletRPC)
|
||||
|
||||
if !knownTicket {
|
||||
log.Warnf("Invalid ticket from %s", c.ClientIP())
|
||||
sendErrorResponse("invalid ticket", http.StatusBadRequest, c)
|
||||
log.Warnf("Unknown ticket from %s", c.ClientIP())
|
||||
sendError(errUnknownTicket, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -30,7 +29,7 @@ func setVoteChoices(c *gin.Context) {
|
||||
var setVoteChoicesRequest SetVoteChoicesRequest
|
||||
if err := binding.JSON.BindBody(rawRequest, &setVoteChoicesRequest); err != nil {
|
||||
log.Warnf("Bad setvotechoices request from %s: %v", c.ClientIP(), err)
|
||||
sendErrorResponse(err.Error(), http.StatusBadRequest, c)
|
||||
sendErrorWithMsg(err.Error(), errBadRequest, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -38,7 +37,7 @@ func setVoteChoices(c *gin.Context) {
|
||||
err := isValidVoteChoices(cfg.NetParams, currentVoteVersion(cfg.NetParams), voteChoices)
|
||||
if err != nil {
|
||||
log.Warnf("Invalid votechoices from %s: %v", c.ClientIP(), err)
|
||||
sendErrorResponse(err.Error(), http.StatusBadRequest, c)
|
||||
sendErrorWithMsg(err.Error(), errInvalidVoteChoices, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -48,7 +47,7 @@ func setVoteChoices(c *gin.Context) {
|
||||
err = db.UpdateTicket(ticket)
|
||||
if err != nil {
|
||||
log.Errorf("UpdateTicket error: %v", err)
|
||||
sendErrorResponse("database error", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package webapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/decred/vspd/database"
|
||||
@ -18,15 +17,15 @@ func ticketStatus(c *gin.Context) {
|
||||
knownTicket := c.MustGet("KnownTicket").(bool)
|
||||
|
||||
if !knownTicket {
|
||||
log.Warnf("Invalid ticket from %s", c.ClientIP())
|
||||
sendErrorResponse("invalid ticket", http.StatusBadRequest, c)
|
||||
log.Warnf("Unknown ticket from %s", c.ClientIP())
|
||||
sendError(errUnknownTicket, c)
|
||||
return
|
||||
}
|
||||
|
||||
var ticketStatusRequest TicketStatusRequest
|
||||
if err := binding.JSON.BindBody(rawRequest, &ticketStatusRequest); err != nil {
|
||||
log.Warnf("Bad ticketstatus request from %s: %v", c.ClientIP(), err)
|
||||
sendErrorResponse(err.Error(), http.StatusBadRequest, c)
|
||||
sendErrorWithMsg(err.Error(), errBadRequest, c)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -221,7 +221,7 @@ func sendJSONResponse(resp interface{}, c *gin.Context) {
|
||||
dec, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
log.Errorf("JSON marshal error: %v", err)
|
||||
sendErrorResponse("failed to marshal json", http.StatusInternalServerError, c)
|
||||
sendError(errInternalError, c)
|
||||
return
|
||||
}
|
||||
|
||||
@ -231,8 +231,22 @@ func sendJSONResponse(resp interface{}, c *gin.Context) {
|
||||
c.AbortWithStatusJSON(http.StatusOK, resp)
|
||||
}
|
||||
|
||||
func sendErrorResponse(errMsg string, code int, c *gin.Context) {
|
||||
resp := gin.H{"error": errMsg}
|
||||
// sendError returns an error response to the client using the default error
|
||||
// message.
|
||||
func sendError(e apiError, c *gin.Context) {
|
||||
msg := e.defaultMessage()
|
||||
sendErrorWithMsg(msg, e, c)
|
||||
}
|
||||
|
||||
// sendErrorWithMsg returns an error response to the client using the provided
|
||||
// error message.
|
||||
func sendErrorWithMsg(msg string, e apiError, c *gin.Context) {
|
||||
status := e.httpStatus()
|
||||
|
||||
resp := gin.H{
|
||||
"code": int(e),
|
||||
"message": msg,
|
||||
}
|
||||
|
||||
// Try to sign the error response. If it fails, send it without a signature.
|
||||
dec, err := json.Marshal(resp)
|
||||
@ -243,5 +257,5 @@ func sendErrorResponse(errMsg string, code int, c *gin.Context) {
|
||||
c.Writer.Header().Set("VSP-Server-Signature", hex.EncodeToString(sig))
|
||||
}
|
||||
|
||||
c.AbortWithStatusJSON(code, resp)
|
||||
c.AbortWithStatusJSON(status, resp)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user