FloppyDesk 0 Posted July 16, 2019 Hello, i have a problem when i recieve response from only one response! I tried to analyze the request which i send from SOFT by "http analyzer/debugger" and analyzer shows me good !!!JSON!!! response which is: Quote {"error":"invalid_grant","error_description":"Invalid Grant"} But, if i write "rcvdstream" to a file for see the result i got ANOTHER result which is not JSON! Here is my code: 1. Headers: procedure TConnector.SetHttpHeadersCFV; begin FHttpIcs.Agent := FUserAgent; FHttpIcs.ContentTypePost := cAppFormUrlEnc; FHttpIcs.Accept := ' application/json, text/javascript, */*; q=0.01'; FHttpIcs.AcceptLanguage := 'en-US;q=0.5,en;q=0.3'; FHeaders := ''; AddHeader('X-CORRELATION-ID: ' + FColeractionId); AddHeader('x-via-hint_dca: ' + '1_MTM0Mw=='); AddHeader('Origin: ' + 'https://cnn.com/'); AddHeader('Referer: ' + 'https://google.com'); AddHeader('X-THMID: ' + FXtmId); AddHeader('dfpSessionID: ' + FSessionId); AddHeader('X-Requested-With: ' + 'XMLHttpRequest'); AddHeader('Accept-Encoding: gzip, deflate'); FHttpIcs.ExtraHeaders.Text := FHeaders; end; Note: about encoding, i tried to delete accept-encoding header, no helps... 2. Sending request: // set post params // set headers // requesting.... FHttpIcs.RcvdStream := FResponseStream; // url .. https://..../ FHttpIcs.Url := Url; try FHttpIcs.Post(); if (FHttpIcs.StatusCode = cTooManyReqCode) then raise Exception.Create('err connection'); FHtmlResponse := FConnectorUtils.StreamToString(FResponseStream, TEncoding.Default); // !!!!! HTML RESPONSE IS INCORRECT !!!!! //// FConnectorUtils.LogToFile('htmlresponse_.txt', FHtmlResponse); // status code is correct! FConnectorUtils.LogToFile('statuscode_.txt', FHttpIcs.StatusCode.ToString); // phrase is correct! FConnectorUtils.LogToFile('phrase_.txt', FHttpIcs.ReasonPhrase); // last response is EMPTY!!!! FConnectorUtils.LogToFile('lastresponse_.txt', FHttpIcs.LastResponse); except // !!!!! HTML RESPONSE IS INCORRECT !!!!! //// FConnectorUtils.LogToFile('htmlresponse_.txt', FHtmlResponse); // status code is correct! FConnectorUtils.LogToFile('statuscode_.txt', FHttpIcs.StatusCode.ToString); // phrase is correct! FConnectorUtils.LogToFile('phrase_.txt', FHttpIcs.ReasonPhrase); // last response is EMPTY!!!! FConnectorUtils.LogToFile('lastresponse_.txt', FHttpIcs.LastResponse); ReCheck(TMethods.SendRequestM); end; Can someone help me please? thank you in advance! Share this post Link to post
Angus Robertson 574 Posted July 16, 2019 Don't know what FConnectorUtils.StreamToString does, but you always have to seek to beginning of the stream before reading it. There is a new function that convert an HTML page in the buffer to unicode string with the correct codepage: FResponseRaw := IcsHtmlToStr(FResponseStream, FContentType, true); Last boolean option converts HTML entries like £ and ☍ to unicode. That function is used in the new TSslHttpRest unit that hides a lot of the low level stuff you are doing returning Json. Angus 1 Share this post Link to post
FloppyDesk 0 Posted July 16, 2019 (edited) 49 minutes ago, Angus Robertson said: Don't know what FConnectorUtils.StreamToString does, but you always have to seek to beginning of the stream before reading it. There is a new function that convert an HTML page in the buffer to unicode string with the correct codepage: FResponseRaw := IcsHtmlToStr(FResponseStream, FContentType, true); Last boolean option converts HTML entries like £ and ☍ to unicode. That function is used in the new TSslHttpRest unit that hides a lot of the low level stuff you are doing returning Json. Angus Tried this code Quote const cAppFormUrlEnc = 'application/x-www-form-urlencoded'; FHtmlResponse := IcsHtmlToStr(FResponseStream, cAppFormUrlEnc, True); But problem not solved, same result in txt files in folder. Here is FConnectorUtils.StreamToStringCode: function TConnectorUtils.StreamToString(const Stream: TStream; const Encoding: TEncoding): string; var StringBytes: TBytes; begin Stream.Position := 0; SetLength(StringBytes, Stream.Size); Stream.ReadBuffer(StringBytes[0], Stream.Size); Result := Encoding.GetString(StringBytes); end; UPD!!!: PROBLEM SOLVED Problem was in EXCEPT BLOCK: I tried to parse html only on TRY block, but not in except. (Result Code of response is 400) One more question, can i disable this function like in indy? If responsecode > 400 then raise exception? Edited July 16, 2019 by FloppyDesk Share this post Link to post
Angus Robertson 574 Posted July 16, 2019 It is better to process the response in the onRequestDone event. There is a new property added a year ago ResponseNoException which will help you. Angus 1 Share this post Link to post
FloppyDesk 0 Posted July 16, 2019 4 hours ago, Angus Robertson said: It is better to process the response in the onRequestDone event. There is a new property added a year ago ResponseNoException which will help you. Angus Thank you so much - Angus! Tried this property, all works! But this "OnRequestDone" event, i tried to write some code and i got stucked at one question. For example, we have error = 1 (which is bad connection) how i can reconnect same request with same headers/post parameters? I have much methods with requests, new headers, new post params, how i can handle this in this event? Thanks! Share this post Link to post
Angus Robertson 574 Posted July 16, 2019 Most better ICS applications use Async methods so are fully event driven, allowing multiple connections are the same time in a single thread. So most of the code goes in various event But sync calls are easier to use from a program flow perspective and the code can either be in the event are after the sync call, although exceptions cause trouble which is why I added ResponseNoException. But sync programs are less suited to multiple connections or tasks at the same time. In event driven applications, you usually use messages from an event to start something new or a triggers in a timer event to start another connection 60 seconds later of something, I do that a lot. Angus 1 Share this post Link to post