Reghunaath A A
Reghunaath A A

Reputation: 3210

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

I'm getting different response from the api if call it using flutter Response in YARC REST Client: enter image description here enter image description here Response in Flutter: enter image description here 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

Answers (1)

Richard Heap
Richard Heap

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

Related Questions