protected function buildRequest(
        $method,
        $path,
        $data = null,
        array $headers = []
    ) {
        // Create basic request headers
        $host = "Host: {$this->options['host']}";
        if ($this->options['port'] != 80) {
            $host .= ":{$this->options['port']}";
        }
        $request = "$method $path HTTP/1.1\r\n$host\r\n";

        // Add basic auth if set
        if ($this->options['username']) {
            $request .= sprintf("Authorization: Basic %s\r\n",
                base64_encode($this->options['username'].':'.$this->options['password'])
            );
        }

        // Set keep-alive header, which helps to keep to connection
        // initialization costs low, especially when the database server is not
        // available in the locale net.
        $request .= 'Connection: '.($this->options['keep-alive'] ? 'Keep-Alive' : 'Close')."\r\n";

        if ($this->options['headers']) {
            $headers = array_merge($this->options['headers'], $headers);
        }
        if (!isset($headers['Content-Type'])) {
            $headers['Content-Type'] = 'application/json';
        }
        foreach ($headers as $key => $value) {
            if (is_bool($value) === true) {
                $value = ($value) ? 'true' : 'false';
            }
            $request .= $key.': '.$value."\r\n";
        }

        // Also add headers and request body if data should be sent to the
        // server. Otherwise just add the closing mark for the header section
        // of the request.
        if ($data !== null) {
            $request .= 'Content-Length: '.strlen($data)."\r\n\r\n";
            $request .= $data;
        } else {
            $request .= "\r\n";
        }

        return $request;
    }