@@ -141,6 +141,7 @@ void HTTPClient::clear()
141
141
_location.clear ();
142
142
_chunkHeader.clear ();
143
143
_chunkLen = 0 ;
144
+ _transferEncoding = HTTPC_TE_IDENTITY;
144
145
_payload.reset ();
145
146
}
146
147
@@ -1060,6 +1061,142 @@ String HTTPClient::errorToString(int error)
1060
1061
}
1061
1062
}
1062
1063
1064
+ /* *
1065
+ * write a byte to HTTP connection stream
1066
+ * @param b uint8_t byte to be written
1067
+ * @return number of bytes written
1068
+ */
1069
+ size_t HTTPClient::write (uint8_t b)
1070
+ {
1071
+ return write (&b, sizeof (b));
1072
+ }
1073
+
1074
+ /* *
1075
+ * write a byte array to HTTP connection stream
1076
+ * @param buffer uint8_t * byte array to be written
1077
+ * @param size size_t byte array size
1078
+ * @return number of bytes written
1079
+ */
1080
+ size_t HTTPClient::write (const uint8_t *buffer, size_t size)
1081
+ {
1082
+ if (!connected ()) {
1083
+ return 0 ;
1084
+ }
1085
+ if (_transferEncoding == HTTPC_TE_CHUNKED) {
1086
+ int written;
1087
+
1088
+ if (size == 0 ) {
1089
+ return size;
1090
+ }
1091
+ if ((_chunkLen != 0 ) && (_chunkOffset == _chunkLen)) {
1092
+ if (_client->write (" \r\n " ) == 2 ) {
1093
+ _chunkLen = 0 ;
1094
+ } else {
1095
+ return 0 ;
1096
+ }
1097
+ }
1098
+ if (_chunkLen == 0 ) {
1099
+ String header = String (size, 16 ) + " \r\n " ;
1100
+
1101
+ if (_client->write (header.c_str ()) != header.length ()) {
1102
+ return 0 ;
1103
+ }
1104
+ _chunkLen = size;
1105
+ _chunkOffset = 0 ;
1106
+ }
1107
+ if (size > _chunkLen - _chunkOffset) {
1108
+ size = _chunkLen - _chunkOffset;
1109
+ }
1110
+ written = _client->write (buffer, size);
1111
+ _chunkOffset += written;
1112
+ return written;
1113
+ }
1114
+ else {
1115
+ return _client->write (buffer, size);
1116
+ }
1117
+ }
1118
+
1119
+ /* *
1120
+ * retrieve number of bytes available to be read from HTTP connection stream
1121
+ * @return number of available bytes
1122
+ */
1123
+ int HTTPClient::available ()
1124
+ {
1125
+ if (!connected ()) {
1126
+ return 0 ;
1127
+ }
1128
+ if (_transferEncoding == HTTPC_TE_IDENTITY) {
1129
+ return _client->available ();
1130
+ } else if (_transferEncoding == HTTPC_TE_CHUNKED) {
1131
+ if ((_chunkLen == 0 ) && !readChunkHeader (false )) {
1132
+ return 0 ;
1133
+ }
1134
+ if (_chunkLen > 0 ) {
1135
+ if (_chunkOffset < _chunkLen) {
1136
+ unsigned int available = (unsigned int ) _client->available ();
1137
+ if (available < _chunkLen - _chunkOffset) {
1138
+ return available;
1139
+ } else {
1140
+ return (_chunkLen - _chunkOffset);
1141
+ }
1142
+ } else {
1143
+ readChunkTrailer (false );
1144
+ }
1145
+ }
1146
+ return 0 ;
1147
+ } else {
1148
+ return 0 ;
1149
+ }
1150
+ }
1151
+
1152
+ /* *
1153
+ * read a byte from HTTP connection stream
1154
+ * @return byte read, or -1 if no bytes could be read
1155
+ */
1156
+ int HTTPClient::read ()
1157
+ {
1158
+ if (!connected ()) {
1159
+ return -1 ;
1160
+ }
1161
+ if (_transferEncoding == HTTPC_TE_IDENTITY) {
1162
+ return _client->read ();
1163
+ } else if (_transferEncoding == HTTPC_TE_CHUNKED) {
1164
+ while (true ) {
1165
+ if ((_chunkLen == 0 ) && !readChunkHeader ()) {
1166
+ return -1 ;
1167
+ }
1168
+ if (_chunkLen > 0 ) {
1169
+ if (_chunkOffset < _chunkLen) {
1170
+ int c = _client->read ();
1171
+
1172
+ if (c >= 0 ) {
1173
+ _chunkOffset++;
1174
+ }
1175
+ return c;
1176
+ } else if (!readChunkTrailer ()) {
1177
+ return -1 ;
1178
+ }
1179
+ } else {
1180
+ return -1 ;
1181
+ }
1182
+ }
1183
+ } else {
1184
+ return -1 ;
1185
+ }
1186
+ }
1187
+
1188
+ /* *
1189
+ * retrieve next byte available to be read from HTTP connection stream
1190
+ * @return byte available to be read, or -1 if no bytes can be read
1191
+ */
1192
+ int HTTPClient::peek ()
1193
+ {
1194
+ if (!available ()) {
1195
+ return -1 ;
1196
+ }
1197
+ return _client->peek ();
1198
+ }
1199
+
1063
1200
/* *
1064
1201
* adds Header to the request
1065
1202
* @param name
@@ -1091,9 +1228,14 @@ void HTTPClient::addHeader(const String& name, const String& value, bool first,
1091
1228
headerLine += " \r\n " ;
1092
1229
if (first) {
1093
1230
_headers = headerLine + _headers;
1231
+ _transferEncoding = HTTPC_TE_IDENTITY;
1094
1232
} else {
1095
1233
_headers += headerLine;
1096
1234
}
1235
+ if (name.equalsIgnoreCase (F (" Transfer-Encoding" )) &&
1236
+ value.equalsIgnoreCase (F (" chunked" ))) {
1237
+ _transferEncoding = HTTPC_TE_CHUNKED;
1238
+ }
1097
1239
}
1098
1240
}
1099
1241
@@ -1269,6 +1411,27 @@ bool HTTPClient::sendHeader(const char * type)
1269
1411
return (_client->write ((const uint8_t *) header.c_str (), header.length ()) == header.length ());
1270
1412
}
1271
1413
1414
+ /* *
1415
+ * sends HTTP request header
1416
+ * @param type (GET, POST, ...)
1417
+ * @return status
1418
+ */
1419
+ bool HTTPClient::endRequest (void )
1420
+ {
1421
+ if (!connected ()) {
1422
+ return false ;
1423
+ }
1424
+ if (_transferEncoding == HTTPC_TE_CHUNKED) {
1425
+ if ((_chunkLen != 0 ) && (_client->write (" \r\n " ) != 2 )) {
1426
+ return false ;
1427
+ }
1428
+ return (_client->write (" 0\r\n\r\n " ) == 5 );
1429
+ }
1430
+ else {
1431
+ return true ;
1432
+ }
1433
+ }
1434
+
1272
1435
/* *
1273
1436
* reads the response from the server
1274
1437
* @return int http code
@@ -1286,7 +1449,6 @@ int HTTPClient::handleHeaderResponse()
1286
1449
1287
1450
String transferEncoding;
1288
1451
1289
- _transferEncoding = HTTPC_TE_IDENTITY;
1290
1452
unsigned long lastDataTime = millis ();
1291
1453
1292
1454
while (connected ()) {
@@ -1514,6 +1676,7 @@ bool HTTPClient::readChunkHeader(bool blocking)
1514
1676
_chunkLen = (uint32_t ) strtol ((const char *) _chunkHeader.c_str (), NULL ,
1515
1677
16 );
1516
1678
1679
+ _chunkOffset = 0 ;
1517
1680
return true ;
1518
1681
}
1519
1682
0 commit comments