1

I'm facing some issues trying to get my body content in my monkey server. In fact, I don't really know how to access my data using fastcgi library functions.

I'm sending with Postman a PUT request on http://my.server.address:myport/cgi/something with the following JSON content:

{ "hello" : "bonjour" }

On the server side
running on the main thread :

int32_t SWEB_traiter_requette_f(int32_t i32_socket_listen) {
    FCGX_Request st_request;

    (void)FCGX_InitRequest(&st_request, i32_socket_listen, 0);

    if (FCGX_Accept_r(&st_request) == 0) {

        ULOG_log_f(ULOG_PRIO_INFO, "accepting request");
        (void)pthread_mutex_lock(gpu_mutex_s_web);
        traiter_requette_s_web_f(&st_request,FCGX_GetParam("REQUEST_URI", st_request.envp));
        (void)pthread_mutex_unlock(gpu_mutex_s_web);


        (void)FCGX_Finish_r(&st_request);
    }
    FCGX_Free(&st_request,i32_socket_listen);

    return 0;
}

And this is how I handle the request :

static void traiter_requette_s_web_f(FCGX_Request *pst_request,const char * pc_url) {
    size_t z_len;
    char_t *pc_data;
    int i = 0;
    int ch;
    char_t *sz_content_len = FCGX_GetParam("CONTENT_LENGTH" , pst_request->envp);
    char_t *sz_method      = FCGX_GetParam("REQUEST_METHOD" , pst_request->envp);
    char_t *sz_contenttype = FCGX_GetParam("CONTENT_TYPE"   , pst_request->envp);

    if (sz_contenttype != NULL){

        /* first method ..... not working */
        ch = FCGX_GetChar(pst_request->in);
        while(ch != -1){
            i++;
            z_len = strtol(sz_content_len, NULL, 10);
            pc_data = calloc(1,z_len+1);
            if (pc_data == NULL){
                //LCOV_EXCL_START
                ULOG_log_f(ULOG_PRIO_ERREUR, "Erreur d'allocation de psz_data");
                return;
                //LCOV_EXCL_STOP
            }
            pc_data[i-1] = (char_t) ch;
            ch = FCGX_GetChar(pst_request->in);
            if (ch == -1 )
            {
                pc_data=(char*)realloc(pc_data,(i + 1)*sizeof(char));
                pc_data[i] = '\0';
            }

        }
        printf("data !! : %s\n",pc_data);
        /* second method .... not working */

        z_len = strtol(sz_content_len, NULL, 10);
        pc_data = calloc(1,z_len+1);
        if (pc_data == NULL){
            //LCOV_EXCL_START
            ULOG_log_f(ULOG_PRIO_ERREUR, "Erreur d'allocation de psz_data");
            return;
            //LCOV_EXCL_STOP
        }
        (void)FCGX_GetStr(pc_data,z_len,pst_request->in);
        printf("data !! : %s\n",pc_data);   

    }
}

Maybe I'm doing something wrong with pc_data and this is not how to access the body.

How can I access the body of my request?

IAmInPLS
  • 4,051
  • 4
  • 24
  • 57
kidz55
  • 333
  • 4
  • 26
  • `... ,FCGX_GetParam("REQUEST_URI", st_request.envp) ...` :: what is `st_request.envp` , a pointer ? – joop Jun 01 '17 at 09:02
  • In general the PUT and POST data comes via stdin, so you have to access that. But sure this monkey library gives an access to it. – Ho Zong Jun 01 '17 at 09:03
  • `while(ch != -1){ i++; z_len = strtol(sz_content_len, NULL, 10); pc_data = calloc(1,z_len+1);` it looks you are on a `( ch != EOF)` loop here. Calling calloc for every character looks like a memory leak to me. And calculating the `content_length` again for every character doesn't seem right, too. – joop Jun 01 '17 at 09:19
  • thanks @joop !! you found the mistake in my code , now it's working correctly – kidz55 Jun 01 '17 at 09:29
  • @downvoter: Best thing to do when downvoting is giving a reason, which could help to improve the original post. – IAmInPLS Jun 01 '17 at 13:27

3 Answers3

0

It seems that my code was leaking.
This is how you get the body content on a POST request :

static void traiter_requette_s_web_f(FCGX_Request *pst_request,const char * pc_url) {
    size_t z_len;

    int i = 0;
    int ch;
    char_t *sz_content_len = FCGX_GetParam("CONTENT_LENGTH" , pst_request->envp);
    char_t *sz_method      = FCGX_GetParam("REQUEST_METHOD" , pst_request->envp);
    char_t *sz_contenttype = FCGX_GetParam("CONTENT_TYPE"   , pst_request->envp);
    char_t *pc_data = FCGX_GetParam("REQUEST_URI", pst_request->envp);

    if (sz_contenttype != NULL)
    {

        z_len = strtol(sz_content_len, NULL, 10);
        pc_data = calloc(1,z_len+1);
        if (pc_data == NULL){
            return;
        }
        ch = FCGX_GetChar(pst_request->in);
        while(ch != -1){
            i++;
            pc_data[i-1] = (char_t) ch;
            ch = FCGX_GetChar(pst_request->in);
            if (ch == -1 )
            {
                pc_data=(char*)realloc(pc_data,(i + 1)*sizeof(char));
                pc_data[i] = '\0';
            }

        }           
        printf("data !! : %s\n",pc_data);   
    }
}
kidz55
  • 333
  • 4
  • 26
  • 1
    Sanitize your loop. The code above can be tortured to death by a client that sends more bytes than the specified content_length. So your loop should at leas contain a test somewhere for `i < z_len` . – joop Jun 01 '17 at 09:39
0

According to https://fossies.org/dox/FCGI-0.78/ you can read body content on a POST request

#define DATA_READ_CHUNK 81912

void read_payload(size_t content_length, std::string&str) {
    size_t read_length = 0;
    size_t len = 0;
    //DATA_READ_CHUNK should be 8192 according to FCGX_Accept_r(FCGX_Request *reqDataPtr) line 2154 file fcgiapp.c
    while (true) {
        char* buff;
        if (content_length > DATA_READ_CHUNK) {
            buff = (char*)malloc(DATA_READ_CHUNK + 1);
            len = DATA_READ_CHUNK;
        }
        else {
            buff = (char*)malloc(content_length + 1);
            len = content_length;
        }
        buff[len] = '\0';
        std::cin.read(buff, len);
        str.append(buff, len);
        free(buff);
        content_length -= len;
        if (content_length <= 0)break;
    }
    fclose(stdin);
}
Rajib Chy
  • 800
  • 10
  • 22
0

I would like to add a more modern C++ version

std::string f_request_content;
size_t f_request_length = <from the env variable called CONTENT_LENGTH>;
if (f_request_method == "POST")
{
  int ch = FCGX_GetChar (m_request.in);
  while (ch != -1)
  {
    f_request_content.push_back ((char16_t) ch);
    if (f_request_content.length() >= f_request_length)
      break;
    ch = FCGX_GetChar (m_request.in);
  }
}
Alexander
  • 1
  • 1