Skip to content

Instantly share code, notes, and snippets.

@masakielastic
Last active March 21, 2026 20:41
Show Gist options
  • Select an option

  • Save masakielastic/343f6c7af42df64ef227bf5e2b192381 to your computer and use it in GitHub Desktop.

Select an option

Save masakielastic/343f6c7af42df64ef227bf5e2b192381 to your computer and use it in GitHub Desktop.
embed PHP と Stream API で HTTP/1 サーバー。最新版は https://github.com/masakielastic/php-embed-stream-http
#include <php.h>
#include <Zend/zend_smart_str.h>
#include <sapi/embed/php_embed.h>
static int run_min_server(void);
int main(int argc, char **argv)
{
PHP_EMBED_START_BLOCK(argc, argv)
(void) run_min_server();
PHP_EMBED_END_BLOCK()
return 0;
}
static int run_min_server(void)
{
php_stream *server = NULL;
php_stream *client = NULL;
zend_string *err_text = NULL;
zend_string *peer = NULL;
int errcode = 0;
server = php_stream_xport_create(
"tcp://127.0.0.1:8080",
sizeof("tcp://127.0.0.1:8080") - 1,
REPORT_ERRORS,
STREAM_XPORT_SERVER | STREAM_XPORT_BIND | STREAM_XPORT_LISTEN,
NULL,
NULL,
NULL,
&err_text,
&errcode
);
if (!server) {
php_printf("server create failed: %s (%d)\n",
err_text ? ZSTR_VAL(err_text) : "unknown", errcode);
if (err_text) {
zend_string_release(err_text);
}
return FAILURE;
}
for (;;) {
zend_string *accept_error = NULL;
if (php_stream_xport_accept(server, &client, &peer, NULL, NULL, NULL, &accept_error) < 0) {
php_printf("accept failed: %s\n",
accept_error ? ZSTR_VAL(accept_error) : "unknown");
if (accept_error) {
zend_string_release(accept_error);
}
break;
}
if (client) {
char buf[4096];
ssize_t n;
n = php_stream_read(client, buf, sizeof(buf) - 1);
if (n > 0) {
smart_str request_log = {0};
smart_str response = {0};
buf[n] = '\0';
smart_str_appends(&request_log, "request:\n");
smart_str_appendl(&request_log, buf, (size_t) n);
smart_str_appends(&request_log, "\n");
smart_str_0(&request_log);
php_printf("%s", ZSTR_VAL(request_log.s));
smart_str_appends(&response, "HTTP/1.1 200 OK\r\n");
smart_str_appends(&response, "Content-Type: text/plain\r\n");
smart_str_appends(&response, "Content-Length: 12\r\n");
smart_str_appends(&response, "Connection: close\r\n");
smart_str_appends(&response, "\r\n");
smart_str_appends(&response, "hello world\n");
smart_str_0(&response);
php_stream_write(client, ZSTR_VAL(response.s), ZSTR_LEN(response.s));
smart_str_free(&request_log);
smart_str_free(&response);
}
php_stream_xport_shutdown(client, STREAM_SHUT_RDWR);
php_stream_close(client);
client = NULL;
}
if (peer) {
zend_string_release(peer);
peer = NULL;
}
}
php_stream_close(server);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment