Probleme mit libcurl bei CURLOPT_POSTFIELDS

badday

Erfahrenes Mitglied
Moin zusammen,

ich habe gerade ein etwas merkwürdiges Problem mit einer Anwendung, die libcurl benutzt.
Zunächst einmal grob, was ich machen möchte:
Ich habe Serverseitig einen Webservice, den ich via http erreichen kann und dem ich json-Objekte schicke.
Momentan sieht es in etwa so aus:
Code:
std::wstring targetaddress, source;
//....
CURL *curl;
CURLcode res;
 
curl = curl_easy_init();
if(curl) {
	curl_easy_setopt(curl, CURLOPT_URL, targetaddress.c_str());
	curl_easy_setopt(curl, CURLOPT_PORT, 8080);
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, source.c_str());
 
	/* Perform the request, res will get the return code */ 
	res = curl_easy_perform(curl);
 
	/* always cleanup */ 
	curl_easy_cleanup(curl);
}

Wobei targetaddress die genaue Zieladresse enthält (im Beispiel http://musteradresse.de/muster ) und source die Daten, die gesendet werden sollen (als einfache json-Objekte). Der Port ist vom WS so festgelegt.

Via Browser ist der WS z. B. so erreichbar:
Code:
http://musteradresse.de:8080/muster.json
Damit kann ich dann z. B. eine json-Datei herunterladen. Beim upload verwende ich routen, die vom Webservice festgelegt sind, z. B. versuche ich auf
Code:
http://musteradresse.de:8080/muster
etwas hochzuladen. Rufe ich diese Adresse im Browser auf, bleibt das Fenster einfach weiß, aber die Seite ist vorhanden.

Nun zum Problem:
Versuche ich das mit libcurl, so erhalte ich als res von curl_easy_perform(curl); den Fehlercode:
Code:
CURLE_COULDNT_RESOLVE_HOST

Daher meine Frage: Warum erhalte ich diesen Fehler? Die Seite ist ja im Browser aufrufbar.


Vielen Dank.


Gruß,

badday
 
Moin,

es sollte die aktuelle Version sein.

Zu wchar: Kann das ein Problem sein? Werde es gleich mal ausprobieren, melde mich dann wieder.


Gruß,

badday
 
OK, das war tatsächlich das Problem.
Eine Frage habe ich noch:
Das Senden von wchars via POSTFIELDS ist aber kein Problem, oder?

Momentan sieht es so aus:
Code:
if(curl) {
			
			struct curl_slist *headers=NULL;
			headers = curl_slist_append(headers, "Content-Type: application/json; charset=utf-8");

			curl_easy_setopt(curl, CURLOPT_URL, targetaddress.c_str());
			curl_easy_setopt(curl, CURLOPT_PORT, 8080);
			
			curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
			curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, sizeof(wchar_t)*(source.length()+1));
			curl_easy_setopt(curl, CURLOPT_POSTFIELDS, source.c_str());
			
			/* Perform the request, res will get the return code */ 
			res = curl_easy_perform(curl);
 
			/* always cleanup */ 
			curl_easy_cleanup(curl);
			curl_slist_free_all(headers);
targetaddress ist nun char. Allerdings sagt der Server immer, das json-Objekt sei nicht valid, ist es aber, laut jsonlint.com. Ich vermute einfach mal, dass könnte mit der Kodierung zusammenhängen?
Wäre denn die Vorgehensweise soweit richtig mit dem content-type?
Ich habe auch ein setlocale(LC_ALL, "en_US.UTF-8"); eingefügt, nur half das nicht weiter.

Bin für jeden Tipp dankbar.



Danke und Gruß,

badday
 
Zuletzt bearbeitet:
OK, das war tatsächlich das Problem.
Eine Frage habe ich noch:
Das Senden von wchars via POSTFIELDS ist aber kein Problem, oder?
Doch, da ein wchar_t Zeichen aus mehreren Bytes besteht und üblicherweise bei Zeichen aus dem ASCII-Bereich ein Byte davon \0 ist (L'a' == \x61\x00), erkennt curl (welches intern nur mit char arbeitet) nur einen String von 1 Zeichen. (strlen(L"abcdef") == 1)

Evtl. solltest du dir das was über die Leitung geht mit Wireshark anschauen.

Und wenn du schon C++ verwendest, warum verwendest du denn keinen C++ Wrapper für libcurl, z.B. http://curlpp.org/ ?

Gruß
 
Ich schaue schon mit Wireshark, demnach wird das eigentlich schön gesendet.
Wenn du keine CURLOPT_POSTFIELDSIZE angibst, ermittelt curl die Länge der Post-Daten mit strlen, was für wchar_t* in der Regel kein korrektes Ergebnis liefert.

Ich weiß ja nicht wie du die Daten in den wstring bekommen hast; evtl. hast du da getrickst?

Gruß
 
Du hast recht, ohne geht es nicht, aber wie oben geschrieben mache ich das mit CURLOPT_POSTFIELDSIZE:
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, sizeof(wchar_t)*(source.length()+1));


Gruß,

badday
 
Du hast recht, ohne geht es nicht, aber wie oben geschrieben mache ich das mit CURLOPT_POSTFIELDSIZE:
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, sizeof(wchar_t)*(source.length()+1));
Ach so, den Code hatte ich gar nicht gesehen.

Aber warum nimmst du nicht einfach die wstring::data() Methode, da muss nicht extra ein \0 angehängt werden, dann kannst du die +1 weglassen.

Gruß
 
Hey,

ich melde mich nochmal, weil es zwar insofern nun geht, ich aber ein weiteres Problem habe:
Es wird nach jedem Zeichen ein Leerzeichen gesendet, also statt Hund H u n d, aber auch bei Nummer, also statt 900 9 0 0. Damit ist das ganze natürlich kein valides json-Objekt mehr.
Ich sende aktuell die Enkodierung mit via

Code:
struct curl_slist *headers=NULL;
headers = curl_slist_append(headers, "Content-Type: application/json; charset=utf-8");
//...
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

und setzt im Programm am Anfang
Code:
setlocale(LC_ALL, "en_US.UTF-8");

Wo kann das Problem liegen?


Gruß,

badday
 
Zurück