github.com/hoffie/larasync@v0.0.0-20151025221940-0384d2bddcef/api/server/nib.go (about)

     1  package server
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net/http"
     7  	"os"
     8  	"strconv"
     9  
    10  	"github.com/gorilla/mux"
    11  
    12  	"github.com/hoffie/larasync/api"
    13  	"github.com/hoffie/larasync/helpers/bincontainer"
    14  	repositoryModule "github.com/hoffie/larasync/repository"
    15  )
    16  
    17  // nibGet returns the NIB data for a given repository and a given UUID.
    18  func (s *Server) nibGet(rw http.ResponseWriter, req *http.Request) {
    19  	vars := mux.Vars(req)
    20  	repositoryName := vars["repository"]
    21  
    22  	repository, err := s.rm.Open(repositoryName)
    23  	if err != nil {
    24  		errorJSONMessage(rw, "Internal Error", http.StatusInternalServerError)
    25  		return
    26  	}
    27  
    28  	nibID := vars["nibID"]
    29  
    30  	Log.Debug(fmt.Sprintf("Repository %s: Requesting NIB with ID %s", repositoryName, nibID))
    31  	reader, err := repository.GetNIBReader(nibID)
    32  
    33  	if err != nil {
    34  		rw.Header().Set("Content-Type", "plain/text")
    35  		if os.IsNotExist(err) {
    36  			errorText(rw, "Not found", http.StatusNotFound)
    37  		} else {
    38  			errorText(rw, "Internal Error", http.StatusInternalServerError)
    39  		}
    40  		return
    41  	}
    42  
    43  	defer reader.Close()
    44  
    45  	rw.Header().Set("Content-Type", "application/octet-stream")
    46  	attachCurrentTransactionHeader(repository, rw)
    47  	rw.WriteHeader(http.StatusOK)
    48  	io.Copy(rw, reader)
    49  }
    50  
    51  // nibPut is the handler which adds a NIB to the repository.
    52  func (s *Server) nibPut(rw http.ResponseWriter, req *http.Request) {
    53  	vars := mux.Vars(req)
    54  	repositoryName := vars["repository"]
    55  
    56  	repository, err := s.rm.Open(repositoryName)
    57  	if err != nil {
    58  		errorJSONMessage(rw, "Internal Error", http.StatusInternalServerError)
    59  		return
    60  	}
    61  
    62  	nibID := vars["nibID"]
    63  
    64  	successReturnStatus := http.StatusOK
    65  	if !repository.HasNIB(nibID) {
    66  		successReturnStatus = http.StatusCreated
    67  	}
    68  
    69  	Log.Debug(fmt.Sprintf("Repository %s: Adding NIB with ID %s", repositoryName, nibID))
    70  	err = repository.AddNIBContent(req.Body)
    71  
    72  	if err != nil {
    73  		if err == repositoryModule.ErrSignatureVerification {
    74  			Log.Debug(fmt.Sprintf("Repository %s: Signature Verification failed when trying to add NIB with ID %s", repositoryName, nibID))
    75  			errorText(rw, "Signature could not be verified", http.StatusUnauthorized)
    76  		} else if err == repositoryModule.ErrUnMarshalling {
    77  			Log.Debug(fmt.Sprintf("Repository %s: Unmarshalling failed when trying to add NIB with ID %s", repositoryName, nibID))
    78  			errorText(rw, "Could not extract NIB", http.StatusBadRequest)
    79  		} else if err == repositoryModule.ErrNIBConflict {
    80  			Log.Debug(fmt.Sprintf("Repository %s: Conflict when trying to add NIB with ID %s", repositoryName, nibID))
    81  			errorText(rw, "NIB conflict", http.StatusConflict)
    82  		} else if repositoryModule.IsNIBContentMissing(err) {
    83  			Log.Debug(fmt.Sprintf("Repository %s: Contents of NIB not in Server when trying to add NIB with ID %s", repositoryName, nibID))
    84  			nibError := err.(*repositoryModule.ErrNIBContentMissing)
    85  			jsonError := &api.ContentIDsJSONError{}
    86  			jsonError.Error = nibError.Error()
    87  			jsonError.Type = "missing_content_ids"
    88  			jsonError.MissingContentIDs = nibError.MissingContentIDs()
    89  			errorJSON(rw, jsonError, http.StatusPreconditionFailed)
    90  		} else {
    91  			Log.Warn(fmt.Sprintf("Repository %s: Internal Error when trying to add NIB with ID %s. %s", repositoryName, nibID, err.Error()))
    92  			errorText(rw, "Internal Error", http.StatusInternalServerError)
    93  		}
    94  		return
    95  	}
    96  
    97  	rw.Header().Set("Location", req.URL.String())
    98  	attachCurrentTransactionHeader(repository, rw)
    99  	rw.WriteHeader(successReturnStatus)
   100  }
   101  
   102  func (s *Server) nibList(rw http.ResponseWriter, req *http.Request) {
   103  	vars := mux.Vars(req)
   104  	repositoryName := vars["repository"]
   105  
   106  	repository, err := s.rm.Open(repositoryName)
   107  	if err != nil {
   108  		errorText(rw, "Internal Error", http.StatusInternalServerError)
   109  		return
   110  	}
   111  
   112  	values := req.URL.Query()
   113  	fromRepositoryIDString, ok := values["from-transaction-id"]
   114  
   115  	var nibChannel <-chan []byte
   116  	if !ok {
   117  		Log.Debug(fmt.Sprintf("Repository %s:, Requesting complete NIB list", repositoryName))
   118  		nibChannel, err = repository.GetAllNIBBytes()
   119  	} else {
   120  		afterTransactionID, err := strconv.ParseInt(fromRepositoryIDString[0], 10, 64)
   121  		if err != nil {
   122  			errorText(
   123  				rw,
   124  				fmt.Sprintf(
   125  					"from-transaction-id %s is not a valid transaction id",
   126  					fromRepositoryIDString,
   127  				),
   128  				http.StatusBadRequest,
   129  			)
   130  			Log.Debug(fmt.Sprintf("Repository %s: Error while trying to extract transaction id of %s", repositoryName, fromRepositoryIDString[0]))
   131  			return
   132  		}
   133  		Log.Debug(fmt.Sprintf("Repository %s: Requesting NIB list after transaction id %d", repositoryName, afterTransactionID))
   134  		nibChannel, err = repository.GetNIBBytesFrom(afterTransactionID)
   135  	}
   136  
   137  	if err != nil {
   138  		Log.Warn(fmt.Sprintf("Repository %s: Could not extract nib data.", repositoryName))
   139  		errorText(rw, "Could not extract data", http.StatusInternalServerError)
   140  		return
   141  	}
   142  
   143  	header := rw.Header()
   144  	header.Set("Content-Type", "application/octet-stream")
   145  	attachCurrentTransactionHeader(repository, rw)
   146  
   147  	rw.WriteHeader(http.StatusOK)
   148  
   149  	encoder := bincontainer.NewEncoder(rw)
   150  	for nibData := range nibChannel {
   151  		encoder.WriteChunk(nibData)
   152  	}
   153  }