This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to make http post. No libcurl?

Hi, all!

Have nRF9160. 

I'm using http sample as template to make http requests get/post. I send it without any lib to build requests. 
I can't attach libcurl to nRF9160, and as I understand it is now impossible to using libcurl on nRF9160. 

Maybe someone can suggest something to making http requests?

  • Hi,

    I'm not sure if it's possible to port libcurl to nRF9160, but you can use the socket API to make HTTP requests. A colleague has made a HTTP example using the Socket API that's available here: https://github.com/Rallare/fw-nrfconnect-nrf/tree/nrf9160_samples/samples/nrf9160/http. This sample demonstrates how you can send a GET request. For POST requests you can use the following template along with snprintf/sprintf.

    #define HTTP_HOST example.com
    #define HTTP_PATH <post url>
    #define TEST_STRING = "Hello from nrf91"
    
    #define POST_TEMPLATE "POST %s? HTTP/1.1\r\n"\
    		"Host: %s\r\n"\
    		"Connection: keep-alive\r\n"\
    		"Content-Type: text/plain\r\n"\
    		"Content-length: %d\r\n\r\n"\
    		"%s"
    
    /*Prepare POST request*/
    send_data_len = snprintf(send_buf,
    				         500, /*total length should not exceed MTU size*/
    				         POST_TEMPLATE, HTTP_PATH,
    				         HTTP_HOST, strlen(TEST_STRING),
    				         TEST_STRING);
    
    /*Send post request*/
    blocking_send(client_fd, send_buf, send_data_len, 0);

    Edit: defined TEST_STRING 

  • Vidar,

    I'm trying you approach that seams very logical to me but somehow my call does not reach the database.

    I will have to cover up some aspects but I know that that side of the story is simply operational: the server is there and accepts POST REST calls of this organisation (SIGFOX is using this port to send my data to me)

    I just want to avoid someone to start jamming my port for fun.

    I did set up the connection parameters, using the right url and port 443.

    Set up a template to generate the POST code:

    #define POST_TEMPLATE "POST %s HTTP/1.1\r\nHost: %s\r\naccept-encoding: gzip, deflate \r\nConnection: keep-alive\r\nAccept: \*/\* \r\nContent-Type: application/json\r\nContent-length: %d\r\ncache-control: no-cache\r\n%s"

    which results in:

    POST /REST/MCS1608 HTTP/1.1
    Host: xxxxx.xxx
    accept-encoding: gzip, deflate
    Connection: keep-alive
    Accept: */*
    Content-Type: application/json
    Content-length: 79
    cache-control: no-cache
    {"device": "D2078B","timestamp":"1563365148","data":"a318e451a084f800f9004e0d"}

    Next I created a function:

    void app_http_post(void){
    	struct sockaddr_in local_addr;
    	struct addrinfo *res;
    	local_addr.sin_family = AF_INET;
    	local_addr.sin_port = htons(0);
    	local_addr.sin_addr.s_addr = 0;
    
    	printk("HTTP POST example\n\r");
    
    	int err = getaddrinfo(HTTP_HOST, NULL, NULL, &res);
    
    	printk("getaddrinfo err: %d\n\r", err);
    	((struct sockaddr_in *)res->ai_addr)->sin_port = htons(HTTP_PORT);
    
        /*Prepare POST request*/
        char send_buf[500];
        snprintf(send_buf, 500, POST_TEMPLATE, HTTP_PATH, HTTP_HOST, strlen(TEST_STRING), TEST_STRING);
        int send_data_len = strlen(send_buf);
    
        printk("POST code:\n\r%s\n\n\r", send_buf);
    
        /*Open a Socket*/
        int client_fd = socket(AF_INET, SOCK_STREAM, 0);
    
    	printk("client_fd: %d\n\r", client_fd);
    	err = bind(client_fd, (struct sockaddr *)&local_addr,
    		   sizeof(local_addr));
    	printk("bind err: %d\n\r", err);
    
        /*Send post request*/
        int num_bytes = send(client_fd, send_buf, send_data_len, 0);
    
    	printk("send err: %d\n\r", num_bytes);
    
    	int tot_num_bytes = 0;
    
        do {
            num_bytes =	blocking_recv(client_fd, recv_buf, RECV_BUF_SIZE, 0);
    	    tot_num_bytes += num_bytes;
    
    	    if (num_bytes <= 0) {
    		    break;
    		}
    	    printk("%s", recv_buf);
    	  } while (num_bytes > 0);
    
    	printk("\n\rFinished. Closing socket");
    	freeaddrinfo(res);
    	err = close(client_fd);
    }

    But I'm not sure whether all is OK as my POSTed information does not go through.

    I get no answer from the server (I know when something is wrong the server still answers with a fault code)

    send err: -1

    I tried with httpbin.org and there the result was the same: no result.

    with port 80 the result is the same, so I assume the problem is deeper than not being able to achieve an HTTPS call.

  • Hi, 

    Please try the http_post sample attached below and see if you get the same result. I used NCS v.1.0.0 and http://ptsv2.com as a test server.

    Received POST request:

    Project:

    http_post.zip 

    I'd suggest that you create a new ticket for HTTPS as I don't have experience with it. Maybe this thread is helpful: https://devzone.nordicsemi.com/f/nordic-q-a/48202/https-sample/ 

Related