[VC++6.0] HTTP-Request mit cURL klappt nicht !

vfl_freak

Premium-User
Hallo zuammen,

ich sitze hier seit zwei Tagen an dem Problem mittels C/C++ eine (passwortgeschüzte) PHP-Datei von einem Webserver auszulesen ...

Habe hierzu inzwischen die libcurl gefunden! Ein normales perfom klappt wunderbar - die gesuchten Daten werden im Tool angezeigt!
Nun doktere ich damit rum, einen HTTP-Request zu senden, um die ankommenden Daten in einen Buffer auszulesen und dann weiter zu verarbeiten!

Dabei handele ich mir stets ein "bad request" ein.

Die Webadresse (die sich natürlich auch über einen Browser aufrufen lässt) ist grundlegend wie folgt aufgebaut:

https://user:passwort@www.derserver.com/dir1/dir2/csv.php

Ich habe nun in den verschiedensten Form versucht, das GET abzusetzen, bekomme aber mit schöner Regelmäigkeit nur das erwähnte "bad request" zurück.

Aktuell sieht der Aufruf so aus:

Code:
const char *request = "GET /dir1/dir2/csv.php HTTP/1.1\r\nHost: http://user:passwort@www.derserver.com\r\n\r\n";

Habe Versuche mit:
http und https
HTTP/1.0 und HTTP/1.1
mit und ohne User/Passwort
mit und ohne Pfad vor der php-Datei
usw. usw. .....

Hat irgendwer noch eine Idee, was am meiner Syntax falsch sein könnte :confused::confused:

Hier noch mal der gesamte Code der kleinen Testapplikation:

Code:
#include "stdafx.h"
#include <string>
#include <stdio.h>
#include <curl/curl.h>
#include <curl/easy.h>

using namespace std;

/* Auxiliary function that waits on the socket. */
static int wait_on_socket( int sockfd, int for_recv, long timeout_ms )
{
    struct timeval tv;
    fd_set infd, outfd, errfd;
    int res;
    
    tv.tv_sec = timeout_ms / 1000;
    tv.tv_usec= (timeout_ms % 1000) * 1000;
    
    FD_ZERO( &infd );
    FD_ZERO( &outfd );
    FD_ZERO( &errfd );
    
    FD_SET( (u_int)sockfd, &errfd ); /* always check for error */
    
    if( for_recv )
    {
        FD_SET( (u_int)sockfd, &infd );
    }
    else
    {
        FD_SET( (u_int)sockfd, &outfd );
    }
    
    /* select() returns the number of signalled sockets or -1 */
    res = select( sockfd + 1, &infd, &outfd, &errfd, &tv );

    return res;
} // wait_on_socket


int main( void )
{
    CURL *curl;
    CURLcode res;

    int sockfd; /* socket */
    size_t iolen = 0;
 
    curl = curl_easy_init();
    if( curl ) 
    {
        curl_easy_setopt( curl, CURLOPT_PROXY, "aaa.bbb.ccc.ddd:8080" ); 
        curl_easy_setopt( curl, CURLOPT_URL, "http://www.derserver.com/dir1/dir2/csv.php" );
        curl_easy_setopt( curl, CURLOPT_USERPWD, "user:passwort" ); 

        /* Do not do the transfer - only connect to host */
        curl_easy_setopt( curl, CURLOPT_CONNECT_ONLY, 1L );

        res = curl_easy_perform( curl );

        if( CURLE_OK != res )
        {
            printf( "Error: %s\n", strerror(res) );
            return 1;
        }

        // /* Extract the socket from the curl handle - we'll need it for waiting */
        res = curl_easy_getinfo( curl, CURLINFO_LASTSOCKET, &sockfd );

        if(CURLE_OK != res)
        {
            printf( "Error: %s\n", strerror(res) );
            return 1;
        }

        puts("Sending request.");
        /* Minimalistic http request */
        const char *request = "GET /dir1/dir/csv.php HTTP/1.1\r\nHost: http://user:passwort@www.derserver.com\r\n\r\n";


        /* Send the request. Real applications should check the iolen
         * to see if all the request has been sent */
        res = curl_easy_send( curl, request, strlen(request), &iolen );

        if(CURLE_OK != res)
        {
            printf("Error: %s\n", strerror(res));
            return 1;
        }

        string strResult = "";

        puts("Reading response ...");
        for(;;)
        {
            char buf[1024]; 

            int iRes = wait_on_socket( sockfd, 1, 60000L );
            printf( "wait_on_socket <%u> = <%u> ...\n", sockfd, res );
            if( -1 == iRes )
            {
                break;
            }

            res = curl_easy_recv( curl, buf, 1024, &iolen );
            printf( "curl_easy_recv <%u> = <%u> ...\n", sockfd, res );
            if( CURLE_OK != res )
            {
                break;
            }

            strResult += string(buf);
            printf( "Received %u bytes.\n", iolen );
        }


        /* always cleanup */ 
        curl_easy_cleanup( curl );

    } // if
  
    return 0;
} // main

BTW: muss die konkrete Adresse etc. leider aus Datenschutzgründen anonymisieren

Danke Euch im voraus
Gruß
Klaus
 
Moin deepthroat,

Danke für die schnelle Antwort :)
Klappt aber leider auch nicht ...

Als Antwort sehe ich übrigens immer:
"400 Bad Request
...
BorderManager Information Alert"

Gruß
Klaus

