Add chunked mode to http connections

This commit is contained in:
Tobias Blomberg 2020-07-20 14:38:24 +02:00
parent 7e28a99362
commit 2ab1abccba
4 changed files with 63 additions and 8 deletions

View File

@ -21,6 +21,8 @@
* Add a signal to the Config class so that one can subscribe to changes in the
configuration.
* Chunked mode added to the Async::HttpServerConnection.
1.6.0 -- 01 Sep 2019

View File

@ -24,8 +24,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\endverbatim
*/
/****************************************************************************
*
* System Includes
@ -35,6 +33,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <cstring>
#include <cerrno>
#include <sstream>
#include <cassert>
/****************************************************************************
@ -114,7 +113,8 @@ using namespace Async;
****************************************************************************/
HttpServerConnection::HttpServerConnection(size_t recv_buf_len)
: TcpConnection(recv_buf_len), m_state(STATE_DISCONNECTED)
: TcpConnection(recv_buf_len), m_state(STATE_DISCONNECTED),
m_chunked(false)
{
TcpConnection::sendBufferFull.connect(
sigc::mem_fun(*this, &HttpServerConnection::onSendBufferFull));
@ -125,7 +125,7 @@ HttpServerConnection::HttpServerConnection(
int sock, const IpAddress& remote_addr, uint16_t remote_port,
size_t recv_buf_len)
: TcpConnection(sock, remote_addr, remote_port, recv_buf_len),
m_state(STATE_EXPECT_START_LINE)
m_state(STATE_EXPECT_START_LINE), m_chunked(false)
{
} /* HttpServerConnection::HttpServerConnection */
@ -193,6 +193,10 @@ bool HttpServerConnection::write(const Response& res)
{
os << (*it).first << ": " << (*it).second << "\r\n";
}
if (m_chunked)
{
os << "Transfer-encoding: chunked\r\n";
}
os << "\r\n";
if (res.sendContent())
{
@ -200,8 +204,32 @@ bool HttpServerConnection::write(const Response& res)
}
//std::cout << "### HttpServerConnection::write:" << std::endl;
//std::cout << os.str() << std::endl;
int len = TcpConnection::write(os.str().c_str(), os.str().size());
return len == static_cast<int>(os.str().size());
int len = os.str().size();
return TcpConnection::write(os.str().c_str(), len) == len;
} /* HttpServerConnection::write */
bool HttpServerConnection::write(const char* buf, int len)
{
assert(len >= 0);
int ret = -1;
if (m_chunked)
{
std::ostringstream os;
//os << hex << len << ";tg=240;talker=SM0SVX\r\n";
os << hex << len << "\r\n";
ret = TcpConnection::write(os.str().c_str(), os.str().size());
ret += TcpConnection::write(buf, len);
ret += TcpConnection::write("\r\n", 2);
len += os.str().size() + 2;
}
else
{
ret = TcpConnection::write(buf, len);
}
return ret == len;
} /* HttpServerConnection::write */
@ -412,6 +440,8 @@ const char* HttpServerConnection::codeToString(unsigned code)
return "OK";
case 404:
return "Not Found";
case 406:
return "Not Acceptable";
case 501:
return "Not Implemented";
default:

View File

@ -156,7 +156,7 @@ class HttpServerConnection : public TcpConnection
class Response
{
public:
Response(void) : m_code(0), m_send_content(true) {}
Response(void) : m_code(0), m_send_content(false) {}
unsigned code(void) const { return m_code; }
void setCode(unsigned code) { m_code = code; }
@ -177,6 +177,7 @@ class HttpServerConnection : public TcpConnection
m_content = content;
setHeader("Content-type", content_type);
setHeader("Content-length", m_content.size());
setSendContent(true);
}
bool sendContent(void) const { return m_send_content; }
void setSendContent(bool send_content)
@ -229,6 +230,15 @@ class HttpServerConnection : public TcpConnection
*/
virtual void disconnect(void);
/**
* @brief Send data with chunked transfer encoding
*
* Calling this function will enable data to be sent in chunks. The
* "Transfer-encoding: chunked" will be set in the header and each call to
* write() will send a chunk.
*/
void setChunked(void) { m_chunked = true; }
/**
* @brief Send a HTTP response
* @param res The response (@see Response)
@ -236,6 +246,18 @@ class HttpServerConnection : public TcpConnection
*/
virtual bool write(const Response& res);
/**
* @brief Write data to the socket
* @param buf The buffer containing the data to write
* @param len Then length of the data in the buffer
* @return Return \em true on success or else \em false
*
* If chunked mode has been set a chunked header and trailer will be added
* to the data. If not in chunked mode, the raw buffer will be sent without
* modification.
*/
virtual bool write(const char* buf, int len);
/**
* @brief A signal that is emitted when a connection has been terminated
* @param con The connection object
@ -309,6 +331,7 @@ class HttpServerConnection : public TcpConnection
State m_state;
std::string m_row;
Request m_req;
bool m_chunked;
HttpServerConnection(const HttpServerConnection&);
HttpServerConnection& operator=(const HttpServerConnection&);

View File

@ -8,7 +8,7 @@ QTEL=1.2.4
LIBECHOLIB=1.3.3
# Version for the Async library
LIBASYNC=1.6.0.99.4
LIBASYNC=1.6.0.99.5
# SvxLink versions
SVXLINK=1.7.99.22