Skip to content

Overview

DELETE asks the server to delete a specified resource (RESTful style) — the "lightest" of the four common HTTP methods: it usually needs no request body, and the resource location goes in the path (URL). Device deregistration, deleting cloud records, and removing data points can all use DELETE. This tutorial demonstrates: sending a DELETE request to httpbin.org/delete, and the server echoes the request info.

In plain words: DELETE is telling the server "delete XX" — like telling the waiter "please take this dish away". What to delete is written in the "path" (e.g. /devices/1001 deletes device 1001); usually no form needs to be handed over (no request body), and the server replies "deleted" (200 OK) on receipt.

This tutorial is based on the official Ai-Thinker SDK (Ai-Thinker-Open/Ai-Thinker-WB2, version release_bl_iot_sdk_1.6.40).

⚠️ The official SDK does not ship a standalone DELETE example project. This tutorial reworks the official example applications/protocols/http_client_socket (the GET version); the only change is the request message (the method line) — the rest matches the official code, marked with comments.

🎯Page GoalBuild a DELETE request message on top of the official GET example and verify the server echo, mastering message construction for body-less methods.
🧰Prerequisites① Ai-WB2 development board (Type-C data cable) ② A 2.4GHz router (with public internet access) ③ Environment set up per [SDK Installation](../../sdk/sdk_intro) and completed [Connect Wi-Fi](./wifi_connect) and [HTTP GET](./http_get).
🔗RelatedUpdating resources: [HTTP PUT](./http_put); submitting data: [HTTP POST](./http_post).

Enter the Example Project

The official SDK has no dedicated DELETE project, so rework the official http_client_socket project directly:

cd ~/Ai-Thinker-WB2/applications/protocols/http_client_socket

Note: cd is the “change directory” command, entering the official example project; all subsequent make commands must run in this directory.

💡 Copy the directory (e.g. http_client_delete) before modifying, keeping the official project untouched.

Modify the Router Parameters and Target Address

Open http_client_socket/main.c and change the SSID/password at the top (the official default is AIOT@FAE — change it to your own router).

Open http_client_socket/demo.c and change the target server:

#define WEB_SERVER "httpbin.org"
#define WEB_PORT "80"
#define WEB_PATH "/delete"

💡 httpbin.org/delete is a free DELETE test endpoint — it echoes the received request as JSON. In real business, the path often carries the resource ID, e.g. DELETE /devices/1001.

Write the Code (Rework Point: Request Message)

Rework the request message to DELETE based on the official demo.c. The full code for this step has been moved to the end of this page:

📜 Full Code — in the “Full Code” section below, collapsed by default — click to expand, matching the official example (applications/protocols/http_client_socket/http_client_socket/demo.c) except the request message reworked to DELETE per this page.

Code highlights (differences vs the official GET version):

Change Description
DELETE /delete HTTP/1.0 Method line GETDELETE (the only change); the server knows from it that a resource is to be deleted
No request body Usually no body is needed; the message ends with a blank line (\r\n\r\n) — sending extra data may even cause errors
Everything else Identical to the official http_client_socket

💡 Message differences across the four methods: GET/DELETE carry no request body (the resource lives in the path); POST/PUT carry a request body (Content-Type + Content-Length + body). The server decides what to do to the resource entirely from the method line + path.

Build the Project

Build in the project directory:

make -j8

Note: make is the “build” command, turning code into firmware (the program flashed into the board) the board can run; -j8 builds with 8 parallel cores, faster.

On success a firmware build_out/http_client_socket.bin is generated.

Flash the Firmware

Keep the board connected via USB, confirm the serial device, and flash:

make flash p=/dev/ttyUSB0 b=921600

Note: make flash is the “flash” command, writing the compiled firmware into the board. After p= comes the serial device (often /dev/ttyUSB0 on Linux, COM3-like on Windows — use your computer’s actual one), b=921600 is the flash baud rate (serial transfer speed), keep the default.

⏳ During flashing, press and hold the EN button on the board when prompted to enter download mode; wait for the progress bar to complete — that means the flash succeeded.

Run and Verify

After flashing, the board automatically restarts and runs. The serial (baud rate 921600, the “speech rate” of serial transfer — both sides must agree) prints the connection logs, then httpbin.org’s JSON echo:

DNS lookup succeeded. IP=34.224.xxx.xxx
... connected
... socket send success
HTTP/1.1 200 OK
Content-Type: application/json
...
{
  "args": {},
  "data": "",
  "origin": "116.xxx.xxx.xxx",
  ...
}
... done reading from socket. Last read return=0 errno=0

HTTP/1.1 200 OK appearing with the echo "data": "" means the DELETE succeeded — the server correctly identified and processed the deletion request. If you only see GOT IP without the echo, first confirm the board is online (GOT IP), your computer’s browser can open httpbin.org (target server reachable), then see the FAQ at the end.

💡 Summary: you now know the message construction of all four common HTTP methods (GET/POST/PUT/DELETE) — the method line decides the operation, the path locates the resource, an optional body carries data. In real projects, use an HTTP client library (e.g. the official SDK’s components/network/httpc component) or stitch the message manually (as in this series), assembling it per the interface documentation.


API Summary for This Tutorial

getaddrinfo(name, port, &hints, &res)

Resolves a domain name into a linked list of IPs.

Parameters:

  • name: domain or IP string, e.g. "httpbin.org"
  • port: port string, e.g. "80"
  • hints: query criteria structure (limits to IPv4 + TCP)
  • res: output parameter, resolved linked-list pointer

Return: 0 on success; negative error code on failure

freeaddrinfo(res)

Frees the resolution result.

Parameters:

  • res: result linked list returned by getaddrinfo

Return: none

socket(af, type, proto)

Creates a TCP socket.

Parameters:

  • af: AF_INET (IPv4)
  • type: SOCK_STREAM (streaming TCP)
  • proto: pass 0

Return: socket descriptor on success; -1 on failure

connect(fd, addr, addrlen)

Connects to the server.

Parameters:

  • fd: socket descriptor
  • addr: server address (struct sockaddr*)
  • addrlen: address length

Return: 0 on success; negative error code on failure

write(fd, buf, len)

Sends the whole HTTP message (including the request body).

Parameters:

  • fd: socket descriptor
  • buf: request message buffer (request line + headers + blank line + body)
  • len: total message length

Return: bytes sent on success; negative on failure

read(fd, buf, len)

Reads the server response.

Parameters:

  • fd: socket descriptor
  • buf: receive buffer
  • len: buffer length

Return: bytes read; 0 = peer closed; negative = error

close(fd)

Closes the connection.

Parameters:

  • fd: socket descriptor

Return: 0 on success; -1 on failure

setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, len)

Sets the receive timeout.

Parameters:

  • fd: socket descriptor
  • level: SOL_SOCKET
  • optname: SO_RCVTIMEO
  • tv: struct timeval pointer
  • len: sizeof(struct timeval)

Return: 0 on success; negative error code on failure

inet_ntoa(addr)

Converts an IP address to a string.

Parameters:

  • addr: network-byte-order IP

Return: dotted-decimal string

bl_putchar(c)

Outputs one character to the serial.

Parameters:

  • c: the character to output

Return: none

📌 A DELETE message = request line (DELETE path HTTP/1.0) + headers + blank line, no request body. If the interface needs conditional info, put it in the path (/devices/1001) or the request headers.


Full Code

Below is the complete demo.c source, matching the official example (applications/protocols/http_client_socket/http_client_socket/demo.c) except the request message reworked to DELETE per this page:

📜 Click to expand the full demo.c code
c
#include <stdio.h>
#include <FreeRTOS.h>
#include <task.h>
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#include <lwip/tcp.h>
#include <lwip/err.h>
#include <http_client.h>
#include <cli.h>
#include "demo.h"
#include <blog.h>

#define WEB_SERVER "httpbin.org"
#define WEB_PORT "80"
#define WEB_PATH "/delete"

/* ★ Rework point: method GET → DELETE (no request body, message ends with a blank line) */
static const char *REQUEST = "DELETE " WEB_PATH " HTTP/1.0\r\n"
                         "Host: " WEB_SERVER ":" WEB_PORT "\r\n"
                         "User-Agent: aithinker wb2\r\n"
                         "\r\n";

void http_get_task(void *pvParameters)
{
const struct addrinfo hints = {
    .ai_family = AF_INET,
    .ai_socktype = SOCK_STREAM,
};
struct addrinfo *res;
struct in_addr *addr;
int s, r;
char recv_buf[4096];

while (1)
{
    int err = getaddrinfo(WEB_SERVER, "80", &hints, &res);

    if (err != 0 || res == NULL)
    {
        blog_error("DNS lookup failed err=%d res=%p", err, res);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        continue;
    }

    addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
    blog_info("DNS lookup succeeded. IP=%s", inet_ntoa(*addr));

    s = socket(res->ai_family, res->ai_socktype, 0);
    if (s < 0)
    {
        blog_error("... Failed to allocate socket.");
        freeaddrinfo(res);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        continue;
    }
    blog_info("... allocated socket");

    if (connect(s, res->ai_addr, res->ai_addrlen) != 0)
    {
        blog_error("... socket connect failed errno=%d", errno);
        close(s);
        freeaddrinfo(res);
        vTaskDelay(4000 / portTICK_PERIOD_MS);
        continue;
    }

    blog_info("... connected");
    freeaddrinfo(res);

    if (write(s, REQUEST, strlen(REQUEST)) < 0)
    {
        blog_error("... socket send failed");
        close(s);
        vTaskDelay(4000 / portTICK_PERIOD_MS);
        continue;
    }
    blog_info("... socket send success");

    struct timeval receiving_timeout;
    receiving_timeout.tv_sec = 5;
    receiving_timeout.tv_usec = 0;
    if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &receiving_timeout,
                   sizeof(receiving_timeout)) < 0)
    {
        blog_error("... failed to set socket receiving timeout");
        close(s);
        vTaskDelay(4000 / portTICK_PERIOD_MS);
        continue;
    }
    blog_info("... set socket receiving timeout success");

    // FIXME fix putchar
    extern int bl_putchar(int c);

    /* Read HTTP response */
    do
    {
        bzero(recv_buf, sizeof(recv_buf));
        r = read(s, recv_buf, sizeof(recv_buf) - 1);
        for (int i = 0; i < r; i++)
        {
            bl_putchar(recv_buf[i]);
        }
    } while (r > 0);

    blog_info("... done reading from socket. Last read return=%d errno=%d\r\n", r, errno);
    close(s);
    for (int countdown = 10; countdown >= 0; countdown--)
    {
        blog_info("%d... ", countdown);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    blog_info("Starting again!");
}
}

FAQ & Troubleshooting

⚠️ Server returns 405 Method Not Allowed
Cause: the target path doesn't support DELETE (most static sites only support GET/HEAD)
Fix: use a DELETE-capable endpoint (httpbin.org/delete, httpbin.org/anything) or your own server

⚠️ Parameters needed but the interface doc requires them in the body
Cause: some backends accept a body on DELETE too (non-standard)
Fix: stitch per the interface doc (the Content-Type/Content-Length style from the POST/PUT chapters applies as well); the standard approach puts them in the path/request headers

⚠️ Accidentally deleted a real resource
Cause: DELETE is a destructive operation, and the test endpoint got mixed up with the real environment
Fix: only use test sites (httpbin.org) during development; before connecting to a real server, confirm the interface semantics and permissions with the backend team

⚠️ Other issues (can't connect to router / DNS failure / timeout / stack overflow)
Note: identical to HTTP GET
Fix: follow the pitfalls in HTTP GET (including can't connect to the router, serial not found, flashing failure, etc.)

⚠️ Serial device not found / can't open
Cause: USB-to-serial driver not installed, insufficient permission, or the cable only charges and can't transfer data
Fix: on Linux check the device with lsusb/dmesg; if permission denied run sudo chmod 666 /dev/ttyUSB0; on Windows install the driver and check the COM port in Device Manager; try a data-capable cable

⚠️ Flashing keeps waiting / fails
Cause: download mode wasn't entered, wrong baud rate, or a wrong serial number
Fix: press and hold EN during flashing to enter download mode as prompted; change p=/dev/ttyUSB0 to your actual serial port; try another USB port or cable

Self-Check

HTTP/1.1 200 OK appears on the serial with an empty JSON echo — the DELETE request is verified.

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