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 :

  1.  An HTTP Connection is set up
  2. An HTTP request is configured with the three body parameters : content-type, content-length and hook function.
  3. The Connection is open.
  4. The request is sent.
Listing - Standard Body Transfer Function Example Code
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.

Listing - Request Body Hook Function Example Code #1
/*
*********************************************************************************************************
*                                      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. 

Listing - Request Body Hook Function Example Code #2
/*
*********************************************************************************************************
*                                      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);
}