Example #1
0
func (self *ProductViewAPI) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	var cp *cassandra.ColumnParent
	var pred *cassandra.SlicePredicate
	var res []*cassandra.ColumnOrSuperColumn
	var csc *cassandra.ColumnOrSuperColumn
	var ire *cassandra.InvalidRequestException
	var ue *cassandra.UnavailableException
	var te *cassandra.TimedOutException
	var prod Product
	var err error
	var uuidstr string = req.FormValue("id")
	var ts int64 = 0
	var uuid UUID

	var rawdata []byte

	numRequests.Add(1)
	numAPIRequests.Add(1)

	// Check the user is in the reqeuested scope.
	if !self.authenticator.IsAuthenticatedScope(req, self.scope) {
		numDisallowedScope.Add(1)
		http.Error(w,
			"You are not in the right group to access this resource",
			http.StatusForbidden)
		return
	}

	if len(uuidstr) <= 0 {
		http.Error(w, "Requested UUID empty", http.StatusNotAcceptable)
		return
	}

	uuid, err = ParseUUID(uuidstr)
	if err != nil {
		http.Error(w, "Requested UUID invalid", http.StatusNotAcceptable)
		return
	}

	cp = cassandra.NewColumnParent()
	cp.ColumnFamily = "products"

	pred = cassandra.NewSlicePredicate()
	pred.ColumnNames = [][]byte{
		[]byte("name"), []byte("price"), []byte("vendor"),
		[]byte("barcodes"), []byte("stock"),
	}

	res, ire, ue, te, err = self.client.GetSlice([]byte(uuid), cp, pred,
		cassandra.ConsistencyLevel_ONE)
	if ire != nil {
		log.Print("Invalid request: ", ire.Why)
		productViewErrors.Add(ire.Why, 1)
		return
	}
	if ue != nil {
		log.Print("Unavailable")
		productViewErrors.Add("unavailable", 1)
		return
	}
	if te != nil {
		log.Print("Request to database backend timed out")
		productViewErrors.Add("timeout", 1)
		return
	}
	if err != nil {
		log.Print("Generic error: ", err)
		productViewErrors.Add(err.Error(), 1)
		return
	}

	for _, csc = range res {
		var col = csc.Column
		var cname string
		if !csc.IsSetColumn() {
			continue
		}

		cname = string(col.Name)
		if col.IsSetTimestamp() && col.Timestamp > ts {
			ts = col.Timestamp
		}

		if cname == "name" {
			prod.Name = string(col.Value)
		} else if cname == "price" {
			var buf *bytes.Buffer = bytes.NewBuffer(col.Value)
			err = binary.Read(buf, binary.BigEndian, &prod.Price)
			if err != nil {
				log.Print("Row ", uuid.String(), " price is invalid")
				productViewErrors.Add("corrupted-price", 1)
			}
		} else if cname == "vendor" {
			prod.VendorId = UUID(col.Value).String()
		} else if cname == "barcodes" {
			var bc Barcodes
			err = proto.Unmarshal(col.Value, &bc)
			if err != nil {
				log.Print("Row ", uuid.String(), " barcode is invalid")
				productViewErrors.Add("corrupted-barcode", 1)
				return
			}

			for _, code := range bc.Barcode {
				prod.Barcodes = append(prod.Barcodes, code)
			}
		} else if cname == "stock" {
			var buf *bytes.Buffer = bytes.NewBuffer(col.Value)
			err = binary.Read(buf, binary.BigEndian, &prod.Stock)
			if err != nil {
				log.Print("Row ", uuid.String(), " stock is invalid")
				productViewErrors.Add("corrupted-stock", 1)
			}
		}
	}

	rawdata, err = json.Marshal(prod)
	if err != nil {
		log.Print("Error marshalling JSON: ", err)
		numJSONMarshalErrors.Add(1)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Add("Content-type", "application/json")
	w.WriteHeader(http.StatusOK)
	_, err = w.Write(rawdata)
	if err != nil {
		log.Print("Error writing JSON response: ", err)
		numHTTPWriteErrors.Add(err.Error(), 1)
	}
}