github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/runtime/handler/source.go (about)

     1  package handler
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"io"
     8  
     9  	pb "github.com/tickoalcantara12/micro/v3/proto/runtime"
    10  	"github.com/tickoalcantara12/micro/v3/service/auth"
    11  	"github.com/tickoalcantara12/micro/v3/service/errors"
    12  	"github.com/tickoalcantara12/micro/v3/service/store"
    13  )
    14  
    15  const (
    16  	sourcePrefix        = "source://"
    17  	blobNamespacePrefix = "micro/runtime"
    18  )
    19  
    20  // Source implements the proto source service interface
    21  type Source struct{}
    22  
    23  // Upload source to the server
    24  func (s *Source) Upload(ctx context.Context, stream pb.Source_UploadStream) error {
    25  	// authorize the request
    26  	acc, ok := auth.AccountFromContext(ctx)
    27  	if !ok {
    28  		return errors.Unauthorized("runtime.Source.Upload", "An account is required to upload source")
    29  	}
    30  	namespace := acc.Issuer
    31  
    32  	// recieve the source from the client
    33  	buf := bytes.NewBuffer(nil)
    34  	var srv *pb.Service
    35  	for {
    36  		req, err := stream.Recv()
    37  		if err == io.EOF {
    38  			break
    39  		} else if err != nil {
    40  			return errors.InternalServerError("runtime.Source.Upload", err.Error())
    41  		}
    42  
    43  		// get the service from the request, this should be sent on the first message
    44  		if req.Service != nil {
    45  			srv = req.Service
    46  		}
    47  
    48  		// write the bytes to the buffer
    49  		if _, err := buf.Write(req.Data); err != nil {
    50  			return err
    51  		}
    52  	}
    53  
    54  	// ensure the blob and a service was sent over the stream
    55  	if buf == nil {
    56  		return errors.BadRequest("runtime.Source.Upload", "No blob was sent")
    57  	}
    58  	if srv == nil {
    59  		return errors.BadRequest("runtime.Source.Upload", "No service was sent")
    60  	}
    61  
    62  	// write the source to the store
    63  	key := fmt.Sprintf("source://%v:%v", srv.Name, srv.Version)
    64  	opt := store.BlobNamespace(namespace)
    65  	if err := store.DefaultBlobStore.Write(key, buf, opt); err != nil {
    66  		return fmt.Errorf("Error writing source to blob store: %v", err)
    67  	}
    68  
    69  	// close the stream
    70  	return stream.SendAndClose(&pb.UploadResponse{Id: key})
    71  }