Skip to content

Commit 5b7225d

Browse files
Kezinomihakezi
authored andcommitted
[issue #2373] Add getBodyStream for request
1 parent b921af6 commit 5b7225d

File tree

4 files changed

+90
-2
lines changed

4 files changed

+90
-2
lines changed

ext-src/stubs/php_swoole_http_request.stub.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ public static function create(array $options = []): Request {}
77
public function parse(string $data): int|false {}
88
public function isCompleted(): bool {}
99
public function getMethod(): string|false {}
10-
public function getContent(): string|false {}
11-
}
10+
public function getContent(): string|false {}
11+
/** @return resource|false */
12+
public function getBodyStream(){}
13+
}
1214
}

ext-src/stubs/php_swoole_http_request_arginfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@ ZEND_END_ARG_INFO()
2121
#define arginfo_class_Swoole_Http_Request_getMethod arginfo_class_Swoole_Http_Request_getData
2222

2323
#define arginfo_class_Swoole_Http_Request_getContent arginfo_class_Swoole_Http_Request_getData
24+
25+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Swoole_Http_Request_getBodyStream, 0, 0, MAY_BE_RESOURCE|MAY_BE_FALSE)
26+
ZEND_END_ARG_INFO()

ext-src/swoole_http_request.cc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ static PHP_METHOD(swoole_http_request, parse);
209209
static PHP_METHOD(swoole_http_request, isCompleted);
210210
static PHP_METHOD(swoole_http_request, getMethod);
211211
static PHP_METHOD(swoole_http_request, getContent);
212+
static PHP_METHOD(swoole_http_request, getBodyStream);
212213
SW_EXTERN_C_END
213214

214215
// clang-format off
@@ -221,6 +222,7 @@ const zend_function_entry swoole_http_request_methods[] =
221222
PHP_ME(swoole_http_request, parse, arginfo_class_Swoole_Http_Request_parse, ZEND_ACC_PUBLIC)
222223
PHP_ME(swoole_http_request, isCompleted, arginfo_class_Swoole_Http_Request_isCompleted, ZEND_ACC_PUBLIC)
223224
PHP_ME(swoole_http_request, getMethod, arginfo_class_Swoole_Http_Request_getMethod, ZEND_ACC_PUBLIC)
225+
PHP_ME(swoole_http_request, getBodyStream, arginfo_class_Swoole_Http_Request_getBodyStream, ZEND_ACC_PUBLIC)
224226
PHP_FE_END
225227
};
226228
// clang-format on
@@ -910,6 +912,41 @@ static PHP_METHOD(swoole_http_request, getContent) {
910912
RETURN_EMPTY_STRING();
911913
}
912914

915+
static PHP_METHOD(swoole_http_request, getBodyStream) {
916+
HttpContext *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS);
917+
if (UNEXPECTED(!ctx)) {
918+
RETURN_FALSE;
919+
}
920+
921+
char tmp_file[SW_HTTP_UPLOAD_TMPDIR_SIZE];
922+
sw_snprintf(tmp_file, SW_HTTP_UPLOAD_TMPDIR_SIZE, "%s/swoole.request.XXXXXX", ctx->upload_tmp_dir.c_str());
923+
int fd = swoole_tmpfile(tmp_file);
924+
if (fd < 0) {
925+
RETURN_FALSE;
926+
}
927+
928+
HttpRequest *req = &ctx->request;
929+
if (req->body_length > 0) {
930+
zval *zdata = &req->zdata;
931+
write(fd, Z_STRVAL_P(zdata) + Z_STRLEN_P(zdata) - req->body_length, req->body_length);
932+
} else if (req->chunked_body && req->chunked_body->length != 0) {
933+
write(fd, req->chunked_body->str, req->chunked_body->length);
934+
} else if (req->h2_data_buffer && req->h2_data_buffer->length != 0) {
935+
write(fd, req->h2_data_buffer->str, req->h2_data_buffer->length);
936+
}
937+
938+
lseek(fd, 0, SEEK_SET);
939+
php_stream *stream = php_swoole_create_stream_from_pipe(fd, "r+", nullptr);
940+
if (!stream) {
941+
close(fd);
942+
RETURN_FALSE;
943+
}
944+
zval *ztmpfiles = swoole_http_init_and_read_property(
945+
swoole_http_request_ce, ctx->request.zobject, &ctx->request.ztmpfiles, SW_ZSTR_KNOWN(SW_ZEND_STR_TMPFILES));
946+
add_next_index_string(ztmpfiles, tmp_file);
947+
php_stream_to_zval(stream, return_value);
948+
}
949+
913950
static PHP_METHOD(swoole_http_request, getData) {
914951
HttpContext *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS);
915952
if (UNEXPECTED(!ctx)) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
swoole_http_server: getBodyStream
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/../include/skipif.inc';
6+
skip_if_in_valgrind();
7+
?>
8+
--FILE--
9+
<?php
10+
require __DIR__ . '/../include/bootstrap.php';
11+
12+
use function Co\run;
13+
14+
$pm = new ProcessManager;
15+
$pm->parentFunc = function ($pid) use ($pm) {
16+
run(function () use ($pm) {
17+
$randomData = get_safe_random();
18+
$cli = new Co\http\Client(HTTP_SERVER_HOST, $pm->getFreePort(), false);
19+
$cli->setMethod('POST');
20+
$cli->setData($randomData);
21+
$ok = $cli->execute('/getBodyStream');
22+
Assert::assert($ok);
23+
Assert::same($cli->statusCode, 200);
24+
Assert::same($cli->errCode, 0);
25+
Assert::same($cli->body, $randomData);
26+
$pm->kill();
27+
echo "DONE\n";
28+
});
29+
};
30+
$pm->childFunc = function () use ($pm) {
31+
$http = new Swoole\Http\Server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE);
32+
$http->set(['worker_num' => 1]);
33+
$http->on('workerStart', function () use ($pm) {
34+
$pm->wakeup();
35+
});
36+
$http->on('request', function (Swoole\Http\Request $request, Swoole\Http\Response $response) {
37+
$stream = $request->getBodyStream();
38+
$response->end(stream_get_contents($stream));
39+
});
40+
$http->start();
41+
};
42+
$pm->childFirst();
43+
$pm->run();
44+
?>
45+
--EXPECT--
46+
DONE

0 commit comments

Comments
 (0)