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.
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:
cdis the “change directory” command, entering the official example project; all subsequentmakecommands must run in this directory.
💡 Copy the directory (e.g.
http_client_delete) before modifying, keeping the official project untouched.
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/deleteis 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.
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 GET → DELETE (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 in the project directory:
make -j8
Note:
makeis the “build” command, turning code into firmware (the program flashed into the board) the board can run;-j8builds with 8 parallel cores, faster.
On success a firmware build_out/http_client_socket.bin is generated.
Keep the board connected via USB, confirm the serial device, and flash:
make flash p=/dev/ttyUSB0 b=921600
Note:
make flashis the “flash” command, writing the compiled firmware into the board. Afterp=comes the serial device (often/dev/ttyUSB0on Linux,COM3-like on Windows — use your computer’s actual one),b=921600is 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.
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/httpccomponent) 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 bygetaddrinfo
Return: none
socket(af, type, proto)
Creates a TCP socket.
Parameters:
af:AF_INET(IPv4)type:SOCK_STREAM(streaming TCP)proto: pass0
Return: socket descriptor on success; -1 on failure
connect(fd, addr, addrlen)
Connects to the server.
Parameters:
fd: socket descriptoraddr: 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 descriptorbuf: 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 descriptorbuf: receive bufferlen: 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 descriptorlevel:SOL_SOCKEToptname:SO_RCVTIMEOtv:struct timevalpointerlen: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
#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.

