我在 Dart 中實作了一個服務器,并且想要決議 POST 請求正文。我正在使用 Postman / curl(和 Flutter 應用程式)來測驗服務器。當我使用 訪問服務器localhost時,POST 請求正文得到正確處理,服務器按預期作業。但是,當我嘗試使用域名和 Nginx 處理作為反向代理訪問它時,服務器在嘗試處理請求正文時崩潰。
使用相同的 nginx 配置,但 NodeJS 作為帶有包的服務器(在其他專案中)body-parser,NodeJS 服務器能夠讀取正文。
請求的curl版本:
curl --location --request POST 'https://insanichess.com/api/auth/register' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"email": "[email protected]",
"password": "test_pwd"
}'
Nginx conf 檔案(使用 Certbot 生成):
server {
server_name insanichess.com www.insanichess.com;
location / {
proxy_pass http://localhost:4040;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/insanichess.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/insanichess.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}server {
if ($host = www.insanichess.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = insanichess.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name insanichess.com www.insanichess.com;
return 404; # managed by Certbot
}
Dart 代碼的重要部分:
// insanichess_server.dart
/// Starts the server.
Future<void> start() async {
final InternetAddress address = InternetAddress.loopbackIPv4;
final int port =
int.parse(Platform.environment['INSANICHESS_PORT'] ?? '4040');
final HttpServer server = await HttpServer.bind(address, port);
_logger.info('InsanichessServer.create', 'Server listening on port $port');
await _handleRequests(onServer: server);
}
/// Passes every request [onServer] to [_router].
Future<void> _handleRequests({required HttpServer onServer}) async {
await for (final HttpRequest request in onServer) {
await _router.handle(request);
}
}
// auth_controller.dart
Future<void> handleRegistration(HttpRequest request) async {
if (request.method != 'POST' ||
request.contentLength <= 0 ||
request.headers.contentType?.value != ContentType.json.value) {
return respondWithBadRequest(request);
}
final String content = await utf8.decodeStream(request);
final Map<String, dynamic> body = jsonDecode(content);
//...
}
服務器崩潰
Unhandled exception:
FormatException: Unexpected end of input (at character 1)
^
#0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1405:5)
#1 _ChunkedJsonParser.close (dart:convert-patch/convert_patch.dart:523:7)
#2 _parseJson (dart:convert-patch/convert_patch.dart:41:10)
#3 JsonDecoder.convert (dart:convert/json.dart:506:36)
#4 JsonCodec.decode (dart:convert/json.dart:157:41)
#5 jsonDecode (dart:convert/json.dart:96:10)
#6 AuthController.handleRegistration (package:insanichess_server/src/controller/api/auth/auth.dart:79:39)
<asynchronous suspension>
#7 ApiRouter.handle (package:insanichess_server/src/router/api/api.dart:29:16)
<asynchronous suspension>
#8 ICRouter.handle (package:insanichess_server/src/router/ic_router.dart:27:16)
<asynchronous suspension>
#9 InsanichessServer._handleRequests (package:insanichess_server/src/insanichess_server.dart:38:7)
<asynchronous suspension>
#10 InsanichessServer.start (package:insanichess_server/src/insanichess_server.dart:32:5)
<asynchronous suspension>
#11 main (file:///home/campovski/insanichess/server/bin/main.dart:17:3)
<asynchronous suspension>
我已嘗試按照類似的 StackOverflow 答案中的建議在 nginx 中設定 CORS 和 X-** 標頭,但是錯誤始終相同。x-www-form-urlencoded版本也沒有幫助。
content.length之前列印jsonDecode會給出 0,但是Content-Length在處理程式中列印標題值會給出正確的值(我認為它是 63 或其他值)。
這是處理程式在請求中收到的所有標頭:
user-agent: curl/7.64.1
content-type: application/json; charset=utf-8
connection: upgrade
accept: */*
content-length: 63
host: insanichess.com
我認為問題出在使用 nginx 代理上,因為直接在 localhost 上查詢是可行的,但是幾乎相同的設定使用 NodeJS 作為后端似乎很奇怪。該專案的完整源代碼可在GitHub 上獲得,以防您想仔細查看。
uj5u.com熱心網友回復:
這似乎是一個問題
final Map<String, dynamic> body = jsonDecode(content);
或者在 NGINX 上具有重定向狀態。您應該使用 307 回應代碼。來源
uj5u.com熱心網友回復:
出于某種原因,從 nginx 配置中的塊中洗掉所有內容,但幫助location /除外。proxy_pass這個配置現在可以了:
server {
server_name insanichess.com www.insanichess.com;
location / {
proxy_pass http://localhost:4040;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/insanichess.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/insanichess.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}server {
if ($host = www.insanichess.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = insanichess.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name insanichess.com www.insanichess.com;
return 404; # managed by Certbot
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/410156.html
標籤:
