github.com/ethersphere/bee/v2@v2.2.0/pkg/api/envelope.go (about)

     1  // Copyright 2024 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package api
     6  
     7  import (
     8  	"encoding/hex"
     9  	"errors"
    10  	"net/http"
    11  
    12  	"github.com/ethersphere/bee/v2/pkg/jsonhttp"
    13  	"github.com/ethersphere/bee/v2/pkg/postage"
    14  	"github.com/ethersphere/bee/v2/pkg/swarm"
    15  	"github.com/gorilla/mux"
    16  )
    17  
    18  type postEnvelopeResponse struct {
    19  	Issuer    string `json:"issuer"`    // Ethereum address of the postage batch owner
    20  	Index     string `json:"index"`     // used index of the Postage Batch
    21  	Timestamp string `json:"timestamp"` // timestamp of the postage stamp
    22  	Signature string `json:"signature"` // postage stamp signature
    23  }
    24  
    25  // envelopePostHandler generates new postage stamp for requested chunk address
    26  func (s *Service) envelopePostHandler(w http.ResponseWriter, r *http.Request) {
    27  	logger := s.logger.WithName("post_envelope").Build()
    28  
    29  	headers := struct {
    30  		BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"`
    31  	}{}
    32  	if response := s.mapStructure(r.Header, &headers); response != nil {
    33  		response("invalid header params", logger, w)
    34  		return
    35  	}
    36  
    37  	paths := struct {
    38  		Address swarm.Address `map:"address" validate:"required"`
    39  	}{}
    40  	if response := s.mapStructure(mux.Vars(r), &paths); response != nil {
    41  		response("invalid path params", logger, w)
    42  		return
    43  	}
    44  
    45  	stamper, save, err := s.getStamper(headers.BatchID)
    46  	if err != nil {
    47  		logger.Debug("get stamper failed", "error", err)
    48  		logger.Error(err, "get stamper failed")
    49  		switch {
    50  		case errors.Is(err, errBatchUnusable) || errors.Is(err, postage.ErrNotUsable):
    51  			jsonhttp.UnprocessableEntity(w, "batch not usable yet or does not exist")
    52  		case errors.Is(err, postage.ErrNotFound):
    53  			jsonhttp.NotFound(w, "batch with id not found")
    54  		case errors.Is(err, errInvalidPostageBatch):
    55  			jsonhttp.BadRequest(w, "invalid batch id")
    56  		default:
    57  			jsonhttp.InternalServerError(w, nil)
    58  		}
    59  		return
    60  	}
    61  
    62  	stamp, err := stamper.Stamp(paths.Address)
    63  	if err != nil {
    64  		logger.Debug("split write all failed", "error", err)
    65  		logger.Error(nil, "split write all failed")
    66  		switch {
    67  		case errors.Is(err, postage.ErrBucketFull):
    68  			jsonhttp.PaymentRequired(w, "batch is overissued")
    69  		default:
    70  			jsonhttp.InternalServerError(w, "stamping failed")
    71  		}
    72  		return
    73  	}
    74  	err = save()
    75  	if err != nil {
    76  		jsonhttp.InternalServerError(w, "failed to save stamp issuer")
    77  		return
    78  	}
    79  
    80  	issuer, err := s.signer.EthereumAddress()
    81  	if err != nil {
    82  		jsonhttp.InternalServerError(w, "signer ethereum address")
    83  		return
    84  	}
    85  	jsonhttp.Created(w, postEnvelopeResponse{
    86  		Issuer:    issuer.Hex(),
    87  		Index:     hex.EncodeToString(stamp.Index()),
    88  		Timestamp: hex.EncodeToString(stamp.Timestamp()),
    89  		Signature: hex.EncodeToString(stamp.Sig()),
    90  	})
    91  }