Request's Body Standard Transfer
The POST and PUT methods can be used to transfer data to the HTTP server. The data is included in the body part of the HTTP request.
Additional HTTP header fields must be included when a body is present. The content type of the data must be specified with the Content-Type header field and for a standard transfer the length of the data must be specified with the Content-Length header field. Those headers will be added automatically by the µC/HTTP-client stack after the required parameters are configured.
The function HTTPc_ReqSetParam must be used to configure the additional parameters necessary when data must be transmitted the standard way. Three parameters must be set up :
HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_TYPE
HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_LEN
HTTPc_PARAM_TYPE_REQ_BODY_HOOK
The first parameter is to set the content-type of the data, the second the length of the data and the third is to set the hook function that will be used by the µC/HTTP-client stack to retrieve the data.
Example
Since all the API function are in blocking mode in the example bellow, the HTTPc objects and string can be allocated on the application stack without problems.
The example below implements a function to send a PUT request :
- An HTTP Connection is set up
- An HTTP request is configured with the three body parameters : content-type, content-length and hook function.
- The Connection is open.
- The request is sent.
CPU_CHAR index_html[1024]; /* ********************************************************************************************************* * HTTPcEx_ReqSendPUT_Standard() * * Description : Example function to send a HTTP PUT request with the standard transfer (not chunked). * * Argument(s) : none. * * Return(s) : DEF_YES, is request sent successfully. * DEF_NO, otherwise. ********************************************************************************************************* */ CPU_BOOLEAN HTTPcEx_ReqSendPUT_Standard (void) { HTTPc_CONN_OBJ conn; HTTPc_REQ_OBJ req; HTTPc_RESP_OBJ resp; CPU_CHAR buf[512]; HTTPc_FLAGS flags; HTTP_CONTENT_TYPE content_type; CPU_SIZE_T content_len; CPU_SIZE_T str_len; CPU_BOOLEAN result; HTTPc_ERR err; /* ---------------- INIT NEW CONNECTION --------------- */ HTTPc_ConnClr(&conn, &err); if (err != HTTPc_ERR_NONE) { return (DEF_FAIL); } /* -------------- SET CONNECTION PARAM ---------------- */ #if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED) HTTPc_ConnSetParam(&conn, HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK, &HTTPcEx_ConnCloseCallback, &err); if (err != HTTPc_ERR_NONE) { return (DEF_FAIL); } #endif /* ------------------ INIT NEW REQUEST----------------- */ HTTPc_ReqClr(&req, &err); if (err != HTTPc_ERR_NONE) { return (DEF_FAIL); } /* ----------- SET REQUEST BODY PARAMETERS ------------ */ content_type = HTTP_CONTENT_TYPE_HTML; HTTPc_ReqSetParam(&req, HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_TYPE, &content_type, &err); if (err != HTTPc_ERR_NONE) { return (DEF_FAIL); } content_len = STATIC_INDEX_HTML_LEN; HTTPc_ReqSetParam(&req, HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_LEN, &content_len, &err); if (err != HTTPc_ERR_NONE) { return (DEF_FAIL); } HTTPc_ReqSetParam(&req, HTTPc_PARAM_TYPE_REQ_BODY_HOOK, &HTTPcEx_ReqBodyHook, &err); if (err != HTTPc_ERR_NONE) { return (DEF_FAIL); } /* ------------ SET TRANSACTION CALLBACKS ------------ */ #if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED) HTTPc_ReqSetParam(&req, HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK, &HTTPcEx_TransErrCallback, &err); if (err != HTTPc_ERR_NONE) { return (DEF_FAIL); } #endif /* ----------------- OPEN CONNECTION ------------------ */ str_len = Str_Len("www.example.com"); flags = HTTPc_FLAG_NONE; result = HTTPc_ConnOpen(&conn, &buf, APP_HTTPc_CFG_BUF_SIZE, "www.example.com", str_len, flags, &err); if (err != HTTPc_ERR_NONE) { return (DEF_FAIL); } if (result != DEF_OK) { return (DEF_FAIL); } /* ---------------- SEND HTTP REQUEST ----------------- */ str_len = Str_Len("/index.html"); flags = HTTPc_FLAG_NONE; result = HTTPc_ReqSend(&conn, &req, &resp, HTTP_METHOD_PUT, "/index.html", str_len, flags, &err); if (err != HTTPc_ERR_NONE) { return (DEF_FAIL); } return (DEF_OK); }
The below example is a first implementation of the hook function to retrieve the request body data from the application. In this example, the data is retrieved from an existing application buffer (index_html) and the hook function only set up the data pointer and the length of the data.
/* ********************************************************************************************************* * HTTPcEx_ReqBodyHook() * * Description : Example Hook function to transfer data in request with the standard transfer. * * This function let you the choice to set the pointer to the application data (with p_data) * that the µC/HTTP-client stack will take care of transferring; or to directly copy the data * in the HTTP transmit buffer (with p_buf). * * Argument(s) : p_conn Pointer to the current HTTPc Connection object. * * p_req Pointer to the current HTTPc Request object. * * p_data Pointer to the application data. * * p_buf Pointer to the HTTP buffer. * * buf_len Buffer's length. * * p_data_len Variable that will return the data length passed by the application. * * Return(s) : DEF_YES, if all data as been passed. * DEF_NO, if data still remaining to be passed by the application. ********************************************************************************************************* */ static CPU_BOOLEAN HTTPcEx_ReqBodyHook (HTTPc_CONN_OBJ *p_conn, HTTPc_REQ_OBJ *p_req, void **p_data, CPU_CHAR *p_buf, CPU_INT16U buf_len, CPU_INT16U *p_data_len) { CPU_INT16U size; CPU_INT16U str_len; *p_data = &index_html[0]; str_len = Str_Len(&index_html[0]); Str_Copy_N(p_buf, &index_html[0], str_len); *p_data_len = str_len; return (DEF_YES); }
The below example is a second implementation of the hook function to retrieve the request body data from the application. In this example, the data is retrieved from a file located in a File System (µC/FS is used in this example) and directly copied into the HTTP transmit buffer.
/* ********************************************************************************************************* * HTTPcEx_ReqBodyHook() * * Description : Example Hook function to transfer data in request with the standard transfer. * * This function let you the choice to set the pointer to the application data (with p_data) * that the µC/HTTP-client stack will take care of transferring; or to directly copy the data * in the HTTP transmit buffer (with p_buf). * * Argument(s) : p_conn Pointer to the current HTTPc Connection object. * * p_req Pointer to the current HTTPc Request object. * * p_data Pointer to the application data. * * p_buf Pointer to the HTTP buffer. * * buf_len Buffer's length. * * p_data_len Variable that will return the data length passed by the application. * * Return(s) : DEF_YES, if all data as been passed. * DEF_NO, if data still remaining to be passed by the application. ********************************************************************************************************* */ static CPU_BOOLEAN HTTPcEx_ReqBodyHook (HTTPc_CONN_OBJ *p_conn, HTTPc_REQ_OBJ *p_req, void **p_data, CPU_CHAR *p_buf, CPU_INT16U buf_len, CPU_INT16U *p_data_len) { FS_FILE *p_file; FS_FLAGS fs_flags; CPU_SIZE_T file_rem; CPU_SIZE_T size; CPU_SIZE_T size_rd; CPU_BOOLEAN is_open; CPU_BOOLEAN finish; FS_ERR err_fs; *p_data = DEF_NULL; is_open = FSFile_IsOpen("index.html", &fs_flags, &err_fs); if (err_fs != FS_ERR_NONE) { *p_len_wr = 0; finish = DEF_YES; goto exit; } if (is_open == DEF_NO) { fs_flags = 0; DEF_BIT_SET(fs_flags, FS_FILE_ACCESS_MODE_RD); DEF_BIT_SET(fs_flags, FS_FILE_ACCESS_MODE_CREATE); p_file = FSFile_Open("index.html", fs_flags, &err_fs); if (err_fs != FS_ERR_NONE) { *p_len_wr = 0; finish = DEF_YES; goto exit; } p_req->UserDataPtr = (void *)p_file; } else { p_file = (FS_FILE *)p_req->UserDataPtr; } file_rem = p_file->Size - p_file->Pos; if (file_rem <= 0) { *p_len_wr = 0; finish = DEF_YES; goto exit_close; } size = DEF_MIN(file_rem, buf_len); size_rd = FSFile_Rd(p_file, p_buf, size, &err_fs); if (err_fs != FS_ERR_NONE) { *p_len_wr = 0; finish = DEF_YES; goto exit_close; } *p_len_wr = size_rd; finish = DEF_NO; exit_close: FSFile_Close(p_file, &err_fs); exit: return (finish); }