Skip to content

Commit fe43ef0

Browse files
committed
Fix the issue of incorrect multipart content-type on the HTTP server.
1 parent a3123af commit fe43ef0

File tree

4 files changed

+91
-10
lines changed

4 files changed

+91
-10
lines changed

ext-src/php_swoole_cxx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ class CharPtr {
556556
str_ = estrndup(str, len);
557557
}
558558

559-
void assign_tolower(char *str, size_t len) {
559+
void assign_tolower(const char *str, size_t len) {
560560
release();
561561
str_ = zend_str_tolower_dup(str, len);
562562
}

ext-src/php_swoole_http.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,15 @@ struct Context {
158158
multipart_parser *mt_parser;
159159

160160
uint16_t input_var_num;
161-
char *current_header_name;
161+
const char *current_header_name;
162162
size_t current_header_name_len;
163163
char *current_input_name;
164164
size_t current_input_name_len;
165165
char *current_form_data_name;
166166
size_t current_form_data_name_len;
167167
zval *current_multipart_header;
168+
const char *tmp_content_type;
169+
size_t tmp_content_type_len;
168170
String *form_data_buffer;
169171

170172
std::string upload_tmp_dir;

ext-src/swoole_http_request.cc

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ static int http_request_on_query_string(swoole_http_parser *parser, const char *
267267

268268
static int http_request_on_header_field(swoole_http_parser *parser, const char *at, size_t length) {
269269
HttpContext *ctx = (HttpContext *) parser->data;
270-
ctx->current_header_name = (char *) at;
270+
ctx->current_header_name = at;
271271
ctx->current_header_name_len = length;
272272
return 0;
273273
}
@@ -342,7 +342,7 @@ bool swoole_http_token_list_contains_value(const char *at, size_t length, const
342342
static int http_request_on_header_value(swoole_http_parser *parser, const char *at, size_t length) {
343343
HttpContext *ctx = (HttpContext *) parser->data;
344344
zval *zheader = ctx->request.zheader;
345-
char *header_name = ctx->current_header_name;
345+
const char *header_name = ctx->current_header_name;
346346
size_t header_len = ctx->current_header_name_len;
347347

348348
if (ctx->parse_cookie && SW_STRCASEEQ(header_name, header_len, "cookie")) {
@@ -546,7 +546,11 @@ static int multipart_body_on_header_value(multipart_parser *p, const char *at, s
546546
zval *z_multipart_header = sw_malloc_zval();
547547
array_init(z_multipart_header);
548548

549-
add_assoc_string(z_multipart_header, "type", (char *) "");
549+
if (ctx->tmp_content_type) {
550+
add_assoc_stringl(z_multipart_header, "type", ctx->tmp_content_type, ctx->tmp_content_type_len);
551+
} else {
552+
add_assoc_string(z_multipart_header, "type", (char *) "");
553+
}
550554
add_assoc_string(z_multipart_header, "tmp_name", (char *) "");
551555
add_assoc_long(z_multipart_header, "size", 0);
552556

@@ -563,11 +567,16 @@ static int multipart_body_on_header_value(multipart_parser *p, const char *at, s
563567
ctx->current_multipart_header = z_multipart_header;
564568
}
565569
zval_ptr_dtor(&tmp_array);
566-
} else if (SW_STRCASEEQ(header_name, header_len, "content-type") && ctx->current_multipart_header) {
567-
zval *z_multipart_header = ctx->current_multipart_header;
568-
zval *zerr = zend_hash_str_find(Z_ARRVAL_P(z_multipart_header), ZEND_STRL("error"));
569-
if (zerr && Z_TYPE_P(zerr) == IS_LONG && Z_LVAL_P(zerr) == HTTP_UPLOAD_ERR_OK) {
570-
add_assoc_stringl(z_multipart_header, "type", (char *) at, length);
570+
} else if (SW_STRCASEEQ(header_name, header_len, "content-type")) {
571+
if (ctx->current_multipart_header) {
572+
zval *z_multipart_header = ctx->current_multipart_header;
573+
zval *zerr = zend_hash_str_find(Z_ARRVAL_P(z_multipart_header), ZEND_STRL("error"));
574+
if (zerr && Z_TYPE_P(zerr) == IS_LONG && Z_LVAL_P(zerr) == HTTP_UPLOAD_ERR_OK) {
575+
add_assoc_stringl(z_multipart_header, "type", (char *) at, length);
576+
}
577+
} else {
578+
ctx->tmp_content_type = at;
579+
ctx->tmp_content_type_len = length;
571580
}
572581
} else if (SW_STRCASEEQ(header_name, header_len, SW_HTTP_UPLOAD_FILE)) {
573582
zval *z_multipart_header = ctx->current_multipart_header;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
--TEST--
2+
swoole_http_server: tmp content-type
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/../include/skipif.inc';
6+
?>
7+
--FILE--
8+
<?php
9+
require __DIR__ . '/../include/bootstrap.php';
10+
require_once TESTS_LIB_PATH . '/vendor/autoload.php';
11+
12+
use Swoole\Runtime;
13+
use GuzzleHttp\Client as GuzzleHttpClient;
14+
use Swoole\Http\Server;
15+
use Swoole\Http\Request;
16+
use Swoole\Http\Response;
17+
18+
use function Swoole\Coroutine\run;
19+
20+
Runtime::enableCoroutine(SWOOLE_HOOK_NATIVE_CURL);
21+
22+
register_shutdown_function(function (){
23+
phpt_show_usage();
24+
});
25+
26+
$pm = new SwooleTest\ProcessManager;
27+
$pm->parentFunc = function () use ($pm) {
28+
run(function () use ($pm) {
29+
$client = new GuzzleHttpClient();
30+
$baseUrl = 'http://127.0.0.1:' . $pm->getFreePort();
31+
$res = $client->post($baseUrl . '/', [
32+
'multipart' => [
33+
[
34+
'name' => 'file',
35+
'contents' => fopen(__FILE__, 'r'),
36+
'filename' => basename(__FILE__),
37+
'headers' => ['Content-Type' => 'application/php-script']
38+
],
39+
],
40+
]);
41+
42+
$status = $res->getStatusCode();
43+
$body = $res->getBody()->getContents();
44+
Assert::eq($status, 200);
45+
$result = json_decode($body, true);
46+
Assert::eq($result['file']['name'], basename(__FILE__));
47+
Assert::eq($result['file']['type'], 'application/php-script');
48+
});
49+
echo "DONE\n";
50+
$pm->kill();
51+
};
52+
53+
$pm->childFunc = function () use ($pm) {
54+
$http = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE);
55+
$http->set([
56+
'log_file' => '/dev/null',
57+
]);
58+
$http->on('workerStart', function () use ($pm) {
59+
$pm->wakeup();
60+
});
61+
$http->on('request', function (Request $request, Response $response) use ($http) {
62+
$response->end(json_encode($request->files));
63+
});
64+
$http->start();
65+
};
66+
$pm->childFirst();
67+
$pm->run();
68+
?>
69+
--EXPECT--
70+
DONE

0 commit comments

Comments
 (0)