Перейти к содержанию
  • Регистрация
  • 0
MrDevillio

TNetHTTPRequest как отправить в body русский текст?

Вопрос

Добрый день!

Спойлер

function idHttpPost(const aURL: string; aBody: String; var IsExcepted: Boolean): string;
var
  Return: IHTTPResponse;
  HTTPClient: TNetHTTPClient;
  MS: TMemoryStream;
  aBodyStrings: TStringList;
begin
  Result := '';
  IsExcepted := false;

  try
    aBodyStrings := TStringList.Create;
    MS := TMemoryStream.Create;
    HTTPClient := TNetHTTPClient.Create(nil);
    HTTPClient.HandleRedirects := true;
    with TNetHTTPRequest.Create(nil) do
      try
        Client := HTTPClient;
        aBodyStrings.Add(aBody);
        aBodyStrings.WriteBOM := false;
        aBodyStrings.TrailingLineBreak := false;
        aBodyStrings.SaveToStream(MS);
        // aBodyStrings.SaveToStream(MS, TEncoding.ASCII);
        // aBodyStrings.SaveToStream(MS, TEncoding.ANSI);
        // aBodyStrings.SaveToStream(MS, TEncoding.UTF8);
        // aBodyStrings.SaveToStream(MS, TEncoding.Unicode);
        MS.Position := 0;

        try
          Return := post((IfThen(Pos('http', aURL) = 1, '', FAPIServer) + aURL), MS);
          // Return := Post((IfThen(Pos('http', aURL) = 1, '', FAPIServer) + aURL), aBodyStrings);
          Result := UTF8ToString(Return.ContentAsString());

        except
          on e: exception do
          begin
            IsExcepted := true;
            Result := ' -> api error : ' + TimeToStr(Time) + ' ' + e.Message;
          end;
        end;
      finally
        Free;
      end;
  finally
    aBodyStrings.Free;
    MS.Free;
    HTTPClient.Free;
  end;
end;

 

Вот так пытаюсь отправлять запрос на сервер. Если отправляю body как TStringList, мой тестовый webbroker говорит, что Request.Content = '';

Если отправляю body как TMemoryStream (или как TStringStream) то в момент чтения Request.Content получаю EEncodingError.

Вставил вот такую распорку для хоть какого-то чтения Request.Content (этот текст помогает с русскими буквами в других брокерах, когда запросы шлю из Windows приложений через TIdHTTP)

Спойлер

function BinToAscii(const bin: array of byte): AnsiString;
var i: integer;
begin
  SetLength(Result, Length(bin));
  for i := 0 to Length(bin)-1 do
    Result[1+i] := AnsiChar(bin[i]);
end;

function ConvertContentBytesToUnicode(RC: TBytes): String;
begin
  try
    Result := TEncoding.UTF8.GetString(RC);
  except
    Result := BinToAscii (RC);
  end;
end;

 

Но так вижу только англ буквы, русские - вопросами при любом варианте TEncoding при отправке.

Подскажите, как из Android приложения правильно отправлять запросы с русскими буквами в body?

Спасибо!

Изменено пользователем MrDevillio

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Рекомендуемые сообщения

  • 1

зачем тут utf8tostring
оно и так Unicode

чарсет нужно указывать в запросе. в заголовках. тут никаких свойств запроса не заполнено

кроме того, зачем вам TNetHttpClient. Это компонент - обертка класса THttpClient. Им проще и пользоваться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Спасибо вам большое. И правда, перемудрил, вот так работает:

Спойлер

function idHttpPost(const aURL: string; aBody: String; var IsExcepted: Boolean): string;
var
  Return: IHTTPResponse;
  HTTPClient: THTTPClient;
  aBodyStream: TStringStream;
