io icon indicating copy to clipboard operation
io copied to clipboard

Error: Failed to parse HTTP, 32 is expected to be a Hex digit on get request

Open Guru-Zachw opened this issue 2 years ago • 3 comments

When making a get request failure to read the response (even the Stream<List> ) Tested on android and linux(both with flutter and with a dart script) The code:

import 'dart:io';

Future<void> main(List<String> arguments) async {
  var request = await HttpClient()
      .getUrl(Uri.parse('http://10.22.2.214/settings/time'));
  var response = await request.close();

  await for (var val in response) {
    print('################################\n\n');
    print(val);
  }
}

throws

E/flutter (19504): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: HttpException: Failed to parse HTTP, 32 is expected to be a Hex digit, uri = http://10.22.2.214/settings/time
E/flutter (19504): #0      _HttpIncoming.listen.<anonymous closure> (dart:_http/http_impl.dart:443:7)
E/flutter (19504): #1      _invokeErrorHandler (dart:async/async_error.dart:45:24)
E/flutter (19504): #2      _HandleErrorStream._handleError (dart:async/stream_pipe.dart:269:9)
E/flutter (19504): #3      _ForwardingStreamSubscription._handleError (dart:async/stream_pipe.dart:157:13)
E/flutter (19504): #4      _rootRunBinary (dart:async/zone.dart:1450:47)
E/flutter (19504): #5      _CustomZone.runBinary (dart:async/zone.dart:1342:19)
E/flutter (19504): #6      _CustomZone.runBinaryGuarded (dart:async/zone.dart:1252:7)
E/flutter (19504): #7      _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:360:15)
E/flutter (19504): #8      _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:378:7)
E/flutter (19504): #9      _DelayedError.perform (dart:async/stream_impl.dart:602:14)
E/flutter (19504): #10     _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)
E/flutter (19504): #11     _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:663:7)
E/flutter (19504): #12     _rootRun (dart:async/zone.dart:1418:47)
E/flutter (19504): #13     _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (19504): #14     _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (19504): #15     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (19504): #16     _rootRun (dart:async/zone.dart:1426:13)
E/flutter (19504): #17     _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (19504): #18     _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (19504): #19     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (19504): #20     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter (19504): #21     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
E/flutter (19504):

When expecting this response (hit from curl with no state changes hitting the endpoint via .getUrl right after failed)

HTTP/1.1 200 OK
Content-Type: text/html
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Headers: *
Connection: close
Accept-Ranges: none
Transfer-Encoding: chunked

