Skip to content

Instantly share code, notes, and snippets.

@imba-tjd
Last active May 6, 2026 04:11
Show Gist options
  • Select an option

  • Save imba-tjd/523b377a0d36d40ae5109826e9eb9a0f to your computer and use it in GitHub Desktop.

Select an option

Save imba-tjd/523b377a0d36d40ae5109826e9eb9a0f to your computer and use it in GitHub Desktop.
Windows httpapi server example.
// https://learn.microsoft.com/zh-cn/windows/win32/Http
// gcc server.c -Os -Wall -lhttpapi -o server
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <http.h>
#include <windows.h>
#include <signal.h>
static HANDLE hReqQueue;
static HTTP_SERVER_SESSION_ID serverSessionId;
static HTTP_URL_GROUP_ID urlGroupId;
static void cleanup(int) {
HttpCloseRequestQueue(hReqQueue);
hReqQueue = NULL; // notify receive loop
HttpCloseUrlGroup(urlGroupId);
HttpCloseServerSession(serverSessionId);
HttpTerminate(HTTP_INITIALIZE_SERVER, NULL);
puts("Server terminated");
}
int main() {
ULONG ret;
// Initialize HTTP Server API
ret = HttpInitialize((HTTPAPI_VERSION)HTTPAPI_VERSION_2, HTTP_INITIALIZE_SERVER, NULL);
if (ret != NO_ERROR) {
printf("HttpInitialize failed with %lu\n", ret);
return ret;
}
// Create HTTP Server Session
ret = HttpCreateServerSession((HTTPAPI_VERSION)HTTPAPI_VERSION_2, &serverSessionId, 0);
if (ret != NO_ERROR) {
printf("HttpCreateServerSession failed with %lu\n", ret);
return ret;
}
// Create URL Group
ret = HttpCreateUrlGroup(serverSessionId, &urlGroupId, 0);
if (ret != NO_ERROR) {
printf("HttpCreateUrlGroup failed with %lu\n", ret);
return ret;
}
// Create Request Queue
ret = HttpCreateRequestQueue((HTTPAPI_VERSION)HTTPAPI_VERSION_2, NULL, NULL, 0, &hReqQueue);
if (ret != NO_ERROR) {
printf("HttpCreateRequestQueue failed with %lu\n", ret);
return ret;
}
// Bind URL Group to Request Queue
HTTP_BINDING_INFO bindingInfo = {
.Flags.Present = 1,
.RequestQueueHandle = hReqQueue
};
ret = HttpSetUrlGroupProperty(urlGroupId, HttpServerBindingProperty, &bindingInfo, sizeof(bindingInfo));
if (ret != NO_ERROR) {
printf("HttpSetUrlGroupProperty failed with %lu\n", ret);
return ret;
}
// Set URL
ret = HttpAddUrlToUrlGroup(urlGroupId, L"http://localhost:8080/", 0, 0);
if (ret != NO_ERROR) {
printf("HttpAddUrlToUrlGroup failed with %lu\n", ret);
return ret;
}
signal(SIGINT, cleanup);
puts("Server started on http://localhost:8080");
// Main loop to handle requests
while (1) {
if (!hReqQueue) return 0; // cleaned in SIGINT
// Initialize request structure
#define requestBufferLength (sizeof(HTTP_REQUEST) + 1024)
char requestBuffer[requestBufferLength] = {0};
HTTP_REQUEST *request = (HTTP_REQUEST*) requestBuffer;
// Receive a request
DWORD bytesRead;
ret = HttpReceiveHttpRequest(hReqQueue, HTTP_NULL_ID, 0, request, requestBufferLength, &bytesRead, NULL);
if (ret != NO_ERROR) {
printf("HttpReceiveHttpRequest failed with %lu\n", ret);
continue;
}
// Log remote addr
PSOCKADDR_IN r = (PSOCKADDR_IN)request->Address.pRemoteAddress;
#define SIN_ADDR_B(s) (s->sin_addr.S_un.S_un_b)
printf("Received from %hhu.%hhu.%hhu.%hhu:%hu\n",
SIN_ADDR_B(r).s_b1, SIN_ADDR_B(r).s_b2, SIN_ADDR_B(r).s_b3, SIN_ADDR_B(r).s_b4, r->sin_port);
// Initialize the response
HTTP_RESPONSE response = {
.StatusCode = 200,
.pReason = "OK",
};
response.ReasonLength = (USHORT)strlen(response.pReason);
response.Headers.KnownHeaders[HttpHeaderContentType].pRawValue = "text/plain";
response.Headers.KnownHeaders[HttpHeaderContentType].RawValueLength = (USHORT)strlen(response.Headers.KnownHeaders[HttpHeaderContentType].pRawValue);
// Response body
const char* responseBody = "Hello, World!";
HTTP_DATA_CHUNK dataChunk = {
.DataChunkType = HttpDataChunkFromMemory,
.FromMemory = {
.pBuffer = (PVOID)responseBody,
.BufferLength = (ULONG)strlen(responseBody)
}
};
response.EntityChunkCount = 1;
response.pEntityChunks = &dataChunk;
// Send the response
DWORD bytesSent;
ret = HttpSendHttpResponse(hReqQueue, request->RequestId, HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA, &response, NULL, &bytesSent, NULL, 0, NULL, NULL);
if (ret != NO_ERROR) {
printf("HttpSendHttpResponse failed with %lu\n", ret);
}
}
}
@imba-tjd
Copy link
Copy Markdown
Author

imba-tjd commented Nov 3, 2024

Unfinished pyx binding with some notes:

