Concepts First
- POST: an HTTP method meaning "submit data to the server" — form submission, sensor reporting, resource creation.
- Request body: the key difference from GET — data goes in the body instead of the URL, suited to larger payloads.
- chunked transfer: when the total length is unknown, split the data into chunks, each prefixed by a hex length, ending with
0\r\n\r\n. The example'spayload_cbdemonstrates this. - Response callback: server data is printed chunk by chunk via
response_cb.
Example Overview
This page covers the POST part of the wifi_http example in the official Bouffalo SDK (examples/wifi/sta/wifi_http, wifi_http_client.c):
wifi_http_test <url>builds the POST request after GET completes;req.method = HTTP_POSTwithheader_fieldsset toTransfer-Encoding: chunked;payload_cbis invoked while sending the body and writes the three chunks in chunked format;- calls
https_client_request(&req, 3*1000, "IPv4 POST")synchronously. - Sibling examples: PUT/DELETE have no ready-made example — see self-written PUT and self-written DELETE; GET in HTTP GET.
Operation Steps
Open a terminal and enter the SDK HTTP example directory (prerequisite: set up the environment as in Quick Start (Linux) or Windows):
cd examples/wifi/sta/wifi_httpBoth Ai-M61 and Ai-M62 use bl616:
make CHIP=bl616 BOARD=bl616dkHold BOOT, briefly press EN/RST to enter download mode, then flash:
make flash CHIP=bl616 COMX=/dev/ttyUSB0Serial tool at 2000000 baud. Wait for bouffalolab />, connect to the router, then run the command (the example does GET first, then POST; this page focuses on the POST part):
wifi_sta_connect Your_SSID 12345678
wifi_http_test http://www.gov.cnAfter GET, the example continues with POST and prints Http client POST request server success. The POST body uses chunked encoding: three chunks foobar, chunked, last, each prefixed with its hex length.
Code Execution Flow
The complete HTTP POST flow from request to response:
APIs Used by the Example
https_client_request(&req, timeout, user_data)
Synchronously issues one HTTP/HTTPS request. For POST, req.method = HTTP_POST; req.header_fields can add custom headers.
Parameters:
&req:struct https_client_requesttimeout: timeout in ms (3000 in the example)
Return: >= 0 on success; < 0 on failure
payload_cb(sock, req, user_data)
Body-sending callback: called by the library when it needs payload data; the example writes the three chunks (with length prefixes) and returns the number of bytes written.
Parameters:
sock: connection socketreq:struct http_request
Return: bytes written
response_cb(rsp, final_data, user_data)
Response callback, prints server data chunk by chunk.
Parameters:
rsp:struct http_responsefinal_data:HTTP_DATA_MORE/HTTP_DATA_FINAL
Return: none
Complete Code
The full wifi_http_client.c source, identical to the official example (examples/wifi/sta/wifi_http). Collapsed by default; click to expand:
📜 Click to expand wifi_http/main.c full code
/****************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include <lwip/tcpip.h>
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#include "wifi_mgmr_ext.h"
#include "bflb_irq.h"
#include "bflb_uart.h"
#include "rfparam_adapter.h"
#include "board.h"
#include "shell.h"
#ifndef BL602
#include "fhost_api.h"
#include "wifi_mgmr.h"
#endif
#include "async_event.h"
#include "mm.h"
#define DBG_TAG "MAIN"
#include "log.h"
struct bflb_device_s *gpio;
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define WIFI_STACK_SIZE (1536)
#define TASK_PRIORITY_FW (16)
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static struct bflb_device_s *uart0;
extern void shell_init_with_task(struct bflb_device_s *shell);
extern void wifi_event_handler(async_input_event_t ev, void *priv);
/* Main wifi stack entry point */
extern void wifi_main(void *param);
#ifdef BL602
extern void wifi_task_create(void);
extern int fhost_init(void);
extern int wifi_mgmr_task_start(void);
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Functions
****************************************************************************/
void wifi_start_firmware_task(void *param)
{
LOG_I("Starting wifi ...\r\n");
async_register_event_filter(EV_WIFI, wifi_event_handler, NULL);
wifi_task_create();
LOG_I("Starting fhost ...\r\n");
fhost_init();
vTaskDelete(NULL);
}
void wifi_event_handler(async_input_event_t ev, void *priv)
{
uint32_t code = ev->code;
switch (code) {
case CODE_WIFI_ON_INIT_DONE: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_INIT_DONE\r\n", __func__);
wifi_mgmr_task_start();
} break;
case CODE_WIFI_ON_MGMR_DONE: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_MGMR_DONE\r\n", __func__);
} break;
case CODE_WIFI_ON_SCAN_DONE: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_SCAN_DONE\r\n", __func__);
wifi_mgmr_sta_scanlist();
} break;
case CODE_WIFI_ON_CONNECTED: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_CONNECTED\r\n", __func__);
void mm_sec_keydump();
mm_sec_keydump();
} break;
case CODE_WIFI_ON_GOT_IP: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_GOT_IP\r\n", __func__);
LOG_I("[SYS] Memory left is %d Bytes\r\n", kfree_size(0));
} break;
case CODE_WIFI_ON_DISCONNECT: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_DISCONNECT\r\n", __func__);
} break;
case CODE_WIFI_ON_AP_STARTED: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STARTED\r\n", __func__);
} break;
case CODE_WIFI_ON_AP_STOPPED: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STOPPED\r\n", __func__);
} break;
case CODE_WIFI_ON_AP_STA_ADD: {
LOG_I("[APP] [EVT] [AP] [ADD] %lld\r\n", xTaskGetTickCount());
} break;
case CODE_WIFI_ON_AP_STA_DEL: {
LOG_I("[APP] [EVT] [AP] [DEL] %lld\r\n", xTaskGetTickCount());
} break;
default: {
LOG_I("[APP] [EVT] Unknown code %u \r\n", code);
}
}
}
int main(void)
{
board_init();
uart0 = bflb_device_get_by_name("uart0");
shell_init_with_task(uart0);
if (0 != rfparam_init(0, NULL, 0)) {
LOG_I("PHY RF init failed!\r\n");
return 0;
}
LOG_I("PHY RF init success!\r\n");
tcpip_init(NULL, NULL);
xTaskCreate(wifi_start_firmware_task, "wifi init", 1024, NULL, 10, NULL);
vTaskStartScheduler();
while (1) {
}
}
int cmd_gethostbyname(int argc, char **argv)
{
struct addrinfo hints, *res, *p;
int status;
char ipstr[INET6_ADDRSTRLEN];
char *name = argv[1];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
if(!strcmp(argv[1], "-4")) {
hints.ai_family = AF_INET;
name = argv[2];
}
if(!strcmp(argv[1], "-6")) {
hints.ai_family = AF_INET6;
name = argv[2];
}
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(name, NULL, &hints, &res)) != 0) {
fprintf(stderr, "getaddrinfo error: %d\r\n", status);
return 0;
}
printf("IP addresses for %s:\r\n", name);
for (p = res; p != NULL; p = p->ai_next) {
void *addr;
char *ipver;
if (p->ai_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
} else {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf(" %s: %s\r\n", ipver, ipstr);
}
freeaddrinfo(res);
return 0;
}
SHELL_CMD_EXPORT_ALIAS(cmd_gethostbyname, gethostbyname, gethostbyname command);📜 Click to expand wifi_http_client.c full code
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <lwip/api.h>
#include <lwip/arch.h>
#include <lwip/opt.h>
#include <lwip/inet.h>
#include <lwip/errno.h>
#include <netdb.h>
#include "shell.h"
#include "utils_getopt.h"
#include "bflb_mtimer.h"
#include "https_client.h"
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
#endif
static int payload_cb(int sock, struct http_request *req, void *user_data)
{
const char *content[] = {
"foobar",
"chunked",
"last"
};
char tmp[64];
int i, pos = 0;
for (i = 0; i < ARRAY_SIZE(content); i++) {
pos += snprintf(tmp + pos, sizeof(tmp) - pos,
"%x\r\n%s\r\n",
(unsigned int)strlen(content[i]),
content[i]);
}
pos += snprintf(tmp + pos, sizeof(tmp) - pos, "0\r\n\r\n");
(void)zsock_send(sock, tmp, pos, 0);
return pos;
}
static int log_output(void *ptr, size_t size)
{
size_t i;
for (i = 0; i < size; i++) {
putchar(((char *)ptr)[i]);
}
return i;
}
static void response_cb(struct http_response *rsp,
enum http_final_call final_data,
void *user_data)
{
log_output(rsp->recv_buf, rsp->data_len);
if (final_data == HTTP_DATA_MORE) {
//printf("Partial data received (%zd bytes)\r\n", rsp->data_len);
} else if (final_data == HTTP_DATA_FINAL) {
//printf("All the data received (%zd bytes)\r\n", rsp->data_len);
}
}
#define PING_USAGE \
"wifi_http_test [url]\r\n" \
"\t url: url or dest server ip\r\n" \
static void wifi_test_http_client_init(int argc, char **argv)
{
int ret;
char *url;
struct https_client_request req;
if (argc < 2) {
printf("%s", PING_USAGE);
return;
}
/* get address (argv[1] if present) */
url = argv[1];
memset(&req, 0, sizeof(req));
req.method = HTTP_GET;
req.url = url;
req.protocol = "HTTP/1.1";
req.response = response_cb;
ret = https_client_request(&req, 3*1000, "IPv4 GET");
if (ret < 0) {
printf("http_client get request fail ret:%d\r\n", ret);
} else {
printf("Http client GET request server success\r\n");
}
const char *headers[] = {
"Transfer-Encoding: chunked\r\n",
NULL
};
memset(&req, 0, sizeof(req));
req.method = HTTP_POST;
req.url = url;
req.protocol = "HTTP/1.1";
req.payload_cb = payload_cb;
req.header_fields = headers;
req.response = response_cb;
ret = https_client_request(&req, 3*1000, "IPv4 POST");
if (ret < 0) {
printf("http_client post request fail ret:%d\r\n", ret);
} else {
printf("Http client POST request server success\r\n");
}
}
#ifdef CONFIG_SHELL
#include <shell.h>
int cmd_wifi_http_client(int argc, char **argv)
{
wifi_test_http_client_init(argc, argv);
return 0;
}
SHELL_CMD_EXPORT_ALIAS(cmd_wifi_http_client, wifi_http_test, wifi http client test);
#endifFAQ
POST request fails
Confirm the server accepts POST and the URL is correct; chunked encoding needs server support for Transfer-Encoding: chunked (most web servers support it); for local tests run a service that handles POST (e.g. a small Python/Node server).
How do I send JSON instead of the fixed three chunks
Replace the content[] array in payload_cb with your JSON string; alternatively skip chunked and fill req.payload / req.payload_len with the complete body (see the self-written PUT example).
Have questions?
For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