<!DOCTYPE html><html lang="en"><head><meta name="viewport" content="width=500">
<meta charset="utf-8"><title>Time Settings</title><script>
var d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings")}function B(){window.open("/settings","_self")}function S(){BTa(),GetV(),Cs(),FC()}function gId(t){return d.getElementById(t)}function Cs(){gId("cac").style.display="none",gId("coc").style.display="block",gId("ccc").style.display="none",gId("ca").selected&&(gId("cac").style.display="block"),gId("cc").selected&&(gId("coc").style.display="none",gId("ccc").style.display="block"),gId("cn").selected&&(gId("coc").style.display="none")}function BTa(){var t="<tr><th>Active</th><th>Hour</th><th>Minute</th><th>Preset</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr>";for(i=0;i<8;i++)for(t+='<tr><td><input name="W'+i+'" id="W'+i+'" type="number" style="display:none"><input id="W'+i+'0" type="checkbox"></td><td><input name="H'+i+'" type="number" min="0" max="24"></td><td><input name="N'+i+'" type="number" min="0" max="59"></td><td><input name="T'+i+'" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W'+i+j+'" type="checkbox"></td>';for(t+='<tr><td><input name="W8" id="W8" type="number" style="display:none"><input id="W80" type="checkbox"></td><td>Sunrise<input name="H8" value="255" type="hidden"></td><td><input name="N8" type="number" min="-59" max="59"></td><td><input name="T8" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W8'+j+'" type="checkbox"></td>';for(t+='<tr><td><input name="W9" id="W9" type="number" style="display:none"><input id="W90" type="checkbox"></td><td>Sunset<input name="H9" value="255" type="hidden"></td><td><input name="N9" type="number" min="-59" max="59"><td><input name="T9" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W9'+j+'" type="checkbox"></td>';gId("TMT").innerHTML=t}function FC(){for(j=0;j<8;j++)for(i=0;i<10;i++)gId("W"+i+j).checked=gId("W"+i).value>>j&1}function Wd(){for(a=[0,0,0,0,0,0,0,0,0,0],i=0;i<10;i++){for(m=1,j=0;j<8;j++)a[i]+=gId("W"+i+j).checked*m,m*=2;gId("W"+i).value=a[i]}}function addRow(t,e,n,i){var d=gId("macros"),u=d.rows.length,c=d.insertRow(u);document.createElement("td");c.insertCell(0).innerHTML=`Button ${t}:`,c.insertCell(1).innerHTML=`<input name="MP${t}" type="number" min="0" max="250" value="${e}" required>`,c.insertCell(2).innerHTML=`<input name="ML${t}" type="number" min="0" max="250" value="${n}" required>`,c.insertCell(3).innerHTML=`<input name="MD${t}" type="number" min="0" max="250" value="${i}" required>`}function GetV() {
d.Sf.NT.checked=1;d.Sf.NS.value="Ntp-wwv.nist.gov";d.Sf.CF.checked=0;d.Sf.TZ.selectedIndex=6;d.Sf.UO.value=0;d.Sf.LN.value="0.00";d.Sf.LT.value="0.00";d.getElementsByClassName("times")[0].innerHTML="2106-2-7, 12:39:17 AM";d.Sf.OL.selectedIndex=0;d.Sf.O1.value=0;d.Sf.O2.value=0;d.Sf.OM.value=0;d.Sf.OS.checked=0;d.Sf.O5.checked=0;d.Sf.CX.value="HHMMSS";d.Sf.CB.checked=1;d.Sf.CE.checked=0;d.Sf.CY.value=22;d.Sf.CI.value=1;d.Sf.CD.value=1;d.Sf.CH.value=2;d.Sf.CM.value=1;d.Sf.CS.value=1;d.Sf.A0.value=0;d.Sf.A1.value=0;d.Sf.MC.value=0;d.Sf.MN.value=0;addRow(0,0,0,0);addRow(1,0,0,0);addRow(2,0,0,0);addRow(3,0,0,0);d.Sf.H0.value=9;d.Sf.N0.value=24;d.Sf.T0.value=1;d.Sf.W0.value=255;d.Sf.H1.value=9;d.Sf.N1.value=38;d.Sf.T1.value=2;d.Sf.W1.value=255;d.Sf.H2.value=0;d.Sf.N2.value=0;d.Sf.T2.value=0;d.Sf.W2.value=255;d.Sf.H3.value=0;d.Sf.N3.value=0;d.Sf.T3.value=0;d.Sf.W3.value=255;d.Sf.H4.value=0;d.Sf.N4.value=0;d.Sf.T4.value=0;d.Sf.W4.value=255;d.Sf.H5.value=0;d.Sf.N5.value=0;d.Sf.T5.value=0;d.Sf.W5.value=255;d.Sf.H6.value=0;d.Sf.N6.value=0;d.Sf.T6.value=0;d.Sf.W6.value=255;d.Sf.H7.value=0;d.Sf.N7.value=0;d.Sf.T7.value=0;d.Sf.W7.value=255;d.Sf.N8.value=0;d.Sf.T8.value=0;d.Sf.W8.value=0;d.Sf.N9.value=0;d.Sf.T9.value=0;d.Sf.W9.value=0;}</script><style>body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%;margin:0}hr{border-color:#666}a{color:#28f;text-decoration:none}.btn,button{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:12px 8px 8px;padding:1px 6px;cursor:pointer;text-decoration:none}.lnk{border:0}.helpB{text-align:left;position:absolute;width:60px}input{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}input:disabled{color:#888}input[type=number]{width:4em;margin:2px}input[type=number].xxl{width:100px}input[type=number].xl{width:85px}input[type=number].l{width:63px}input[type=number].m{width:56px}input[type=number].s{width:49px}input[type=number].xs{width:42px}input[type=checkbox]{transform:scale(1.5);margin-right:10px}select{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}td{padding:2px}.d5{width:4.5em!important}#toast{opacity:0;background-color:#444;border-radius:5px;bottom:64px;color:#fff;font-size:17px;padding:16px;pointer-events:none;position:fixed;text-align:center;z-index:5;transform:translateX(-50%);max-width:90%;left:50%}#toast.show{opacity:1;background-color:#264;animation:fadein .5s,fadein .5s 2.5s reverse}#toast.error{opacity:1;background-color:#b21;animation:fadein .5s}</style></head><body onload="S()"><form
 id="form_s" name="Sf" method="post" onsubmit="Wd()"><div class="helpB"><button 
type="button" onclick="H()">?</button></div><button type="button" onclick="B()">
Back</button><button type="submit">Save</button><hr><h2>Time setup</h2>
Get time from NTP server: <input type="checkbox" name="NT"><br><input name="NS" 
maxlength="32"><br>Use 24h format: <input type="checkbox" name="CF"><br>
Time zone: <select name="TZ"><option value="0" selected="selected">GMT(UTC)
</option><option value="1">GMT/BST</option><option value="2">CET/CEST</option>
<option value="3">EET/EEST</option><option value="4">US-EST/EDT</option><option 
value="5">US-CST/CDT</option><option value="6">US-MST/MDT</option><option 
value="7">US-AZ</option><option value="8">US-PST/PDT</option><option value="9">
CST(AWST)</option><option value="10">JST(KST)</option><option value="11">
AEST/AEDT</option><option value="12">NZST/NZDT</option><option value="13">
North Korea</option><option value="14">IST (India)</option><option value="15">
CA-Saskatchewan</option><option value="16">ACST</option><option value="17">
ACST/ACDT</option><option value="18">HST (Hawaii)</option><option value="19">
NOVT (Novosibirsk)</option><option value="20">AKST/AKDT (Anchorage)</option>
<option value="21">MX-CST/CDT</option></select><br>UTC offset: <input name="UO" 
type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br>
Current local time is <span class="times">unknown</span>.<br>Latitude (N): 
<input name="LT" type="number" min="-66.6" max="66.6" step="0.01">
 Longitude (E): <input name="LN" type="number" min="-180" max="180" step="0.01">
<div id="sun" class="times"></div><h3>Clock</h3>Clock Overlay: <select 
name="OL" onchange="Cs()"><option value="0" id="cn" selected="selected">None
</option><option value="1" id="ca">Analog Clock</option><option value="2">
Single Digit Clock</option><option value="3" id="cc">Cronixie Clock</option>
</select><br><div id="coc">First LED: <input name="O1" type="number" min="0" 
max="255" required> Last LED: <input name="O2" type="number" min="0" max="255" 
required><br><div id="cac">12h LED: <input name="OM" type="number" min="0" 
max="255" required><br>Show 5min marks: <input type="checkbox" name="O5"><br>
</div>Seconds (as trail): <input type="checkbox" name="OS"><br></div><div 
id="ccc">Cronixie Display: <input name="CX" maxlength="6"><br>
Cronixie Backlight: <input type="checkbox" name="CB"><br></div>Countdown Mode: 
<input type="checkbox" name="CE"><br>Countdown Goal:<br>Year: 20 <input 
name="CY" type="number" min="0" max="99" required> Month: <input name="CI" 
type="number" min="1" max="12" required> Day: <input name="CD" type="number" 
min="1" max="31" required><br>Hour: <input name="CH" type="number" min="0" 
max="23" required> Minute: <input name="CM" type="number" min="0" max="59" 
required> Second: <input name="CS" type="number" min="0" max="59" required><br>
<h3>Macro presets</h3><b>Macros have moved!</b><br><i>
Presets now also can be used as macros to save both JSON and HTTP API commands.
<br>Just enter the preset id below!</i> <i>
Use 0 for the default action instead of a preset</i><br>Alexa On/Off Preset: 
<input name="A0" type="number" min="0" max="250" required> <input name="A1" 
type="number" min="0" max="250" required><br>Countdown-Over Preset: <input 
name="MC" type="number" min="0" max="250" required><br>
Timed-Light-Over Presets: <input name="MN" type="number" min="0" max="250" 
required><br><h3>Button actions</h3><table style="margin:0 auto" id="macros">
<thead><tr><td>push<br>switch</td><td>short<br>on-&gt;off</td><td>long<br>
off-&gt;on</td><td>double<br>N/A</td></tr></thead><tbody></tbody></table><a 
href="https://github.com/Aircoookie/WLED/wiki/Macros#analog-button" 
target="_blank">Analog Button setup</a><h3>Time-controlled presets</h3><div 
style="display:inline-block"><table id="TMT"></table></div><hr><button 
type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form></body></html>

Guru-Zachw avatar Aug 05 '22 16:08 Guru-Zachw

I tried

var response = await Process.run('curl', ['http://10.22.2.214/settings/time']);

for fun and it Successfully returned the response on flutter android and flutter linux.

Guru-Zachw avatar Aug 05 '22 17:08 Guru-Zachw

I created a quick server that returns the value I showed above It looks liked the problem is with the header: 'Transfer-Encoding': 'chunked'

Guru-Zachw avatar Aug 05 '22 19:08 Guru-Zachw

I will acknowledge that the request from the 3rd party device I am working with is erroneous. But the problem that I would say should be addressed here is that if there is an erroneous HTTP response (potentially out of my control) then I have no way to get the full raw response (that I know of) of which I can parse as I please. Python/Curl/JavaScript/Postman/Chrome all either handle this case gracefully, or they lack some 'smart' functionality that errors out before I can recover the complete data from the request.

Guru-Zachw avatar Aug 08 '22 14:08 Guru-Zachw