Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi TidHTTP.Post() - Parameter werden nicht getrennt (https://www.delphipraxis.net/60592-tidhttp-post-parameter-werden-nicht-getrennt.html)

TDKBacke 9. Jan 2006 19:33


TidHTTP.Post() - Parameter werden nicht getrennt
 
Hallo Forum,

wie ich bei einer Suche hier im Forum feststellen musste, existieren schon einige Beiträge zum Thema TidHTTP.Post() und nicht (richtig) ankommende Parameter, allerdings ist mein Fall etwas anders gelagert.

Zuerst einmal der Code (der Vollständigkeit wegen etwas länglich, der wichtige Teil ist durch '!!! ... !!!'-Kommentare kenntlich gemacht):
Delphi-Quellcode:
procedure Proxy.HTTPServerCommandGet(AThread: TIdPeerThread;
  RequestInfo: TIdHTTPRequestInfo; ResponseInfo: TIdHTTPResponseInfo);
var
    i : integer;
    HTTPClient : TIdHTTP;
    tmpStringList : TStringList;

begin
    // HTTPClient initialisieren
    HTTPClient:=TIdHTTP.Create(nil);
    HTTPClient.HandleRedirects:=true;
    HTTPClient.ProtocolVersion:=pv1_0;

    // HTTP-Header manipulieren
    // ...

    // POST-Anfragen weitergeben
    if (RequestInfo.Command='POST') then
    begin
        ResponseInfo.ContentStream:=TMemoryStream.Create;
        tmpStringList:=TStringList.Create;

        // !!! Hier beginnt das Problem !!!

        for i:=0 to RequestInfo.Params.Count-1 do
        begin
            // Variante 1
            tmpStringList.Add(RequestInfo.Params.Strings[i]);

            // Variante 2
            // if (i<RequestInfo.Params.Count-1) then tmpStringList.Add(URLEncode(RequestInfo.Params.Strings[i] + '&'))
            // else tmpStringList.Add(URLEncode(RequestInfo.Params.Strings[i]));
        end;

        HTTPClient.Post('http://' + RequestInfo.Host + RequestInfo.Document, tmpStringList, ResponseInfo.ContentStream);

        // !!! Hier endet das Problem !!!

    end;

    ResponseInfo.ContentType:=HTTPClient.Response.ContentType;
    ResponseInfo.ContentLength:=length(ResponseInfo.ContentText);
    ResponseInfo.ResponseNo:=HTTPClient.ResponseCode;
    ResponseInfo.ServerSoftware:=HTTPClient.Response.Server;

    ResponseInfo.WriteHeader;
    ResponseInfo.WriteContent;
end;
Wie man vielleicht erkennen kann, soll das einen HTTP-Proxy darstellen. Mit dem HTTP-Server aus Indy wird ein Request angenommen, an TidHTTP weitergeleitet und dessen Ergebnis wiederum an den Aufrufer zurückgegeben. (Für GET-Anfragen - hier rausgestrichen - funktioniert das übrigens problemlos.)
Bei POST-Anfragen gibt es aber folgendes Problem:
tmpStringList enthält die Parameter für die POST-Anfrage und hat nach dem Befüllen aus RequestInfo.Params z.B. den folgenden Inhalt:
tmpStringList.Strings[0]='nick=Anonym'
tmpStringList.Strings[1]='mail=beispiel'
tmpStringList.Strings[2]='msg=Inhalt'
tmpStringList.Strings[3]='id=camponotus'


Das ist soweit auch korrekt. Wenn ich nun aber testweise ein PHP-Skript aufrufe, das lediglich die oben genannten Variablen ausgibt, erhalte ich folgendes Ergebnis:
$id=
$nick=Anonym mail=beispiel msg=Inhalt id=camponotus
$mail=
$msg=


Offensichtlich werden die einzelnen Parameter also nicht getrennt und der komplette String der ersten Variable zugewiesen. Deswegen habe ich eine zweite, im obigen Code auskommentierte Variante zum Einlesen der Parameter ausprobiert, die an alle Parameter ausser dem letzten ein '&' anhängt. Dann sehen tmpStringList und das Ergebnis des PHP-Skripts so aus:
tmpStringList.Strings[0]='nick=Anonym&'
tmpStringList.Strings[1]='mail=beispiel&'
tmpStringList.Strings[2]='msg=Inhalt&'
tmpStringList.Strings[3]='id=camponotus'

=>
$id=
$nick=Anonym
$mail=
$msg=

Jetzt werden die Parameter nach dem ersten '&' also einfach ignoriert.

Mein Ziel wäre folgende Ausgabe:
$nick=Anonym
$mail=beispiel
$msg=Inhalt
$id=camponotus


Kann mir jemand sagen, wie ich das erreiche?
Offensichtlich stimmt ja etwas mit dem Abgrenzen der Parameter nicht. Mit #13+#10 statt '&' will es aber auch nicht gelingen. Genausowenig hilft die direkte Übergabe von RequestInfo.Params.Strings an Post().
Das PHP-Skript ist übrigens nicht die Fehlerquelle, zumindest funktioniert es ohne den Umweg über den Proxy wie erwartet.

Als Entwicklungsumgebung nutze ich Delphi 6 und die mitgelieferte Indy-Version.

Vielen Dank im voraus für alle Lösungen bzw. Anregungen.

marabu 9. Jan 2006 21:20

Re: TidHTTP.Post() - Parameter werden nicht getrennt
 
Herzlich Willkommen in der Delphi-PRAXiS, TDKBacke.

Mir fallen an deinem Code zwei Dinge auf. Du setzt die Protokoll-Version explizit auf pv1_0, wo doch die Indy-Macher schreiben, dass Indy selbsttätig einen fallback durchführt, sobald POST verwendet wird und solange keine bessere Methode bekannt ist um mit fehlerhaften HTTP Servern zu kommunizieren.

Dann wäre da noch dein FOR loop. Ich denke, dass du den eliminieren kannst:

Delphi-Quellcode:
// !!! Hier beginnt das Problem !!!
HTTPClient.Post(
  'http://' + RequestInfo.Host + RequestInfo.Document,
  RequestInfo.Params,
  ResponseInfo.ContentStream
);
// !!! Hier endet das Problem !!!
Ich kann den Code momentan nicht testen, aber auch wenn er dein Problem nicht löst, dann reduziert er wenigstens die lines of code.

Grüße vom marabu

TDKBacke 9. Jan 2006 22:16

Re: TidHTTP.Post() - Parameter werden nicht getrennt
 
@marabu:
Danke für die Begrüßung und die Antwort.

Allerdings:
Zitat:

Zitat von TDKBacke
Genausowenig hilft die direkte Übergabe von RequestInfo.Params.Strings an Post().

So hatte ich es zu Beginn, dann wird aber, wie im ersten Beitrag beschrieben, alles als ein Parameter interpretiert. Deswegen wollte ich in der Schleife an jeden Parameter noch eine Art Terminator anhängen, aber weder '&' noch #13+#10 helfen weiter.

Werde mal auf HTTP 1.1 umstellen und sehen, was sich dadurch verändert. Klingt ja recht vielversprechend, wenn da von Entwicklerseite auf Probleme hingewiesen wird. :)

marabu 10. Jan 2006 18:26

Re: TidHTTP.Post() - Parameter werden nicht getrennt
 
Hallo,

deinen vergeblichen Versuch die RequestInfo.Params direkt zu übergeben habe ich in der Fülle deines Beitrages wohl überlesen - tut mir leid.

Ich habe mir nun auch einen Proxy (zum Testen) geschrieben, beim IE eingetragen und ein Formular (4 Input Felder) mit POST in Auftrag gegeben. Ich speichere die Request.Params in einem ValueListEditor damit ich mitverfolgen kann, was so an Daten fließt - deshalb die CriticalSection UILock. Intern leite ich den Request auf eine PHP-Seite, die mir mit phpinfo() alle POST Variablen anzeigt. Alles schaut so aus wie du es gerne hättest. Jetzt ist es an dir den Unterschied in der Vorgehensweise zu finden.

Delphi-Quellcode:
procedure TDemoForm.HTTPServerCommandGet(AThread: TIdPeerThread;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  client: TIdHTTP;
begin
  UILock.Acquire;
  try
    VLE.Strings.Assign(ARequestInfo.Params);
  finally
    UILock.Release;
  end;
  AResponseInfo.ContentStream := TMemoryStream.Create;

  client := TIdHTTP.Create(nil);
  with client do
  begin
    Request.Assign(ARequestInfo);
    HandleRedirects := true;
    AllowCookies := true;
    CookieManager := TIdCookieManager.Create(client);
  end;

  if ARequestInfo.Command = 'POST' then
    client.Post(
      // 'http://' + ARequestInfo.Host + ARequestInfo.Document,
      'http://localhost/root/test.php',
      ARequestInfo.Params,
      AResponseInfo.ContentStream
    )
  else if ARequestInfo.Command = 'GET' then
    client.Get(
      'http://' + ARequestInfo.Host + ARequestInfo.Document,
      AResponseInfo.ContentStream
    )
  else
  begin
    ShowMessage(ARequestInfo.Command);
    Exit;
  end;

  AResponseInfo.ContentType := client.Response.ContentType;
  AResponseInfo.ContentLength := AResponseInfo.ContentStream.Size;
  AResponseInfo.ResponseNo := client.ResponseCode;
  AResponseInfo.ServerSoftware := client.Response.Server;

  AResponseInfo.WriteHeader;
  AResponseInfo.WriteContent;

  AResponseInfo.ContentStream.Free;
  client.Free;
end;
Grüße vom marabu

TDKBacke 11. Jan 2006 22:16

Re: TidHTTP.Post() - Parameter werden nicht getrennt
 
Danke für das Testen, habe mein Programm an Deine Vorlage angepasst. (Letztendlich also die Initialisierung des HTTP-Clients, die direkte Übergabe der Params an Post() und *räusper* die Freigabe am Ende.)
Geholfen hat es leider nichts, stattdessen kommt jetzt überhaupt nichts mehr an, statt wie zuvor alles in einem Parameter.
Wir scheinen verschiedene Indy-Versionen zu benutzen, da der Client bei mir die Member "AllowCookies" und " CookieManager" nicht kennt. (Aber ich schleuse die "Cookie:"- und "SetCookie:"-HTTP-Felder sowieso nur durch.) Allerdings halte ich es für unwahrscheinlich, dass die von Borland offiziell mit Delphi 6 ausgelieferte Indy-Version einen so gravierenden Fehler enthält.

Zur Sicherheit noch das verwendete PHP-Skript:
Code:
<?php
echo "id=$_POST["id"]
";
echo "nick=$_POST["nick"]
";
echo "mail=$_POST["mail"]
";
echo "msg=$_POST["msg"]
";
?>
Naja, da dürfte eigentlich nichts schief laufen, insbesondere da beim Aufruf über ein Formular ohne zwischengeschalteten Proxy die korrekten Werte ausgegeben werden.

tn249 11. Jan 2006 22:26

Re: TidHTTP.Post() - Parameter werden nicht getrennt
 
ich hab nicht alles gelesen, nur kurz meine erfahrungen zu indy-post;

1. es empfiehlt sich mit nem networksniffer die daten die übetragen werden zu überprüfen einfach um nicht von möglichen fehlern in der serversoftware abhängig zu sein.

2. ich hab es mit indy 9 noch nie geschafft post mit TStringlist erfolgreich abzuschicken, er hat die argumente einfach nicht angehängt, stattdessen habe ich TIdMultiPartFromData verwendet, was bei mir ohne fehler ging.

Gruß
Thomas


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:14 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz