与其他客户端相比,在 flutter post 请求中得到不同的响应

getting different response in flutter post request compared to other rest clients

如果使用 flutter 调用它,我会从 api 得到不同的响应 YARC REST 客户端中的响应: 颤振中的响应: 第一行是 json 发送到 api.

api 日志中的错误显示:

Failed to parse json data from JsonRpc@::ffff:192.168.0.243: Error: illegal value at Line: 0, Column: 0

Main.dart:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:smart_home/user_model.dart';
import 'package:http/http.dart' as http;
void main() {
  runApp(const MyApp());
}

Future req(String col) async{
  var data = json.encode({
    "command":"color",
    "color":[255,0,0],
    "priority":50,
    "origin":"My Fancy App"
  });

  print(data);
  final response = await http.post(Uri.parse("http://192.168.0.151:8090/json-rpc"),
      body: data,
      headers: {"Authorization": "token 46a2032e-da1b-4c20-b690-27413aa43589"}
  );
  print(response.body);
  if(response.statusCode==200){
    final String responseString = response.body;
    return userModelFromJson(responseString);
  }
  else
  return null;
}
class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  var selectedvalue = null;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      home: Scaffold(
        appBar: AppBar(
          title: Text("Led Controls",
            style: TextStyle(fontSize: 25),),
        ),
        body: Column(
          children: [
            Container(
              padding: EdgeInsets.fromLTRB(20, 10, 20, 10),
              child: DropdownButton(
                value: selectedvalue,
                items: <String>['Static color', 'Effects'].map((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
                onChanged: (value) {
                  setState(() {
                    selectedvalue=value.toString();
                  });
                },
                isExpanded: true,
                hint: Text("Select Operating Mode"),
              ),
            ),
            if(selectedvalue=="Static color") Container(
              //padding: EdgeInsets.fromLTRB(20, 10, 20, 10),
                child: ColorPicker(
                    pickerColor: Colors.white,
                    paletteType: PaletteType.hueWheel,
                    onColorChanged: (x) async{
                      String col="[${x.red.toString()},${x.green.toString()},${x.blue.toString()}]";
                      final UserModel? resp = await req(col);
                      //print(resp!.success);
                },
                )
            )

          ],
        ),
      ),
    );
  }
}



这是我的第一个 flutter 项目,所以我仍然不完全确定这些东西是如何工作的。

更新: 它在 YARC、邮递员和 python 上运行良好。它不适用于高级休息客户端 (arc) 和 flutter。

这是由 Hyperion 服务器中的错误引起的。它将 HTTP headers 视为区分大小写。 (这违反了相关的 RFC。)Dart 总是强制 headers 为小写。在这种情况下,服务器正在寻找 Content-Length,但 Dart 发送 content-length,服务器(错误地)没有弄清楚是同一件事。

幸运的是,Dart 中有一种方法可以强制 headers 的大小写,但你必须多写几行 boiler-plate。这是一个工作示例:

import 'dart:convert';
import 'dart:io';

void main() async {
  // encode the post body as JSON and then UTF8 bytes
  final dataBytes = utf8.encode(json.encode({
    'command': 'color',
    'color': [255, 0, 0],
    'priority': 50,
    'origin': 'My Dart App'
  }));

  // use the low level HttpClient to get control of the header case
  final client = HttpClient();
  final request = await client.post('127.0.0.1', 8090, '/json-rpc');
  // manually add the content length header to preserve its case
  request.headers.add(
    'Content-Length', // note the upper case string - try it with lower case (spoiler it fails)
    dataBytes.length.toString(),
    preserveHeaderCase: true,
  );
  // optional - add other headers (e.g. Auth) here
  // request.headers.add(/*some other header*/);
  
  // send the body bytes
  request.add(dataBytes);
  
  // 'close' the request to send it, and get a response
  final response = await request.close();
  print(response.statusCode);

  // turn the streamed response back to a string so that it can be parsed as JSON
  final responseBody = await response.transform(utf8.decoder).join();
  print(responseBody);
  
  // close the client (or re-use it if you prefer)
  client.close();
}