func (r *Response) StreamError() error {
	return r.streamErr
}
StreamError returns an error which occurred in a goroutine spawned from
ReadStreamJSON method. Don't call this method before the channel returned
from ReadStreamJSON is closed.
package client
import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"gopkg.in/sensorbee/sensorbee.v0/server/response"
	"io"
	"io/ioutil"
	"mime"
	"net/http"
	"strconv"
	"strings"
)
type Response struct {
	Raw *http.Response
	closeStream  chan struct{}
	streamClosed chan struct{}
	streamErr    error
	closed   bool
	closeErr error
	bodyCache []byte
	errCache  *response.Error
	readErr   error
	mimeType     string
	mimeParams   map[string]string
	mimeParseErr error
}
func (r *Response) Close() error {
	if r.closed {
		return r.closeErr
	}
	r.closed = true
	if r.closeStream != nil {
		close(r.closeStream)
	}
	r.closeErr = r.Raw.Body.Close()
	if r.closeStream != nil {
		<-r.streamClosed  
	}
	return r.closeErr
}
func (r *Response) IsStream() bool {
	if err := r.parseMediaType(); err != nil {
		return false
	}
	if !strings.Contains(r.mimeType, "multipart") {
		return false
	}
	return r.mimeParams["boundary"] != ""
}
func (r *Response) parseMediaType() error {
	if r.mimeType != "" || r.mimeParseErr != nil {
		return r.mimeParseErr
	}
	t, p, err := mime.ParseMediaType(r.Raw.Header.Get("Content-Type"))
	if err != nil {
		r.mimeParseErr = err
		return err
	}
	r.mimeType = t
	r.mimeParams = p
	return nil
}
func (r *Response) Body() ([]byte, error) {
	if r.IsStream() {
		return nil, errors.New("cannot perform Body method on a stream response")
	}
	if r.bodyCache != nil || r.readErr != nil {
		return r.bodyCache, r.readErr
	}
	defer r.Close()
	r.bodyCache, r.readErr = ioutil.ReadAll(r.Raw.Body)
	return r.bodyCache, r.readErr
}
func (r *Response) IsError() bool {
	return r.Raw.StatusCode < 200 || 300 <= r.Raw.StatusCode
}
func (r *Response) Error() (*response.Error, error) {
	if !r.IsError() {
		return nil, errors.New("the response isn't an error")
	}
	if r.errCache != nil || r.readErr != nil {
		return r.errCache, r.readErr
	}
	res := struct {
		Error *response.Error `json:"error"`
	}{}
	if err := r.ReadJSON(&res); err != nil {
		return nil, err
	}
	if res.Error == nil {
		return nil, errors.New("invalid error response")
	}
	r.errCache = res.Error
	return r.errCache, nil
}
func (r *Response) ReadJSON(js interface{}) error {
	body, err := r.Body()
	if err != nil {
		return err
	}
	dec := json.NewDecoder(bytes.NewReader(body))
	dec.UseNumber()
	if err := dec.Decode(js); err != nil {
		r.readErr = err
		return err
	}
	return nil
}
func (r *Response) ReadStreamJSON() (<-chan interface{}, error) {
	if !r.IsStream() {
		return nil, errors.New("the response isn't a stream")
	}
	ch := make(chan interface{})
	r.closeStream = make(chan struct{})
	r.streamClosed = make(chan struct{})
	go func() {
		defer func() {
			close(ch)
			close(r.streamClosed)
		}()
		reader := bufio.NewReader(r.Raw.Body)
		nextLine := func() ([]byte, []byte, error) {
			line, err := reader.ReadBytes('\n')
			if err != nil {
				return nil, nil, err
			}
			nl := line
			line = line[:len(line)-1]  
			if l := len(line); l > 0 && line[l-1] == '\r' {
				line = line[:l-1]
				nl = nl[len(nl)-2:]
			} else {
				nl = nl[len(nl)-1:]
			}
			return line, nl, nil
		}
		boundary := append([]byte("--"), []byte(r.mimeParams["boundary"])...)
		isBoundaryLine := func(line []byte) (bool, bool) {
			if !bytes.HasPrefix(line, boundary) {
				return false, false
			}
			line = line[len(boundary):]
			isFinal := false
			if bytes.HasPrefix(line, []byte("--")) {
				isFinal = true
				line = line[2:]
			}
			for len(line) > 0 && (line[0] == ' ' || line[0] == '\t') {
				line = line[1:]
			}
			return len(line) == 0, isFinal
		}
		for {  
			if line, _, err := nextLine(); err != nil {
				if err == io.EOF {
					r.streamErr = io.ErrUnexpectedEOF
				} else {
					r.streamErr = err
				}
				return
			} else if b, final := isBoundaryLine(line); b {
				if final {
					return
				}
				break
			}
		}
		bodyBuf := make([]byte, 4096)
		for {  
			body := bodyBuf[:0]
			header := http.Header{}
			for {  
				line, _, err := nextLine()
				if err != nil {
					if err != io.EOF {
						r.streamErr = err
					}
					return
				}
				if len(line) == 0 {
					break
				}
				l := string(line)
				i := strings.Index(l, ": ")
				if i < 0 {
					continue
				}
				header.Set(l[:i], l[i+2:])
			}
			if ct := header.Get("Content-Type"); !strings.Contains(ct, "application/json") {
				r.streamErr = errors.New("the stream contains non-JSON contents")
				return
			}
			boundaryFound := false
			finalPart := false
			clStr := header.Get("Content-Length")
			if clStr != "" {
				cl, err := strconv.Atoi(clStr)
				if err != nil {
					r.streamErr = err
					return
				}
				if len(bodyBuf) < cl {
					bodyBuf = make([]byte, cl)
				}
				body = bodyBuf[:cl]
				if _, err := io.ReadFull(reader, body); err != nil {
					if err != io.EOF {
						r.streamErr = err
					}
					return
				}
			} else {
				var prevNL []byte
				for {
					line, nl, err := nextLine()
					if err != nil {
						if err != io.EOF {
							r.streamErr = err
						}
						return
					}
					if boundaryFound, finalPart = isBoundaryLine(line); boundaryFound {
						break
					}
					body = append(body, prevNL...)
					body = append(body, line...)
					prevNL = nl
				}
			}
			if len(bodyBuf) < len(body) {
				bodyBuf = body
			}
			var js interface{}
			if err := json.Unmarshal(body, &js); err != nil {
				r.streamErr = fmt.Errorf("cannot parse JSON: %v", err)
				return
			}
			select {
			case <-r.closeStream:
				return
			case ch <- js:
			}
			if !boundaryFound {
				for {
					line, _, err := nextLine()
					if err != nil {
						if err != io.EOF {
							r.streamErr = err
						}
						return
					}
					if boundaryFound, finalPart = isBoundaryLine(line); boundaryFound {
						break
					}
				}
			}
			if finalPart {
				return
			}
		}
	}()
	return ch, nil
}