implemented handle of unlimited size of dynamic variable expand;

fixed problem appeared when dynamic variable split into two chunk of
data
This commit is contained in:
Bogdan Pilyugin 2022-10-29 14:11:07 +02:00
parent 7a46c36156
commit 0f386c35d0

View File

@ -220,8 +220,8 @@ static esp_err_t POSTHandler(httpd_req_t *req)
httpd_resp_set_hdr(req, "Location", filename); httpd_resp_set_hdr(req, "Location", filename);
httpd_resp_send(req, NULL, 0); // Response body can be empty httpd_resp_send(req, NULL, 0); // Response body can be empty
#if HTTP_SERVER_DEBUG_LEVEL > 0 #if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Redirect request from POST"); ESP_LOGI(TAG, "Redirect request from POST");
#endif #endif
return ESP_OK; return ESP_OK;
} }
@ -251,9 +251,8 @@ static esp_err_t GETHandler(httpd_req_t *req)
espfs_file_t *file; espfs_file_t *file;
struct espfs_stat_t stat; struct espfs_stat_t stat;
bool isDynamicVars = false; bool isDynamicVars = false;
uint32_t fileSize; //length of file in bytes uint32_t bufSize; //size of ram buffer for chunk of data, read from file
uint32_t bufSize; uint32_t readBytes; //number of bytes, read from file. used for information only
uint32_t readBytes; //number of bytes, already read from file
const char *filename = get_path_from_uri(filepath, const char *filename = get_path_from_uri(filepath,
((struct file_server_data*) req->user_ctx)->base_path, ((struct file_server_data*) req->user_ctx)->base_path,
@ -308,8 +307,7 @@ static esp_err_t GETHandler(httpd_req_t *req)
/* Retrieve the pointer to scratch buffer for temporary storage */ /* Retrieve the pointer to scratch buffer for temporary storage */
char *chunk = ((struct file_server_data*) req->user_ctx)->scratch; char *chunk = ((struct file_server_data*) req->user_ctx)->scratch;
fileSize = stat.size; bufSize = MIN(stat.size, SCRATCH_BUFSIZE - MAX_DYNVAR_LENGTH);
bufSize = MIN(fileSize, SCRATCH_BUFSIZE - MAX_DYNVAR_LENGTH); //
readBytes = 0; readBytes = 0;
//allocate buffer for file data //allocate buffer for file data
char *buf = (char*) malloc(bufSize); char *buf = (char*) malloc(bufSize);
@ -334,12 +332,11 @@ static esp_err_t GETHandler(httpd_req_t *req)
if (IS_FILE_EXT(filename, ".html") || IS_FILE_EXT(filename, ".json")) if (IS_FILE_EXT(filename, ".html") || IS_FILE_EXT(filename, ".json"))
isDynamicVars = true; isDynamicVars = true;
bool transfComplete = false;
do do
{ {
int pt = 0; int pt = 0;
int prcdBytes = 0; int preparedBytes = 0;
while (pt < bufSize && prcdBytes < (SCRATCH_BUFSIZE)) while (pt < bufSize)
{ {
if (buf[pt] == '~' && isDynamicVars) //open tag if (buf[pt] == '~' && isDynamicVars) //open tag
{ {
@ -353,9 +350,7 @@ static esp_err_t GETHandler(httpd_req_t *req)
if (buf[++pt] != '~') if (buf[++pt] != '~')
DynVarName[k++] = buf[pt]; //continue extract variable name from buf DynVarName[k++] = buf[pt]; //continue extract variable name from buf
else else
{
break; //found close tag break; //found close tag
}
} }
else //need read more characters directly from file else //need read more characters directly from file
{ {
@ -367,68 +362,80 @@ static esp_err_t GETHandler(httpd_req_t *req)
else else
break; //found close tag break; //found close tag
} }
else // end of file else
{ //unexpected end of file
break; //error end of file goto file_send_error;
}
} }
} }
if (buf[pt] == '~' || ch == '~') //close tag, got valid dynamic variable name if (buf[pt] == '~' || ch == '~') //close tag, got valid dynamic variable name
{ {
DynVarName[k] = 0x00; DynVarName[k] = 0x00;
prcdBytes += HTTPPrint(req, &chunk[prcdBytes], DynVarName); preparedBytes += HTTPPrint(req, &chunk[preparedBytes], DynVarName);
pt++;
}
else //not found close tag, exit by overflow max variable size or file end
{
//skip close '~' in buf or directly in file
if (ch == '~')
espfs_fread(file, &ch, 1);
else
pt++;
} }
else
//not found close tag, exit by overflow max variable size or file end
goto file_send_error;
} }
else else
chunk[prcdBytes++] = buf[pt++]; //ordinary character chunk[preparedBytes++] = buf[pt++]; //write to chunk ordinary character
}
if (prcdBytes != 0) //check if scratch buffer is full and need send chunk
{ if (preparedBytes >= (SCRATCH_BUFSIZE - MAX_DYNVAR_LENGTH))
/* Send the buffer contents as HTTP response chunk */
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Write to HTTPserv resp %d", prcdBytes);
#endif
if (httpd_resp_send_chunk(req, chunk, prcdBytes) != ESP_OK)
{ {
ESP_LOGE(TAG, "File sending failed!"); #if HTTP_SERVER_DEBUG_LEVEL > 0
/* Abort sending file */ ESP_LOGI(TAG, "Write to HTTPserv resp %d", preparedBytes);
httpd_resp_sendstr_chunk(req, NULL); #endif
/* Respond with 500 Internal Server Error */ if (httpd_resp_send_chunk(req, chunk, preparedBytes) != ESP_OK)
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, goto file_send_error;
"Failed to send file"); preparedBytes = 0;
free(buf);
espfs_fclose(file);
return ESP_FAIL;
} }
} }
/* Keep looping till the whole file is sent */
int nextPortion;
if((nextPortion = espfs_fread(file, buf, bufSize)))
{
bufSize = nextPortion;
readBytes += nextPortion;
}
else
transfComplete = true;
}
while (!transfComplete);
/* Close file after sending complete */ //data in buffer is finished and not void, need send chunk
espfs_fclose(file); if (preparedBytes)
{
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Write to HTTPserv resp %d", preparedBytes);
#endif
if (httpd_resp_send_chunk(req, chunk, preparedBytes) != ESP_OK)
goto file_send_error;
}
//try to read next part of data from file
bufSize = espfs_fread(file, buf, bufSize);
readBytes += bufSize;
}
while (bufSize > 0);
#if HTTP_SERVER_DEBUG_LEVEL > 0 #if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "File sending complete, read from file %d", readBytes); ESP_LOGI(TAG, "File sending complete, read from file %d", readBytes);
#endif #endif
/* Respond with an empty chunk to signal HTTP response completion */ /* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_send_chunk(req, NULL, 0); httpd_resp_send_chunk(req, NULL, 0);
free(buf); free(buf);
espfs_fclose(file);
return ESP_OK; return ESP_OK;
file_send_error:
ESP_LOGE(TAG, "File sending failed!");
/* Abort sending file */
httpd_resp_sendstr_chunk(req, NULL);
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR,
"Failed to send file");
free(buf);
espfs_fclose(file);
return ESP_FAIL;
} }
static httpd_handle_t start_webserver(void) static httpd_handle_t start_webserver(void)