c# - Why HttpClient blocks forever with chunked encoding? -
here's simple code snippet:
var httpmessage = new httprequestmessage(httpmethod.get, "https://google.com")) var task = client.sendasync(httpmessage, httpcompletionoption.responseheadersread); var response = await task; this code works fine. when replace custom server gives me chunked encoding "await task" hangs forever.
i've got backing code working through streamsocket , know server works fine. read http headers, parse incoming chunks e.t.c. problem why httpclient hangs chunked encoding?
update:
i forgot mention i'm using customhttphandler allow untrusted certificates.
/// <summary> /// httpmessagehandler lets use windows runtime ihttpfilter types /// </summary> public class customhttpclienthandler : httpmessagehandler { static readonly list<chainvalidationresult> allowedcertificateerrors = new list<chainvalidationresult>(){ chainvalidationresult.expired, chainvalidationresult.untrusted, chainvalidationresult.invalidname, }; private static readonly version noversion = new version(0, 0); private static readonly version version10 = new version(1, 0); private static readonly version version11 = new version(1, 1); private static readonly version version20 = new version(2, 0); private readonly rt.httpclient _client; private bool _disposed = false; public customhttpclienthandler() { var filter = new httpbaseprotocolfilter(); foreach (var error in allowedcertificateerrors) filter.ignorableservercertificateerrors.add(error); _client = new rt.httpclient(filter); } protected override async task<httpresponsemessage> sendasync(httprequestmessage request, cancellationtoken cancellationtoken) { checkdisposed(); var rtmessage = await converthttprequestmessagetort(request, cancellationtoken).configureawait(false); var resp = await _client.sendrequestasync(rtmessage).astask(cancellationtoken).configureawait(false); var netresp = await convertrtresponsemessagetonet(request, resp, cancellationtoken).configureawait(false); return netresp; } internal static async task<rt.httprequestmessage> converthttprequestmessagetort(httprequestmessage message, cancellationtoken token) { var rt = new rt.httprequestmessage() { method = new rt.httpmethod(message.method.method), content = await getcontentfromnet(message.content).configureawait(false), requesturi = message.requesturi, }; copyheaders(message.headers, rt.headers); foreach (var prop in message.properties) rt.properties.add(prop); return rt; } internal static void copyheaders(ienumerable<keyvaluepair<string, ienumerable<string>>> source, idictionary<string, string> destination) { var headers = kvp in source val in kvp.value select new keyvaluepair<string, string>(kvp.key, val); destination.clear(); foreach (var header in headers) destination.add(header); } internal static async task<rt.ihttpcontent> getcontentfromnet(httpcontent content) { if (content == null) return null; rt.ihttpcontent c; if (content stringcontent) c = new rt.httpstringcontent(await content.readasstringasync().configureawait(false), windows.storage.streams.unicodeencoding.utf8); else { var stream = await content.readasstreamasync().configureawait(false); c = new rt.httpstreamcontent(stream.asinputstream()); } copyheaders(content.headers, c.headers); return c; } internal static async task<httpcontent> getnetcontentfromrt(rt.ihttpcontent content, cancellationtoken token) { if (content == null) return null; var str = await content.readasinputstreamasync().astask(token).configureawait(false); var c = new streamcontent(str.asstreamforread()); foreach (var header in content.headers) c.headers.tryaddwithoutvalidation(header.key, header.value); return c; } internal static async task<httpresponsemessage> convertrtresponsemessagetonet(httprequestmessage request, rt.httpresponsemessage message, cancellationtoken token) { var resp = new httpresponsemessage((httpstatuscode)(int)message.statuscode) { reasonphrase = message.reasonphrase, requestmessage = request, content = await getnetcontentfromrt(message.content, token).configureawait(false), version = getversionfromenum(message.version), }; foreach (var header in message.headers) resp.headers.tryaddwithoutvalidation(header.key, header.value); return resp; } internal static version getversionfromenum(rt.httpversion version) { switch (version) { case rt.httpversion.none: return noversion; case rt.httpversion.http10: return version10; case rt.httpversion.http11: return version11; case rt.httpversion.http20: return version20; default: throw new argumentoutofrangeexception("version"); } } private void checkdisposed() { if (_disposed) throw new objectdisposedexception("winrthttpclienthandler"); } protected override void dispose(bool disposing) { if (disposing && !_disposed) { _client.dispose(); _disposed = true; } base.dispose(disposing); } } update:
on desktop use httpwebrequest communicate server. winrt don't have option allow self-signed certificates httpwebrequest that's why switched httpclient
Comments
Post a Comment