begin
  Result := '';
  IsExcepted := false;

  try
    try
      aBodyStream := TStringStream.Create(aBody, TEncoding.UTF8);
      HTTPClient := THTTPClient.Create;
      with HTTPClient do
      begin
        HandleRedirects := true;
        ContentType := 'application/json';
        Accept := 'application/json';
        Return := Post((IfThen(Pos('http', aURL) = 1, '', FAPIServer) + aURL), aBodyStream);
        Result := Return.ContentAsString;
      end;
    except
      on e: exception do
      begin
        IsExcepted := true;
        Result := ' -> api error : ' + TimeToStr(Time) + ' ' + e.Message;
      end;
    end;
  finally
    aBodyStream.Free;
    HTTPClient.Free;
  end;
end;

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


  • Похожий контент

    • От kiz35196
      перевожу проект с инди на System.Net.HttpClient, никак не могу заставить его скачать файл,с инди всё как-то проще было
      подскажите пожалуйста
    • От GoldenEalge
      Подскажите как сохранить ,а потом загрузить куки в THTTPClient , как понимаю нужно работать с TCookieManager
      Сохранять пытаюсь так :
      cookies := aResponse.cookies.AsJSON(false); В cookies получаю 
      {\"Capacity\":4,\"Count\":3,\"List\":[{\"Name\":\"csrftoken\",\"Value\":\"Jljq2Sx5n9lXek4u4rri9L1zGBIExSzT\",\"Expires\":\"2019-01-06T18:41:36.854\",\"Domain\":\".i.instagram.com\",\"Path\":\"/\",\"Secure\":true,\"HttpOnly\":false},{\"Name\":\"rur\",\"Value\":\"PRN\",\"Expires\":\"1899-12-30T00:00:00.000\",\"Domain\":\".i.instagram.com\",\"Path\":\"/\",\"Secure\":false,\"HttpOnly\":false},{\"Name\":\"mid\",\"Value\":\"WlIjkQABAAF-JTqtAx_AdVdFxepj\",\"Expires\":\"2038-01-02T18:41:36.854\",\"Domain\":\".i.instagram.com\",\"Path\":\"/\",\"Secure\":false,\"HttpOnly\":false},{\"Name\":\"\",\"Value\":\"\",\"Expires\":\"1899-12-30T00:00:00.000\",\"Domain\":\"\",\"Path\":\"\",\"Secure\":false,\"HttpOnly\":false}],\"OnNotify\":null} Но как потом загрузить это обратно?
       
    • От Alex7wrt
      Добрый день
      В мобильном приложении используется следующая функция для чтения содержимого https страницы
      function geturlstring(url: string): string; var HTTP: THTTPClient; stream: tstringstream; begin try HTTP:=THTTPClient.Create; Stream:= TStringStream.Create('',TEncoding.UTF7); HTTP.Get(url, stream); Stream.Position:=0; Result:=stream.DataString; HTTP.Free; Stream.Free; except result:='error'; end; end; Почему-то в некоторых случаях, при подключении через WiFi, функция выдает 'error'. Хотя при проверке сам сайт с этим url открывается. Это вообще ссылка на гугловский сервис. Ошибку замечал например в WiFi сети метрополитена. Там подключение к WiFi двухэтапное - сначала открывается сервисная веб страница, нажимаешь ОК или что-то типа того, и WiFi подключается. 
      В этом случае функция выдает ошибку, хотя браузер работает, и другие и приложения типа мессенджера и вайбера видят сеть.В мобильных сетях вроде работает нормально, там ошибок не замечал.
      В чем может быть проблема? Может ли это быть потому, что url относится к https протоколу? 
       
    • От Rustam Bikeev
      Доброго времени суток уважаемые форумчане, назрел вопрос по компоненту ThttpClient. Я сам слеп в области Http что такое Post, Get  и прочие аббревиатуры для меня страшные и дикие звери которых никогда не видел. Потому и приходится спрашивать у вас. Как отправить на веб сервер запрос для получения текстового файла или картинки. Куда и как принять этот файл. Я нечерта не пойму если вы напишите сделай это сделай то, прошу вас опишите как пользоваться этими 3 функциями 
      THTTPClient.GetRequest
      THTTPClient.Post
      THTTPClient.Get
       
    • От gresaggr
      Добрый день.
      IDE: Delphi 10.1 Berlin Update2
      OS: Windows 7/64 ->Android (тестировал на 4.4.4)
      Вопрос 1:
       
      Пытаюсь загрузить в Listbox файл с русскими словами: ListBox1.Items.LoadFromFile(TPath.Combine(TPath.GetDocumentsPath, 'test1.txt'));
      При запуске на устройстве выдает ошибку: No mapping for the Unicode character exists in the target multi-byte code page
      Файл пытался сохранить и в UTF-8, и в ANSI, и в Unicode - без разницы (после смены кодировки делал Deployment)
      Как можно это победить?
      Вопрос 2:
      Вставил напрямую в дизайн-моде список этих же слов (из файла вопрос1) в Listbox - при старте программа очень долго думает. Слов порядка 10000. Как-то можно это ускорить?


       


       


       
    • От Евгений Корепов
      Начал переносить проекты из XE8 в Berlin, столкнулся с странным затыком в простеньком коде - делаем запрос на сайт, получаем куки, делаем post авторизацию, получаем редирект, если все хорошо, то октрываем страницу из header Location. Выяснилось что не смотря на HTTPClient.AllowCookies:=True, в HTTPResponse.Cookies всегда пустота. Пришлось копать исходники. Вот что обнаружилось в source\rtl\net\System.Net.HttpClient.pas:
      procedure THTTPClient.ExecuteHTTPInternal(const ARequest: IHTTPRequest; const AContentStream: TStream; const AResponse: IHTTPResponse); var LRequest: THTTPRequest; LResponse: THTTPResponse; State: THTTPState; LExecResult: TExecutionResult; LClientCertificateList: TCertificateList; OrigSourceStreamPosition: Int64; OrigContentStreamPosition: Int64; OrigContentStreamSize: Int64; Status: Integer; LCookieHeader: string; begin LResponse := AResponse as THTTPResponse; LRequest := ARequest as THTTPRequest; OrigSourceStreamPosition := 0; if LRequest.FSourceStream <> nil then OrigSourceStreamPosition := LRequest.FSourceStream.Position; if AContentStream <> nil then begin OrigContentStreamPosition := AContentStream.Position; OrigContentStreamSize := AContentStream.Size; end else begin OrigContentStreamPosition := 0; OrigContentStreamSize := 0; end; State := Default(THTTPState); LClientCertificateList := TCertificateList.Create; try while True do begin LRequest.DoPrepare; // Add Cookies if FCookieManager <> nil then begin LCookieHeader := FCookieManager.CookieHeaders(LRequest.FURL); if LCookieHeader <> '' then LRequest.AddHeader('Cookie', LCookieHeader); // do not localize end; if not SetServerCredential(LRequest, LResponse, State) then Break; if not SetProxyCredential(LRequest, LResponse, State) then Break; if LRequest.FSourceStream <> nil then LRequest.FSourceStream.Position := OrigSourceStreamPosition; if LResponse <> nil then begin LResponse.FStream.Position := OrigContentStreamPosition; LResponse.FStream.Size := OrigContentStreamSize; end; LExecResult := DoExecuteRequest(LRequest, LResponse, AContentStream); case LExecResult of TExecutionResult.Success: begin if not SameText(LRequest.FMethodString, sHTTPMethodHead) then LResponse.DoReadData(LResponse.FStream); Status := LResponse.GetStatusCode; case Status of 200: begin Break; // Если запрос удачен, то выходим из цикла end; 401: begin State.Status := InternalState.ServerAuthRequired; end; 407: begin State.Status := InternalState.ProxyAuthRequired; end; else begin case Status of 301..304, 307: if FHandleRedirects and (LRequest.FMethodString <> sHTTPMethodHead) then begin Inc(State.Redirections); if State.Redirections > FMaxRedirects then raise ENetHTTPRequestException.CreateResFmt(@SNetHttpMaxRedirections, [FMaxRedirects]); end else Break; else end; State.Status := InternalState.Other; if DoProcessStatus(LRequest, LResponse) then Break; end; end; end; TExecutionResult.ServerCertificateInvalid: begin DoValidateServerCertificate(LRequest); end; TExecutionResult.ClientCertificateNeeded: begin DoNeedClientCertificate(LRequest, LClientCertificateList); end else raise ENetHTTPClientException.CreateRes(@SNetHttpClientUnknownError); end; if AllowCookies then UpdateCookiesFromResponse(LResponse); // Вот эта, критически важная процедура, при Status=200 никогда не выполняется end; // После выхода из цикла попадаем сюда if LRequest.FSourceStream <> nil then LRequest.FSourceStream.Seek(0, TSeekOrigin.soEnd); LResponse.FStream.Position := OrigContentStreamPosition; finally LClientCertificateList.Free; end; end; Т.е. разработчики исключили выполнение UpdateCookiesFromResponse(LResponse), которая помещает куки из ответа в HTTPClient.
      А вот код из XE8 который нормально работает с Cookies:
      function THTTPClient.ExecuteHTTPInternal(const ARequest: IHTTPRequest; const AContentStream: TStream): IHTTPResponse; var LRequest: THTTPRequest; LResponse: THTTPResponse; State: THTTPState; LExecResult: TExecutionResult; LClientCertificateList: TCertificateList; OrigSourceStreamPosition: Int64; OrigContentStreamPosition: Int64; OrigContentStreamSize: Int64; Status: Integer; LCookieHeader: string; begin Result := nil; LResponse := nil; LRequest := ARequest as THTTPRequest; OrigSourceStreamPosition := 0; if LRequest.FSourceStream <> nil then OrigSourceStreamPosition := LRequest.FSourceStream.Position; if AContentStream <> nil then begin OrigContentStreamPosition := AContentStream.Position; OrigContentStreamSize := AContentStream.Size; end else begin OrigContentStreamPosition := 0; OrigContentStreamSize := 0; end; State := Default(THTTPState); LClientCertificateList := TCertificateList.Create; try while True do begin LRequest.DoPrepare; // Add Cookies if FCookieManager <> nil then begin LCookieHeader := FCookieManager.CookieHeaders(LRequest.FURL); if LCookieHeader <> '' then LRequest.AddHeader('Cookie', LCookieHeader); // do not localize end; if not SetServerCredential(LRequest, LResponse, State) then Break; if not SetProxyCredential(LRequest, LResponse, State) then Break; if LRequest.FSourceStream <> nil then LRequest.FSourceStream.Position := OrigSourceStreamPosition; if LResponse <> nil then begin LResponse.FStream.Position := OrigContentStreamPosition; LResponse.FStream.Size := OrigContentStreamSize; end; LExecResult := DoExecuteRequest(LRequest, LResponse, AContentStream); case LExecResult of TExecutionResult.Success: begin if not SameText(LRequest.FMethodString, sHTTPMethodHead) then LResponse.DoReadData(LResponse.FStream); Status := LResponse.GetStatusCode; case Status of 200: begin Break; end; 401: begin State.Status := InternalState.ServerAuthRequired; end; 407: begin State.Status := InternalState.ProxyAuthRequired; end; else begin case Status of 301..304, 307: if FHandleRedirects and (LRequest.FMethodString <> sHTTPMethodHead) then begin Inc(State.Redirections); if State.Redirections > FMaxRedirects then raise ENetHTTPRequestException.CreateResFmt(@SNetHttpMaxRedirections, [FMaxRedirects]); end else Break; else end; State.Status := InternalState.Other; if DoProcessStatus(LRequest, LResponse) then Break; end; end; end; TExecutionResult.ServerCertificateInvalid: begin DoValidateServerCertificate(LRequest); end; TExecutionResult.ClientCertificateNeeded: begin DoNeedClientCertificate(LRequest, LClientCertificateList); end else raise ENetHTTPClientException.CreateRes(@SNetHttpClientUnknownError); end; end; if LRequest.FSourceStream <> nil then LRequest.FSourceStream.Seek(0, TSeekOrigin.soEnd); if AllowCookies then UpdateCookiesFromResponse(LResponse); // Здесь все верно, процедура за пределами цикла и выполняется всегда когда нужно. finally LClientCertificateList.Free; Result := IHTTPResponse(LResponse); end; end; А теперь вопрос: ну как так то? В продукте за 54 тысячи рублей сильно обидно исправлять такие косяки. Такое ощущение что разраб подрабатывал на стороне в проектах на php и забыл переключится на другой язык, там break прерывает работу аналога case и код работал бы правильно.
       
    • От magicxor
      При простом GET-запросе на эти URL:
      https://accounts.google.com/AddSession?hl=ru&continue=https://www.google.com/%3Fgws_rd%3Dssl
      https://accounts.google.com/Logout?hl=ru&continue=https://www.google.com/%3Fgws_rd%3Dssl&timeStmp=1463418874
      Возникает исключение:
      В инди такой проблемы нет, она отдаёт контент HTML страницы, как и положено.
      Потестить можно через C:\Users\Public\Documents\Embarcadero\Studio\18.0\Samples\Object Pascal\RTL\HttpAsyncDownload
      Это очередной баг?
      (использую Delphi 10.1 Berlin)
    • От Евгений Корепов
      Есть сайт просроченным сертификатом безопасности (госконтора, такое у них в порядке вещей), сертификат могут обновить завтра, а могут и через год, но работать с ним надо.
      Var HTTPClient: THTTPClient; HTTPResponse: IHTTPResponse; begin HTTPClient:=THTTPClient.Create; HTTPClient.OnValidateServerCertificate:=HTTPClientValidateServerCertificate; ..... try HTTPResponse:=HTTPClient.Post(FHTTPRec.Query,FHTTPRec.PostData); except on E : Exception do begin FHTTPRec.ErrorCode:=-1; FHTTPRec.ErrorMsg:=E.Message; end; ..... end; procedure THTTPThread.HTTPClientValidateServerCertificate(const Sender: TObject; const ARequest: TURLRequest; const Certificate: TCertificate; var Accepted: Boolean); begin Accepted:=True; end; Под Windows код работает идеально - вызывается HTTPClientValidateServerCertificate, где принудительно доверяем сертификату.
      Под Андроид HTTPClientValidateServerCertificate или игнорируется, или до процедуры не доходит. Получаю ошибку:
      First chance exception at $A06ECCE5. Exception class EJNIException with message 'java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.'. Process tratata.apk (25487) First chance exception at $A0EA44F5. Exception class ENetHTTPCertificateException with message 'Server Certificate Invalid or not present'. Process tratata.apk (25487) Как победить проблему? 
      P.S. До этого проект работал на Indy, там подобные проблемы успешно игнорировались. Но решил перевести все на THTTPClient и вот результат :-(
       
    • От Rusland
      Пытаюсь скачать XML с курсами валют с cbr.ru. Получаю ошибку Project raised exception class EEncodingError with message 'No mapping for the Unicode character exists in the target multi-byte code page'. Как исправить?
      //aUrl = http://www.cbr.ru/scripts/XML_daily.asp function GetXML(aURL: string): String; var Http: THTTPClient; Ss: TStringStream; begin Result:=''; Http:=THTTPClient.Create; try Ss:=TStringStream.Create('', TEncoding.UTF8); Http.Get(aURL,ss); Result:=Ss.DataString; // тут ошибка except end; Http.Free; end;
    • От krapotkin
      Делаю приложение Android / IOS. Коллеги делают серверную сторону на PHP, предоставляющую API.
      Все взаимодействует нормально, проверено.
      Теперь мне нужно подключиться к этому серверу через HTTPS.  Текст сертификата публичного ключа мне выдали. На сервере сертификат самоподписанный, не покупной.
      Как добавить этот сертификат/текст при запросе в событии HTTPClient.OnNeedClientCertificate?
      Как проверить сертификат сервера в событии HTTPClient.OnValidateServerCertificate?
      Доки пустые. Developer skill sprint просмотрел, там только в комментах обещали разобраться с этим вопросом, но до сих пор молчок.
       
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...