Skip to content

Commit

Permalink
Optimize http (#4032)
Browse files Browse the repository at this point in the history
* improve httpclient

* fix bugs

* improve library, fix type

* fix tests
  • Loading branch information
matyhtf authored Jan 28, 2021
1 parent 8f075dc commit a131fa8
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 25 deletions.
52 changes: 35 additions & 17 deletions ext-src/php_swoole_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Generated by build-library.php, Please DO NOT modify!
*/

/* $Id: d11b08d63da2235271f6423764b5b0a5ab803b5e */
/* $Id: 92fd0de7d122fd973205d73931bda42c3bc80bb7 */

static const char* swoole_library_source_constants =
"\n"
Expand Down Expand Up @@ -6844,6 +6844,27 @@ static const char* swoole_library_source_core_coroutine_functions =
"\n"
"use Swoole\\Coroutine;\n"
"\n"
"function run(callable $fn, ...$args)\n"
"{\n"
" $s = new Scheduler();\n"
" $options = Coroutine::getOptions();\n"
" if (!isset($options['hook_flags'])) {\n"
" $s->set(['hook_flags' => SWOOLE_HOOK_ALL]);\n"
" }\n"
" $s->add($fn, ...$args);\n"
" return $s->start();\n"
"}\n"
"\n"
"function go(callable $fn, ...$args)\n"
"{\n"
" Coroutine::create($fn, ...$args);\n"
"}\n"
"\n"
"function defer(callable $fn)\n"
"{\n"
" Coroutine::defer($fn);\n"
"}\n"
"\n"
"function batch(array $tasks, float $timeout = -1): array\n"
"{\n"
" $wg = new WaitGroup(count($tasks));\n"
Expand Down Expand Up @@ -7392,27 +7413,24 @@ static const char* swoole_library_source_alias_ns =
"\n"
"declare(strict_types=1);\n"
"\n"
"namespace Swoole\\Coroutine {\n"
" use Swoole\\Coroutine;\n"
"namespace Co;\n"
"\n"
"use Swoole\\Coroutine;\n"
"\n"
"if (SWOOLE_USE_SHORTNAME) {\n"
" function run(callable $fn, ...$args)\n"
" {\n"
" $s = new Scheduler();\n"
" $options = Coroutine::getOptions();\n"
" if (!isset($options['hook_flags'])) {\n"
" $s->set(['hook_flags' => SWOOLE_HOOK_ALL]);\n"
" }\n"
" $s->add($fn, ...$args);\n"
" return $s->start();\n"
" return \\Swoole\\Coroutine\\run($fn, ...$args);\n"
" }\n"
"}\n"
"\n"
"namespace Co {\n"
" if (SWOOLE_USE_SHORTNAME) {\n"
" function run(callable $fn, ...$args)\n"
" {\n"
" return \\Swoole\\Coroutine\\run($fn, ...$args);\n"
" }\n"
" function go(callable $fn, ...$args)\n"
" {\n"
" return Coroutine::create($fn, ...$args);\n"
" }\n"
"\n"
" function defer(callable $fn)\n"
" {\n"
" Coroutine::defer($fn);\n"
" }\n"
"}\n";

Expand Down
11 changes: 8 additions & 3 deletions ext-src/swoole_http_client_coro.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1034,13 +1034,18 @@ bool HttpClient::send() {
header_flag |= HTTP_HEADER_CONTENT_LENGTH;
// ignore custom Content-Length value
continue;
} else if (SW_STRCASEEQ(key, keylen, "Connection")) {
}
zend::String str_value(zvalue);
add_headers(buffer, key, keylen, str_value.val(), str_value.len());

if (SW_STRCASEEQ(key, keylen, "Connection")) {
header_flag |= HTTP_HEADER_CONNECTION;
if (SW_STRCASEEQ(str_value.val(), str_value.len(), "close")) {
keep_alive = 0;
}
} else if (SW_STRCASEEQ(key, keylen, "Accept-Encoding")) {
header_flag |= HTTP_HEADER_ACCEPT_ENCODING;
}
zend::String str_value(zvalue);
add_headers(buffer, key, keylen, str_value.val(), str_value.len());
}
SW_HASHTABLE_FOREACH_END();
}
Expand Down
4 changes: 2 additions & 2 deletions ext-src/swoole_http_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,10 @@ bool http_context_send_data(http_context *ctx, const char *data, size_t length)

