Skip to content

Concepts First

  • HTTP: the request-response protocol used by web pages and APIs. The client sends a request (method + URL), the server returns a response (status + content).
  • GET: the most common HTTP method — "fetch this resource", e.g. loading a page, querying weather, reading device state. GET normally has no body; parameters go in the URL.
  • URL: a uniform resource locator such as http://www.gov.cn, composed of scheme, host and path.
  • Response callback: the example receives server data through response_cb; a response may arrive in multiple chunks (HTTP_DATA_MORE / HTTP_DATA_FINAL).

Example Overview

This page covers the GET part of the wifi_http example in the official Bouffalo SDK (examples/wifi/sta/wifi_http, wifi_http_client.c):

  • wifi_http_test <url> issues the request;
  • builds https_client_request: method = HTTP_GET, url from the command line, protocol = "HTTP/1.1";
  • calls https_client_request(&req, 3*1000, "IPv4 GET") synchronously with a 3-second timeout;
  • the response is printed character by character via response_cb.
  • Sibling examples: the same command continues with POST (see HTTP POST); TLS variant in HTTPS; PUT/DELETE have no ready-made example — see the self-written PUT.

Operation Steps

1
Enter the Example Directory

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_http
2
Build the Project

Both Ai-M61 and Ai-M62 use bl616:

make CHIP=bl616 BOARD=bl616dk
3
Flash the Firmware

Hold BOOT, briefly press EN/RST to enter download mode, then flash:

make flash CHIP=bl616 COMX=/dev/ttyUSB0
4
Connect Wi-Fi and Issue GET

Serial tool at 2000000 baud. Wait for bouffalolab />, connect to the router, then run the request (the example does GET first, then POST; this page focuses on the GET part):

wifi_sta_connect Your_SSID 12345678
wifi_http_test http://www.gov.cn
5
Run and Verify

The example prints Http client GET request server success and outputs the server’s response; on failure it prints http_client get request fail ret:xxx.

Code Execution Flow

The complete HTTP GET flow from boot to response:

APIs Used by the Example

https_client_request(&req, timeout, user_data)

Synchronously issues one HTTP/HTTPS request. req.method selects the method (HTTP_GET etc.), req.url is the full URL.

Parameters:

  • &req: struct https_client_request (method / url / protocol / response)
  • timeout: timeout in ms (3000 in the example)
  • user_data: passed through to the response callback

Return: >= 0 on success; < 0 on failure

response_cb(rsp, final_data, user_data)

Response callback: invoked on every received chunk; final_data is HTTP_DATA_MORE (more coming) or HTTP_DATA_FINAL (done). The example prints rsp->recv_buf content.

Parameters:

  • rsp: struct http_response (recv_buf, data_len)
  • final_data: whether data is complete

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
c
/****************************************************************************
 *
 * 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
c

#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);
#endif

FAQ

What does get request fail ret mean

ret < 0 means TCP connection or HTTP parsing failed: confirm Wi-Fi is connected and the URL is reachable; some overseas sites are slow from China — try http://www.baidu.com or a local server; increase the second argument of https_client_request if 3 seconds is too short.

The printed content looks like garbage

If the server returns HTML or compressed content, the serial output looks like "garbage" or escape characters — that is normal; the key success marker is HTTP GET request server success.

Have questions?

For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23