Пример #1
0
func (this *urlArgs) getScanVector() (timestamp.Vector, errors.Error) {
	var full_vector_data []*restArg
	var sparse_vector_data map[string]*restArg

	scan_vector_data_field, err := this.formValue(SCAN_VECTOR)

	if err != nil || scan_vector_data_field == "" {
		return nil, err
	}
	decoder := json.NewDecoder(strings.NewReader(scan_vector_data_field))
	e := decoder.Decode(&full_vector_data)
	if e == nil {
		return makeFullVector(full_vector_data)
	}
	decoder = json.NewDecoder(strings.NewReader(scan_vector_data_field))
	e = decoder.Decode(&sparse_vector_data)
	if e != nil {
		return nil, errors.NewServiceErrorBadValue(e, SCAN_VECTOR)
	}
	// Check that the rest data has the expected names
	for _, arg := range sparse_vector_data {
		if arg.Value == 0 || arg.Guard == "" {
			return nil, errors.NewServiceErrorBadValue(e, SCAN_VECTOR)
		}
	}

	return makeSparseVector(sparse_vector_data)
}
Пример #2
0
func getCredentials(a httpRequestArgs, auths []string) (datastore.Credentials, errors.Error) {
	cred_data, err := a.getCredentials()
	if err != nil {
		return nil, err
	}

	if len(cred_data) > 0 {
		// Credentials are in request parameters:
		creds := datastore.Credentials{}
		for _, cred := range cred_data {
			user, user_ok := cred["user"]
			pass, pass_ok := cred["pass"]
			if user_ok && pass_ok {
				creds[user] = pass
			} else {
				err = errors.NewServiceErrorMissingValue("user or pass")
				break
			}
		}
		return creds, nil
	}

	if len(auths) > 0 {
		// Credentials are in http header:
		auth := auths[0]
		if strings.HasPrefix(auth, "Basic ") {
			encoded_creds := strings.Split(auth, " ")[1]
			decoded_creds, err := base64.StdEncoding.DecodeString(encoded_creds)
			if err != nil {
				return nil, errors.NewServiceErrorBadValue(err, CREDS)
			}
			// Authorization header is in format "user:pass"
			// per http://tools.ietf.org/html/rfc1945#section-10.2
			u_details := strings.Split(string(decoded_creds), ":")
			creds := datastore.Credentials{}
			switch len(u_details) {
			case 2:
				creds[u_details[0]] = u_details[1]
			case 3:
				// Support usernames like "local:xxx" or "admin:xxx"
				creds[strings.Join(u_details[:2], ":")] = u_details[2]
			default:
				// Authorization header format is incorrect
				return nil, errors.NewServiceErrorBadValue(nil, CREDS)
			}
			return creds, nil
		}
	}

	return nil, err
}
Пример #3
0
func makeSparseVector(args map[string]interface{}) (*scanVectorEntries, errors.Error) {
	entries := make([]timestamp.Entry, len(args))
	i := 0
	for key, arg := range args {
		index, err := strconv.Atoi(key)
		if err != nil {
			return nil, errors.NewServiceErrorBadValue(err, SCAN_VECTOR)
		}
		array, ok := arg.([]interface{})
		if !ok {
			return nil, errors.NewServiceErrorTypeMismatch("scan vector entry", "two-element array")
		}
		sequenceNum, uuid, error := extractValues(array)
		if err != nil {
			return nil, error
		}
		entries[i] = &scanVectorEntry{
			position: uint32(index),
			value:    sequenceNum,
			guard:    uuid,
		}
		i = i + 1
	}
	return &scanVectorEntries{
		entries: entries,
	}, nil
}
Пример #4
0
// helper function to create a time.Duration instance from a given string.
// There must be a unit - valid units are "ns", "us", "ms", "s", "m", "h"
func newDuration(s string) (duration time.Duration, err errors.Error) {
	// Error if given string has no unit
	last_char := s[len(s)-1]
	if last_char != 's' && last_char != 'm' && last_char != 'h' {
		err = errors.NewServiceErrorBadValue(nil,
			fmt.Sprintf("duration value %s: missing or incorrect unit "+
				"(valid units: ns, us, ms, s, m, h)", s))
	}
	if err == nil {
		d, e := time.ParseDuration(s)
		if e != nil {
			err = errors.NewServiceErrorBadValue(e, "duration")
		} else {
			duration = d
		}
	}
	return
}
Пример #5
0
func (this *urlArgs) getCredentials() ([]map[string]string, errors.Error) {
	var creds_data []map[string]string

	creds_field, err := this.formValue(CREDS)
	if err == nil && creds_field != "" {
		decoder := json.NewDecoder(strings.NewReader(creds_field))
		e := decoder.Decode(&creds_data)
		if e != nil {
			err = errors.NewServiceErrorBadValue(e, CREDS)
		}
	}
	return creds_data, err
}
Пример #6
0
// create a jsonArgs structure from the given http request.
func newJsonArgs(req *http.Request) (*jsonArgs, errors.Error) {
	var p jsonArgs
	decoder := json.NewDecoder(req.Body)
	err := decoder.Decode(&p.args)
	if err != nil {
		return nil, errors.NewServiceErrorBadValue(err, "JSON request body")
	}
	for arg, _ := range p.args {
		if !isValidParameter(arg) {
			return nil, errors.NewServiceErrorUnrecognizedParameter(arg)
		}
	}
	p.req = req
	return &p, nil
}
Пример #7
0
func (this *urlArgs) getTristate(f string) (value.Tristate, errors.Error) {
	tristate_value := value.NONE
	value_field, err := this.formValue(f)
	if err != nil {
		return tristate_value, err
	}
	if value_field == "" {
		return tristate_value, nil
	}
	bool_value, e := strconv.ParseBool(value_field)
	if e != nil {
		return tristate_value, errors.NewServiceErrorBadValue(e, f)
	}
	tristate_value = value.ToTristate(bool_value)
	return tristate_value, nil
}
Пример #8
0
func (this *urlArgs) getScanVectors() (map[string]timestamp.Vector, errors.Error) {
	scan_vectors_data_field, err := this.formValue(SCAN_VECTORS)

	if err != nil || scan_vectors_data_field == "" {
		return nil, err
	}

	var target interface{}
	decoder := json.NewDecoder(strings.NewReader(scan_vectors_data_field))
	e := decoder.Decode(&target)
	if e != nil {
		return nil, errors.NewServiceErrorBadValue(e, SCAN_VECTORS)
	}

	return getScanVectorsFromJSON(target)
}
Пример #9
0
func (this *urlArgs) getStatement() (string, errors.Error) {
	statement, err := this.formValue(STATEMENT)
	if err != nil {
		return "", err
	}

	if statement == "" && this.req.Method == "POST" {
		bytes, err := ioutil.ReadAll(this.req.Body)
		if err != nil {
			return "", errors.NewServiceErrorBadValue(err, STATEMENT)
		}

		statement = string(bytes)
	}

	return statement, nil
}
Пример #10
0
func (this *jsonArgs) getScanVector() (timestamp.Vector, errors.Error) {
	var type_ok bool

	scan_vector_data_field, in_request := this.getField(SCAN_VECTOR)
	if !in_request {
		return nil, nil
	}
	full_vector_data, type_ok := scan_vector_data_field.([]interface{})
	if type_ok {
		if len(full_vector_data) != SCAN_VECTOR_SIZE {
			return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR,
				fmt.Sprintf("array of %d entries", SCAN_VECTOR_SIZE))
		}
		entries := make([]timestamp.Entry, len(full_vector_data))
		for index, arg := range full_vector_data {
			nextEntry, err := makeVectorEntry(index, arg)
			if err != nil {
				return nil, err
			}
			entries[index] = nextEntry
		}
	}
	sparse_vector_data, type_ok := scan_vector_data_field.(map[string]interface{})
	if !type_ok {
		return nil, errors.NewServiceErrorTypeMismatch(SCAN_VECTOR, "array or map of { number, string }")
	}
	entries := make([]timestamp.Entry, len(sparse_vector_data))
	i := 0
	for key, arg := range sparse_vector_data {
		index, e := strconv.Atoi(key)
		if e != nil {
			return nil, errors.NewServiceErrorBadValue(e, SCAN_VECTOR)
		}
		nextEntry, err := makeVectorEntry(index, arg)
		if err != nil {
			return nil, err
		}
		entries[i] = nextEntry
		i = i + 1
	}
	return &scanVectorEntries{
		entries: entries,
	}, nil
}
Пример #11
0
// makeSparseVector is used when the request contains a sparse entry arg
func makeSparseVector(args map[string]*restArg) (*scanVectorEntries, errors.Error) {
	entries := make([]timestamp.Entry, len(args))
	i := 0
	for key, arg := range args {
		index, err := strconv.Atoi(key)
		if err != nil {
			return nil, errors.NewServiceErrorBadValue(err, SCAN_VECTOR)
		}
		entries[i] = &scanVectorEntry{
			position: uint32(index),
			value:    arg.Value,
			guard:    arg.Guard,
		}
		i = i + 1
	}
	return &scanVectorEntries{
		entries: entries,
	}, nil
}
Пример #12
0
// Positional args are of the form: args=json_list
func (this *urlArgs) getPositionalArgs() (value.Values, errors.Error) {
	var positionalArgs value.Values

	args_field, err := this.formValue(ARGS)
	if err != nil || args_field == "" {
		return positionalArgs, err
	}

	var args []interface{}

	decoder := json.NewDecoder(strings.NewReader(args_field))
	e := decoder.Decode(&args)
	if e != nil {
		return positionalArgs, errors.NewServiceErrorBadValue(e, ARGS)
	}

	positionalArgs = make([]value.Value, len(args))
	// Put each element of args into positionalArgs
	for i, arg := range args {
		positionalArgs[i] = value.NewValue(arg)
	}

	return positionalArgs, nil
}
Пример #13
0
func newHttpRequest(resp http.ResponseWriter, req *http.Request, bp BufferPool, size int) *httpRequest {
	var httpArgs httpRequestArgs
	var err errors.Error

	// Limit body size in case of denial-of-service attack
	req.Body = http.MaxBytesReader(resp, req.Body, int64(size))

	e := req.ParseForm()
	if e != nil {
		err = errors.NewServiceErrorBadValue(e, "request form")
	}

	if err != nil && req.Method != "GET" && req.Method != "POST" {
		err = errors.NewServiceErrorHTTPMethod(req.Method)
	}

	err = contentNegotiation(resp, req)

	if err == nil {
		httpArgs, err = getRequestParams(req)
	}

	var statement string
	if err == nil {
		statement, err = httpArgs.getStatement()
	}

	var prepared *plan.Prepared

	if err == nil {
		prepared, err = getPrepared(httpArgs)
		plan, plan_err := getEncodedPlan(httpArgs)
		if err != nil && err.Code() == errors.NO_SUCH_PREPARED {
			if plan_err != nil {
				err = plan_err
			}
			if plan_err == nil && plan != nil {
				prepared = plan
				err = nil
			}
		}
		if err == nil && plan_err != nil {
			err = plan_err
		}
		if prepared != nil && plan != nil && prepared.EncodedPlan() != plan.EncodedPlan() {
			err = errors.NewPreparedEncodingMismatchError(prepared.Name())
		}
	}

	if err == nil && statement == "" && prepared == nil {
		err = errors.NewServiceErrorMissingValue("statement or prepared")
	}

	var namedArgs map[string]value.Value
	if err == nil {
		namedArgs, err = httpArgs.getNamedArgs()
	}

	var positionalArgs value.Values
	if err == nil {
		positionalArgs, err = httpArgs.getPositionalArgs()
	}

	var namespace string
	if err == nil {
		namespace, err = httpArgs.getString(NAMESPACE, "")
	}

	var timeout time.Duration
	if err == nil {
		timeout, err = httpArgs.getDuration(TIMEOUT)
	}

	var max_parallelism int
	if err == nil {
		var maxp string
		maxp, err = httpArgs.getString(MAX_PARALLELISM, "")
		if err == nil && maxp != "" {
			var e error
			max_parallelism, e = strconv.Atoi(maxp)
			if e != nil {
				err = errors.NewServiceErrorBadValue(e, "max parallelism")
			}
		}
	}

	var readonly value.Tristate
	if err == nil {
		readonly, err = getReadonly(httpArgs, req.Method == "GET")
	}

	var metrics value.Tristate
	if err == nil {
		metrics, err = httpArgs.getTristate(METRICS)
	}

	var format Format
	if err == nil {
		format, err = getFormat(httpArgs)
	}

	if err == nil && format != JSON {
		err = errors.NewServiceErrorNotImplemented("format", format.String())
	}

	var signature value.Tristate
	if err == nil {
		signature, err = httpArgs.getTristate(SIGNATURE)
	}

	var compression Compression
	if err == nil {
		compression, err = getCompression(httpArgs)
	}

	if err == nil && compression != NONE {
		err = errors.NewServiceErrorNotImplemented("compression", compression.String())
	}

	var encoding Encoding
	if err == nil {
		encoding, err = getEncoding(httpArgs)
	}

	if err == nil && encoding != UTF8 {
		err = errors.NewServiceErrorNotImplemented("encoding", encoding.String())
	}

	var pretty value.Tristate
	if err == nil {
		pretty, err = httpArgs.getTristate(PRETTY)
	}

	if err == nil && pretty == value.FALSE {
		err = errors.NewServiceErrorNotImplemented("pretty", "false")
	}

	var consistency *scanConfigImpl

	if err == nil {
		consistency, err = getScanConfiguration(httpArgs)
	}

	var creds datastore.Credentials
	if err == nil {
		creds, err = getCredentials(httpArgs, req.Header["Authorization"])
	}

	client_id := ""
	if err == nil {
		client_id, err = getClientID(httpArgs)
	}

	base := server.NewBaseRequest(statement, prepared, namedArgs, positionalArgs, namespace,
		max_parallelism, readonly, metrics, signature, consistency, client_id, creds)

	rv := &httpRequest{
		BaseRequest:   *base,
		resp:          resp,
		req:           req,
		requestNotify: make(chan bool, 1),
	}

	rv.SetTimeout(rv, timeout)

	rv.writer = NewBufferedWriter(rv, bp)

	// Abort if client closes connection; alternatively, return when request completes.
	closeNotify := resp.(http.CloseNotifier).CloseNotify()
	closeNotifier := func() {
		select {
		case <-closeNotify:
			rv.Expire()
			return
		case <-rv.requestNotify:
			return
		}
	}
	go closeNotifier()

	if err != nil {
		rv.Fail(err)
	}

	return rv
}