EDIT: Muss oder darf ich überhaupt hier die Einwahldaten mitangeben ? ? ?
 
Zuletzt bearbeitet:
Als Antwort sehe ich übrigens immer:
"400 Bad Request
...
BorderManager Information Alert"
Das ist ja erstmal eine Fehlermeldung vom Proxy. Irgendwie versteht der deinen Request nicht. Hast du es mal mit einem anderen Server probiert?
EDIT: Muss oder darf ich überhaupt hier die Einwahldaten mitangeben ? ? ?
Nein, die Authentifizierung erfolgt später nachdem der Server eine 401 Antwort gegeben hat.

Gibt es eigentlich einen Grund warum du nicht curl_easy_perform() verwendest?

Gruß
 
Hi deepthroat,

Das ist ja erstmal eine Fehlermeldung vom Proxy. Irgendwie versteht der deinen Request nicht. Hast du es mal mit einem anderen Server probiert?
Aha ... nicht der Gegenstelle :confused:
Ja, mit einer simplen Adresse wie wetteronline_de ...
Kommt aber genau das Gleiche ... hab's just nochmal getestet (klingt dann in der Tat eher nach unserem Proxy) .....

Nein, die Authentifizierung erfolgt später nachdem der Server eine 401 Antwort gegeben hat.
Ah, ok, wieder eine Erleuchtung :p

Gibt es eigentlich einen Grund warum du nicht curl_easy_perform() verwendest?
Ja, eigentlich schon!
Wenn ich das easy_perform ohne vorheriges "CURLOPT_CONNECT_ONLY" aufrufe, sehe ich alle gewünschten Daten in der kleinen Applikation, die dann aufgerufen wird (übrigens ebenso, wenn ich deren Kommandozeilenversion verwende; die kannich dann sogar in eine Datei umlenken ;))

Leider ist mein Chef der Meinung, dass das für unsere Anwender in der Buchhaltung zu komplex ist !
Er möchte, dass das Ganze zu definierten Zeiten von einem Java-Client aus angestossen wird, dann im C++-Server die Daten runtergeladen und in speziellen Tabellen gespeichert werden ... :-(
Und so wie ich die cURL-Doko verstehe, kann ich aus dem cURL-Handle (CURL *curl;) nicht die Daten auslesen ...
Oder kennst Du da vlt. einen gangbaren Weg ?
Andersrum sollte wohl dieses Applikationsfenster besser nicht aufgehen :(

Gruß
Klaus
 
Hi vfl_freak,
Kommt aber genau das Gleiche ... hab's just nochmal getestet (klingt dann in der Tat eher nach unserem Proxy) .....
... und ohne Proxy?
Wenn ich das easy_perform ohne vorheriges "CURLOPT_CONNECT_ONLY" aufrufe, sehe ich alle gewünschten Daten in der kleinen Applikation, die dann aufgerufen wird (übrigens ebenso, wenn ich deren Kommandozeilenversion verwende; die kannich dann sogar in eine Datei umlenken ;))

Leider ist mein Chef der Meinung, dass das für unsere Anwender in der Buchhaltung zu komplex ist !
Er möchte, dass das Ganze zu definierten Zeiten von einem Java-Client aus angestossen wird, dann im C++-Server die Daten runtergeladen und in speziellen Tabellen gespeichert werden ... :-(
Und so wie ich die cURL-Doko verstehe, kann ich aus dem cURL-Handle (CURL *curl;) nicht die Daten auslesen ...
Doch, das geht alles. Siehe z.B. http://curl.haxx.se/libcurl/c/getinmemory.html
Andersrum sollte wohl dieses Applikationsfenster besser nicht aufgehen :(
Du meinst, das du keine Konsolenfenster haben möchtest? Dann müßtest du aber eine Windows-Applikation erzeugen (PE Header Subsystem auf Windows GUI stellen).

Gruß
 
tja, ohne Proxy geht gar nix, dann komme ich hier gar nicht erst raus (weiß den genauen Fehlercode im Moment nicht mehr genau) ....

Du meinst, das du keine Konsolenfenster haben möchtest?
Dann müßtest du aber eine Windows-Applikation erzeugen (PE Header Subsystem auf Windows GUI stellen).
Nein in diesem Fall nicht, da unsere C++-Server uaf einem eigenen Rechner, auf dem es unseren Chef stört ... :-(

oops, da habe ich irgendwie übersehen ....
Wollte das Beispiel gerade mal testen, allerdings scheint ein Bug drin zu sein :suspekt:
Der Rückgabewert der Funktion "myrealloc" ist "void*" und soll an einen "char*" gegeben werden, was mein Compiler gar nicht mag ...
Muss ich mir nach der Pause mal anschauen ...

Erst nochmal Danke für die super kompetente Hilfe :)

Gruß
Klaus
 
ok, auch wieder wahr ..... :p

tja, jetzt sich mein Chef während meiner Mittagspause doch wieder um entschieden, weil es ihm alles zu lange dauerte ...
Wir machen es jetzt doch so, wie ich es schon ganz zu Anfang vorgeschlagen hatte ... nämlich mit dem JavaClient. Da sind es dann nur ein paar Zeilen mit der Klasse URL!

Aber werde mir das Thema hier mal auf Termin legen und beizeiten, wenn dann mal Zeit ist, nochmals angehen! Es muss ja nun auch unter C/C++ gehen :-(

Nochmals Danke für Die Hilfe ... ;-):p

tschüss
Klaus
 
Zurück