roadrunner
roadrunner copied to clipboard
[🐛 BUG]: Unable to upload file when raw_body enabled
No duplicates 🥲.
- [X] I have searched for a similar issue in our bug tracker and didn't find any solutions.
What happened?
I'm trying to upload file, but RR server is failing.
Issue looks pretty similar to https://github.com/roadrunner-server/roadrunner/issues/1765, but it's already fixed and released, but my problem is still here.
Version (rr --version)
2023.3.8 (build time: 2023-12-14T16:05:31+0000, go1.21.5), OS: darwin, arch: arm64
How to reproduce the issue?
On file upload with raw_body: true will RR fail.
Of course, firstly I was thought that there is some issue with app code, so I've simplified worker as much as possible and if you'll try to upload file to worker like attached below it will fail anyway.
<?php
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
$worker = new \Spiral\RoadRunner\Http\PSR7Worker(
\Spiral\RoadRunner\Worker::create(),
new \Nyholm\Psr7\Factory\Psr17Factory(),
new \Nyholm\Psr7\Factory\Psr17Factory(),
new \Nyholm\Psr7\Factory\Psr17Factory(),
);
while ($request = $worker->waitRequest()) {
try {
$worker->respond(new \Nyholm\Psr7\Response());
} catch (Throwable $e) {
$worker->getWorker()->error((string) $e);
}
}
.rr.yaml which will reproduce this error
version: '3'
rpc:
listen: tcp://127.0.0.1:6001
server:
command: "php src/worker.php"
relay: pipes
logs:
mode: development
level: debug
encoding: console
output: stderr
err_output: stderr
http:
address: 127.0.0.1:8080
internal_error_code: 505
access_logs: false
raw_body: true
middleware: [ "static" ]
uploads:
dir: "/tmp"
static:
dir: "public/"
forbid: [ "index.php" ]
But if you'll change raw_body: false it'll work flawless
Relevant log output
2023-12-16T13:44:54+0000 ERROR http internal server error {"message": "http_plugin: 2023/12/16 13:44:54 http: panic serving 127.0.0.1:53182: interface conversion: interface {} is handler.dataTree, not []uint8\ngoroutine 210 [running]:\nnet/http.(*conn).serve.func1()\n\tnet/http/server.go:1868 +0xb0\npanic({0x103d47920?, 0x1400011c7e0?})\n\truntime/panic.go:920 +0x26c\ngithub.com/roadrunner-server/http/v4/handler.(*Request).Payload(...)\n\tgithub.com/roadrunner-server/http/[email protected]/handler/request.go:172\ngithub.com/roadrunner-server/http/v4/handler.(*Handler).ServeHTTP(0x1400086c000, {0x1040671e0, 0x140000a64e0}, 0x1022e97b0?)\n\tgithub.com/roadrunner-server/http/[email protected]/handler/handler.go:139 +0x1764\ngithub.com/roadrunner-server/http/v4.(*Plugin).ServeHTTP(0x1400088df40, {0x1040671e0, 0x140000a64e0}, 0x14000c32100)\n\tgithub.com/roadrunner-server/http/[email protected]/plugin.go:205 +0x3f0\ngithub.com/roadrunner-server/http/v4.(*Plugin).applyBundledMiddleware.MaxRequestSize.func1({0x1040671e0, 0x140000a64e0}, 0x3?)\n\tgithub.com/roadrunner-server/http/[email protected]/middleware/maxRequest.go:15 +0xb0\nnet/http.HandlerFunc.ServeHTTP(0x14001006200?, {0x1040671e0?, 0x140000a64e0?}, 0x103558d38?)\n\tnet/http/server.go:2136 +0x38\ngithub.com/roadrunner-server/http/v4.(*Plugin).applyBundledMiddleware.NewLogMiddleware.(*lm).Log.func5({0x1040672d0, 0x1400099a078}, 0x0?)\n\tgithub.com/roadrunner-server/http/[email protected]/middleware/log.go:125 +0x140\nnet/http.HandlerFunc.ServeHTTP(0x0?, {0x1040672d0?, 0x1400099a078?}, 0x1?)\n\tnet/http/server.go:2136 +0x38\ngithub.com/roadrunner-server/static/v4.(*Plugin).Middleware.func1({0x1040672d0, 0x1400099a078}, 0x14001006200)\n\tgithub.com/roadrunner-server/static/[email protected]/plugin.go:149 +0x4e8\nnet/http.HandlerFunc.ServeHTTP(0x1400092c050?, {0x1040672d0?, 0x1400099a078?}, 0xc1578855a02b0028?)\n\tnet/http/server.go:2136 +0x38\ngithub.com/roadrunner-server/prometheus/v4.(*Plugin).Middleware.func1({0x1040660c8, 0x140009b6460}, 0x14001006200)\n\tgithub.com/roadrunner-server/prometheus/[email protected]/plugin.go:131 +0x464\nnet/http.HandlerFunc.ServeHTTP(0x10405f070?, {0x1040660c8?, 0x140009b6460?}, 0x6?)\n\tnet/http/server.go:2136 +0x38\nnet/http.serverHandler.ServeHTTP(...)\n\tnet/http/server.go:2938\nnet/http.(*conn).serve(0x14000c621b0, {0x10406e968, 0x14000bd01b0})\n\tnet/http/server.go:2009 +0x5b0\ncreated by net/http.(*Server).Serve in goroutine 110\n\tnet/http/server.go:3086 +0x4cc\n"}
Hey @m157y 👋
Please attach at least a cURL sample request to reproduce your behavior.
Sure
curl 'http://localhost:8080/' \
-H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryCeAZDfHPsreuikmt' \
--data-raw $'------WebKitFormBoundaryCeAZDfHPsreuikmt\r\nContent-Disposition: form-data; name="newsItem[url]"\r\n\r\ntest\r\n------WebKitFormBoundaryCeAZDfHPsreuikmt\r\nContent-Disposition: form-data; name="newsItem[title]"\r\n\r\nTest\r\n------WebKitFormBoundaryCeAZDfHPsreuikmt\r\nContent-Disposition: form-data; name="newsItem[preview]"\r\n\r\nTest news\r\n------WebKitFormBoundaryCeAZDfHPsreuikmt\r\nContent-Disposition: form-data; name="newsItem[text]"\r\n\r\nTest\r\n------WebKitFormBoundaryCeAZDfHPsreuikmt\r\nContent-Disposition: form-data; name="newsItem[imageUrl]"; filename="600x600.jpeg"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundaryCeAZDfHPsreuikmt\r\nContent-Disposition: form-data; name="newsItem[isActive]"\r\n\r\n0\r\n------WebKitFormBoundaryCeAZDfHPsreuikmt--\r\n'
Cool, thanks. I'm currently working on updating and removing this raw_body option at all.
I double-checked this case and I guess I should improve the docs, because multipart data comes to the worker already parsed (kind of raw format).
So, this is completely ok to not use raw_body with multipart (most use-cases for this flag is for the url-encoded data).
btw, we're moving to the protobuf data format between the worker and RR (instead of JSON), and soon this option would be deprecated and all will be in a kind of raw format.
ref: #1696