Reputation: 3210
I'm getting different response from the api if call it using flutter
Response in YARC REST Client:
Response in Flutter:
The first line is the json sent to the api.
The error showm in api log:
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);
},
)
)
],
),
),
);
}
}
This is my first flutter project so I'm still not completely sure of how stuff work.
Update: It is working fine on YARC, postman and python. It is not working on advanced rest client(arc) and flutter.
Upvotes: 1
Views: 1433
Reputation: 51770
This is caused by a bug in the Hyperion server. It is treating the HTTP headers as case sensitive. (This violates the relevant RFC.) Dart always forces the headers to lower case. In this case the server is looking for Content-Length
, but Dart sends content-length
, which the server (incorrectly) doesn't figure out are the same thing.
Luckily there's a way in Dart to force the case of headers, but you have to write a few more lines of boiler-plate. Here's a working example:
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();
}
Upvotes: 2