예제 #1
0
파일: server.go 프로젝트: amarantha-k/query
func (this *Server) serviceRequest(request Request) {
	defer func() {
		err := recover()
		if err != nil {
			buf := make([]byte, 1<<16)
			n := runtime.Stack(buf, false)
			s := string(buf[0:n])
			logging.Severep("", logging.Pair{"panic", err},
				logging.Pair{"stack", s})
			os.Stderr.WriteString(s)
			os.Stderr.Sync()
		}
	}()

	request.Servicing()

	namespace := request.Namespace()
	if namespace == "" {
		namespace = this.namespace
	}

	prepared, err := this.getPrepared(request, namespace)
	if err != nil {
		request.Fail(err)
	}

	if (this.readonly || value.ToBool(request.Readonly())) &&
		(prepared != nil && !prepared.Readonly()) {
		request.Fail(errors.NewServiceErrorReadonly("The server or request is read-only" +
			" and cannot accept this write statement."))
	}

	var operator execution.Operator
	if request.State() != FATAL {
		var err error
		operator, err = execution.Build(prepared)
		if err != nil {
			request.Fail(errors.NewError(err, ""))
		}
	}

	if request.State() == FATAL {
		// Fail the request - Write out response - and return
		request.Failed(this)
		return
	}

	// Apply server execution timeout
	if this.timeout > 0 {
		timer := time.AfterFunc(this.timeout, func() { request.Expire() })
		defer timer.Stop()
	}

	go request.Execute(this, prepared.Signature(), operator.StopChannel())

	context := execution.NewContext(this.datastore, this.systemstore, namespace,
		this.readonly, request.NamedArgs(), request.PositionalArgs(), request.Credentials(),
		request.ScanConsistency(), request.ScanVector(),
		request.Output())
	operator.RunOnce(context, nil)
}
예제 #2
0
func newHttpRequest(resp http.ResponseWriter, req *http.Request, bp BufferPool) *httpRequest {
	var httpArgs httpRequestArgs
	var err errors.Error

	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)
	}

	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)
	}

	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 readonly value.Tristate
	if err == nil {
		readonly, err = httpArgs.getTristate(READONLY)
	}
	if err == nil && readonly == value.FALSE && req.Method == "GET" {
		err = errors.NewServiceErrorReadonly(
			fmt.Sprintf("%s=false cannot be used with HTTP GET method.", READONLY))
	}

	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.URL.User, req.Header["Authorization"])
	}

	client_id := ""
	if err == nil {
		client_id, err = httpArgs.getString(CLIENT_CONTEXT_ID, "")
	}

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

	rv := &httpRequest{
		BaseRequest: *base,
		resp:        resp,
		req:         req,
	}

	rv.SetTimeout(rv, timeout)

	rv.writer = NewBufferedWriter(rv, bp)

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

	// Abort if client closes connection
	closeNotify := resp.(http.CloseNotifier).CloseNotify()
	go func() {
		<-closeNotify
		rv.Stop(server.TIMEOUT)
	}()

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

	return rv
}