static bool http_context_sendfile(http_context *ctx, const char *file, uint32_t l_file, off_t offset, size_t length) {
Server *serv = (Server *) ctx->private_data;
return serv->sendfile(ctx->fd, file, l_file, offset, length) == SW_OK;
return serv->sendfile(ctx->fd, file, l_file, offset, length);
}

static bool http_context_disconnect(http_context *ctx) {
Server *serv = (Server *) ctx->private_data;
return serv->close(ctx->fd, 0) == SW_OK;
return serv->close(ctx->fd, 0);
}
2 changes: 1 addition & 1 deletion src/network/client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ static int Client_tcp_connect_async(Client *cli, const char *host, int port, dou
}

static ssize_t Client_tcp_send_async(Client *cli, const char *data, size_t length, int flags) {
int n = length;
ssize_t n = length;
if (swoole_event_write(cli->socket, data, length) < 0) {
if (swoole_get_last_error() == SW_ERROR_OUTPUT_BUFFER_OVERFLOW) {
n = -1;
Expand Down
2 changes: 1 addition & 1 deletion src/server/process.cc
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ bool ProcessFactory::finish(SendData *resp) {
if (swoole_event_write(server_->last_stream_socket, &resp->info, sizeof(resp->info)) < 0) {
return false;
}
if (swoole_event_write(server_->last_stream_socket, resp->data, _len) < 0) {
if (_len > 0 && swoole_event_write(server_->last_stream_socket, resp->data, _len) < 0) {
return false;
}
return true;
Expand Down
55 changes: 55 additions & 0 deletions tests/swoole_http_server/sendfile_no_keepalive.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
--TEST--
swoole_http_server: sendfile with dispatch_mode=7
--SKIPIF--
<?php require __DIR__ . '/../include/skipif.inc'; ?>
--FILE--
<?php
require __DIR__ . '/../include/bootstrap.php';

use Swoole\Coroutine\Http\Client;
use Swoole\WebSocket\Server;

use function Swoole\Coroutine\run;
use function Swoole\Coroutine\go;

$pm = new ProcessManager;

$pm->parentFunc = function ($pid) use ($pm) {
run(function () use ($pm) {
$n = MAX_CONCURRENCY_LOW;
while ($n--) {
go(function () use ($pm) {
$cli = new Client('127.0.0.1', $pm->getFreePort());
$cli->setHeaders(['KeepAlive' => 'off', 'Connection' => 'close']);
for ($i = MAX_REQUESTS_LOW; $i--;) {
$cli->get('/');
Assert::contains($cli->getBody(), 'swoole_http_server: sendfile with dispatch_mode=7');
}
});
}
});
echo "DONE\n";
$pm->kill();
};

$pm->childFunc = function () use ($pm) {
$http = new Server('0.0.0.0', $pm->getFreePort(), SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$http->set([
'log_file' => '/dev/null',
'dispatch_mode' => 7,
]);
$http->on('workerStart', function () use ($pm) {
$pm->wakeup();
});
$http->on('request', function (swoole_http_request $request, swoole_http_response $response) {
$response->sendfile(__FILE__);
});

$http->on('message', function(){});
$http->start();
};
$pm->childFirst();
$pm->run();
?>
--EXPECT--
DONE
54 changes: 54 additions & 0 deletions tests/swoole_http_server/sendfile_with_dispatch_mode_7.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
--TEST--
swoole_http_server: sendfile with dispatch_mode=7
--SKIPIF--
<?php require __DIR__ . '/../include/skipif.inc'; ?>
--FILE--
<?php
require __DIR__ . '/../include/bootstrap.php';

use Swoole\Coroutine\Http\Client;
use Swoole\WebSocket\Server;

use function Swoole\Coroutine\run;
use function Swoole\Coroutine\go;

$pm = new ProcessManager;

$pm->parentFunc = function ($pid) use ($pm) {
run(function () use ($pm) {
$n = MAX_CONCURRENCY_LOW;
while ($n--) {
go(function () use ($pm) {
$cli = new Client('127.0.0.1', $pm->getFreePort());
for ($i = MAX_REQUESTS_LOW; $i--;) {
$cli->get('/');
Assert::contains($cli->getBody(), 'swoole_http_server: sendfile with dispatch_mode=7');
}
});
}
});
echo "DONE\n";
$pm->kill();
};

$pm->childFunc = function () use ($pm) {
$http = new Server('0.0.0.0', $pm->getFreePort(), SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$http->set([
'log_file' => '/dev/null',
'dispatch_mode' => 7,
]);
$http->on('workerStart', function () use ($pm) {
$pm->wakeup();
});
$http->on('request', function (swoole_http_request $request, swoole_http_response $response) {
$response->sendfile(__FILE__);
});

$http->on('message', function(){});
$http->start();
};
$pm->childFirst();
$pm->run();
?>
--EXPECT--
DONE
47 changes: 47 additions & 0 deletions tests/swoole_http_server/sendfile_with_ssl.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
--TEST--
swoole_http_server: sendfile with ssl
--SKIPIF--
<?php require __DIR__ . '/../include/skipif.inc'; ?>
--FILE--
<?php
require __DIR__ . '/../include/bootstrap.php';

$pm = new ProcessManager;
$pm->parentFunc = function ($pid) use ($pm) {
for ($i = MAX_REQUESTS; $i--;) {
$send_file = get_safe_random(mt_rand(0, 65535 * 10));
file_put_contents('/tmp/sendfile.txt', $send_file);

$ctxArr = [
'verify_peer' => false,
];
$ctx = stream_context_create(['ssl' => $ctxArr]);
$recv_file = file_get_contents("https://127.0.0.1:{$pm->getFreePort()}", false, $ctx);
Assert::same($send_file, $recv_file);
}
echo "DONE\n";
$pm->kill();
};
$pm->childFunc = function () use ($pm) {
$http = new swoole_http_server('127.0.0.1', $pm->getFreePort(), SERVER_MODE_RANDOM, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$http->set([
'worker_num' => 1,
'log_file' => '/dev/null',
'ssl_cert_file' => SSL_FILE_DIR . '/server.crt',
'ssl_key_file' => SSL_FILE_DIR . '/server.key',
]);
$http->on('workerStart', function () use ($pm) {
$pm->wakeup();
});
$http->on('request', function (swoole_http_request $request, swoole_http_response $response) {
$response->header('Content-Type', 'application/octet-stream');
$response->header('Content-Disposition', 'attachment; filename=recvfile.txt');
$response->sendfile('/tmp/sendfile.txt');
});
$http->start();
};
$pm->childFirst();
$pm->run();
?>
--EXPECT--
DONE
2 changes: 1 addition & 1 deletion tests/swoole_runtime/curl_native/yield_in_callback.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Fatal error: Uncaught Swoole\Error: API must be called in the coroutine in %s:%d
Stack trace:
#0 %s(%d): Swoole\Coroutine::sleep(0.1)
#1 [internal function]: {closure}(Resource id #%d, 'HTTP/1.1 200 OK...')
#2 @swoole-src/library/alias_ns.php(%d): Swoole\Coroutine\Scheduler->start()
#2 @swoole-src/library/core/Coroutine/functions.php(%d): Swoole\Coroutine\Scheduler->start()
#3 %s(%d): Swoole\Coroutine\run(Object(Closure))
#4 {main}
thrown in %s on line %d

0 comments on commit a131fa8

Please sign in to comment.