HTTP_REQUEST_V2“继承”了HTTP_REQUEST_V1。Vista后HTTP_REQUEST就是V2

# distutils: libraries=httpapi
# distutils: define_macros=WIN32_LEAN_AND_MEAN

# TODO:HTTP_SERVER_SESSION_ID定义错了,是ULONGLONG,不是struct

cdef extern from "<windows.h>":
    ctypedef unsigned short USHORT
    ctypedef unsigned long ULONG
    ctypedef unsigned long long ULONGLONG
    ctypedef void* PVOID
    ctypedef PVOID HANDLE
    ctypedef HANDLE* PHANDLE
    ctypedef Py_UNICODE WCHAR
    ctypedef const WCHAR* PCWSTR


cdef extern from "<http.h>":
    ctypedef struct HTTPAPI_VERSION:
        USHORT HttpApiMajorVersion
        USHORT HttpApiMinorVersion
    cdef HTTPAPI_VERSION HTTPAPI_VERSION_2

    ctypedef enum HTTP_SERVER_PROPERTY: # 一种多态,本enum指定选项类型,用给 队列、会话、URL组 设置属性
        HttpServerBindingProperty # HTTP_BINDING_INFO 仅用于把队列绑给URL组
        HttpServerTimeoutsProperty # HTTP_TIMEOUT_LIMIT_INFO 多个部分的超时配置,默认120秒。用于会话和URL组
        HttpServerLoggingProperty # HTTP_LOGGING_INFO 默认无日志。用于会话和URL组
        HttpServerQueueLengthProperty # ULONG 默认100,用于队列
        HttpServer503VerbosityProperty # HTTP_503_RESPONSE_VERBOSITY 队列满了应该怎么响应。默认重置,可选发送503后关闭,可选包含详细信息


    cdef ULONG HTTP_INITIALIZE_SERVER # Flags
    cdef ULONG NO_ERROR, ERROR_INVALID_PARAMETER # 返回值
    ULONG HttpInitialize(
        HTTPAPI_VERSION Version,
        ULONG Flags,
        PVOID pReserved # NULL
    )
    ULONG HttpTerminate( # 必须传与init相同的参数
        ULONG Flags,
        PVOID pReserved
    )


    ctypedef struct HTTP_SERVER_SESSION_ID: pass
    ctypedef HTTP_SERVER_SESSION_ID* PHTTP_SERVER_SESSION_ID
    ULONG HttpCreateServerSession(
        HTTPAPI_VERSION Version,
        PHTTP_SERVER_SESSION_ID ServerSessionId, # out
        ULONG Reserved # 0
    )
    ULONG HttpCloseServerSession(
        HTTP_SERVER_SESSION_ID ServerSessionId
    )

    ULONG HttpSetServerSessionProperty(
        HTTP_SERVER_SESSION_ID ServerSessionId,
        HTTP_SERVER_PROPERTY Property,
        PVOID PropertyInformation,
        ULONG PropertyInformationLength
    )


    ctypedef struct HTTP_URL_GROUP_ID: pass
    ctypedef HTTP_URL_GROUP_ID* PHTTP_URL_GROUP_ID
    ULONG HttpCreateUrlGroup(
        HTTP_SERVER_SESSION_ID ServerSessionId,
        PHTTP_URL_GROUP_ID pUrlGroupId, # out
        ULONG Reserved
    )
    ULONG HttpCloseUrlGroup( # 会自动删除与其关联的URL,不用手动HttpRemoveUrlFromUrlGroup
        HTTP_URL_GROUP_ID UrlGroupId
    )

    ctypedef ULONGLONG HTTP_URL_CONTEXT
    ULONG HttpAddUrlToUrlGroup(
        HTTP_URL_GROUP_ID UrlGroupId,
        PCWSTR pFullyQualifiedUrl,
        HTTP_URL_CONTEXT UrlContext, # optional,允许用户自定义的一个数字,之后每次HTTP_REQUEST收到时会加上
        ULONG Reserved
    )

    ctypedef struct HTTP_PROPERTY_FLAGS:
        bint Present
        bint _[31]
    ctypedef struct HTTP_BINDING_INFO: # 将队列绑定到URL组里。设计上二者独立,但实际都只会创建一个
        HTTP_PROPERTY_FLAGS Flags
        HANDLE RequestQueueHandle
    ULONG HttpSetUrlGroupProperty(
        HTTP_URL_GROUP_ID UrlGroupId,
        HTTP_SERVER_PROPERTY Property, # 要设置的属性类型
        PVOID PropertyInformation, # 属性的值
        ULONG PropertyInformationLength # sizeof(值)
    )


    ctypedef PVOID PSECURITY_ATTRIBUTES
    ULONG HttpCreateRequestQueue(
        HTTPAPI_VERSION Version,
        PCWSTR Name, # optional,用于其它进程按名称访问Q
        PSECURITY_ATTRIBUTES SecurityAttributes, # optional,不考虑使用
        ULONG Flags, # optional,用于按名称打开而非创建
        PHANDLE RequestQueueHandle # out
    )
    ULONG HttpCloseRequestQueue(
        HANDLE RequestQueueHandle
    )

    ULONG HttpSetRequestQueueProperty(
        HANDLE RequestQueueHandle,
        HTTP_SERVER_PROPERTY Property,
        PVOID PropertyInformation,
        ULONG PropertyInformationLength,
        ULONG Reserved1,
        PVOID Reserved2
    )

@traumasmart29-commits
Copy link
Copy Markdown

In Basketball Stars, victory isn't just about shooting; it's about building energy. The game features a unique "Supershot" mechanic that can turn the tide of any match in seconds. basketball stars

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment