@@ -13,16 +13,14 @@ HTTPResponse::HTTPResponse(ConnectionContext * con):
1313 _statusText = " OK" ;
1414 _headerWritten = false ;
1515 _isError = false ;
16+ _setLength = 0 ;
17+ _sentBytesCount = 0 ;
1618
1719 _responseCacheSize = con->getCacheSize ();
1820 _responseCachePointer = 0 ;
19- if (_responseCacheSize > 0 ) {
20- HTTPS_LOGD (" Creating buffered response, size: %d" , _responseCacheSize);
21- _responseCache = new byte[_responseCacheSize];
22- } else {
23- HTTPS_LOGD (" Creating non-buffered response" );
24- _responseCache = NULL ;
25- }
21+ _responseCache = NULL ;
22+ // Don't create buffer response just yet,
23+ // wait and see if we receive Content-Length ...
2624}
2725
2826HTTPResponse::~HTTPResponse () {
@@ -48,8 +46,26 @@ std::string HTTPResponse::getStatusText() {
4846 return _statusText;
4947}
5048
49+ void HTTPResponse::setContentLength (size_t size) {
50+ if (isHeaderWritten ()) {
51+ HTTPS_LOGE (" Setting Content-Lenght after headers sent!" );
52+ error ();
53+ return ;
54+ }
55+ if ((_setLength > 0 ) && (size != _setLength)) {
56+ HTTPS_LOGW (" Setting Content-Lenght more than once!" );
57+ }
58+ HTTPS_LOGD (" Set Content-Lenght: %d" , size);
59+ _setLength = size;
60+ }
61+
5162void HTTPResponse::setHeader (std::string const &name, std::string const &value) {
5263 _headers.set (new HTTPHeader (name, value));
64+ // Watch for "Content-Length" header
65+ if (name.compare (" Content-Length" ) == 0 ) {
66+ setContentLength (parseUInt (value));
67+ return ;
68+ }
5369}
5470
5571bool HTTPResponse::isHeaderWritten () {
@@ -60,6 +76,14 @@ bool HTTPResponse::isResponseBuffered() {
6076 return _responseCache != NULL ;
6177}
6278
79+ bool HTTPResponse::correctContentLength () {
80+ if (_setLength > 0 ) {
81+ if (_sentBytesCount == _setLength) return true ;
82+ HTTPS_LOGE (" Content-Lenght (%u) and data sent (%u) mismatch!" , _setLength, _sentBytesCount);
83+ }
84+ return false ;
85+ }
86+
6387void HTTPResponse::finalize () {
6488 if (isResponseBuffered ()) {
6589 drainBuffer ();
@@ -77,6 +101,22 @@ void HTTPResponse::printStd(const std::string &str) {
77101 * Writes bytes to the response. May be called several times.
78102 */
79103size_t HTTPResponse::write (const uint8_t *buffer, size_t size) {
104+ if (_sentBytesCount < 1 ) {
105+ if (_setLength > 0 ) {
106+ HTTPS_LOGD (" Streaming response directly, size: %d" , _setLength);
107+ } else if (size > 0 ) {
108+ // Try buffering
109+ if (_responseCacheSize > 0 ) {
110+ _responseCache = new byte[_responseCacheSize];
111+ HTTPS_LOGD (" Content-Length not set. Creating buffered response, size: %d" , _responseCacheSize);
112+ } else {
113+ // We'll have to tear down the connection to signal end of data
114+ setHeader (" Connection" , " close" );
115+ HTTPS_LOGD (" Content-Length not set. Creating non-buffered response" );
116+ }
117+ }
118+ }
119+ _sentBytesCount += size;
80120 if (!isResponseBuffered ()) {
81121 printHeader ();
82122 }
@@ -87,11 +127,8 @@ size_t HTTPResponse::write(const uint8_t *buffer, size_t size) {
87127 * Writes a single byte to the response.
88128 */
89129size_t HTTPResponse::write (uint8_t b) {
90- if (!isResponseBuffered ()) {
91- printHeader ();
92- }
93130 byte ba[] = {b};
94- return writeBytesInternal (ba, 1 );
131+ return write (ba, 1 );
95132}
96133
97134/* *
@@ -168,8 +205,8 @@ void HTTPResponse::drainBuffer(bool onOverflow) {
168205 HTTPS_LOGD (" Draining response buffer" );
169206 // Check for 0 as it may be an overflow reaction without any data that has been written earlier
170207 if (_responseCachePointer > 0 ) {
171- // FIXME: Return value?
172- _con->writeBuffer ((byte*)_responseCache, _responseCachePointer);
208+ _setLength = _responseCachePointer;
209+ _sentBytesCount = _con->writeBuffer ((byte*)_responseCache, _responseCachePointer);
173210 }
174211 delete[] _responseCache;
175212 _responseCache = NULL ;
0 commit comments