Webservice -> Response -> Kodierung

pizza4ever

Lt. Commander
Registriert
Apr. 2009
Beiträge
1.713
Hallo zusammen

eine Frage zu einem Webservice.

Ich habe folgende Sitaution: Ich schicke einem Webservice einen Request mit

Code:
Content-Type: text/html; charset=utf-8

und bekomme eine UTF-8 kodierte Antwort zurück.

Das Problem ist nun, dass .net / Powershell diese nicht als UTF-8 kodiert erkennt und daher Fehler entstehen, siehe auch hier:

https://stackoverflow.com/questions/47952689/powershell-invoke-webrequest-and-character-encoding

PowerShell obeys the standard by assuming ISO-8859-1, but unfortunately the site is using UTF-8.

Das ist wohl garnicht sooo doof was da passiert, siehe auch hier:
https://www.w3.org/International/articles/http-charset/index

Es ist sehr wichtig, Web-Dokumente immer explizit zu kennzeichnen. HTTP/1.1 legt den Standardwert für charset mit ISO-8859-1 fest. Es gibt aber unzählige ungekennzeichnete Dokumente in anderen Zeichencodierungen, weshalb Browser die vom Nutzer bevorzugte Zeichencodierung verwenden, wenn nicht explizit ein charset-Parameter angegeben ist.
Es gibt nun zwar Workarounds wie die Antwort "Raw" zu speichern und dann neu auzulesen, aber das sind ja keine besonders schöne Lösungen, daher meine Fragen:

1.) Ist meine Annahme das die "saubere" Lösung wäre, dass der Webservice im Header der Antwort das Tag:
Code:
Content-Type: xxxx; charset=utf-8

mitgibt?

2.) Ist es üblich, dass auch die HTML Version und der Status Code mitgeliefert werden vom antwortenden Webservice?

3.) Gibt es noch weitere "Standards", die der Webservice einhalten sollten?

Danke und viele Grüße,

Alex
 
Der Content-Type Header im Request macht nur Sinn, wenn man auch Daten mitschickt, also bei POST und PUT.
In der Response setzt der Server mit dem Header dann den Content-Type seiner Antwort.

Die HTML Version hat mit der HTTP Kommunikation nichts zu tun, höchstens die HTTP Version und die wird beim Request und Response mitgeteilt, damit beide Parteien wissen, worauf sie sich einlassen.

Der HTTP Statuscode gehört auch definitiv in jede Response, damit der Client einschätzen kann, ob seine Anfrage erfolgreich war oder nicht.

Insgesamt solltest du dir vielleicht einfach einen Überblick über das HTTP verschaffen. Bei Wiki gibts einen brauchbaren Überblick, wie das so auszusehen hat. Ist vielleicht ein guter Startpunkt.

BTW: Nicht das Rad neu erfinden. Warum benutzt du nicht eine HTTP Framework/Library? Die kümmert sich um das Einhalten des Standards und du kannst dich auf die Zusatzinfos konzentrieren.
 
Hi

ich schreibe den Aufrufenden Webservice nicht, ich kann nur Fehler weitergeben. Und ja du hast recht, wir schicken JSON Daten über (glaube ich) post mit; genaueres kann ich morgen nachliefern. Ich mache nur das testing.

Kannst du mir ein HTTP Framework / Library empfehlen? Ich weiß, dass die andere Seite sehr stark auf Java setzt udn zumindestnes einkippen kann ich es.

Was ist mit meiner Frage zum Headers des Respons?
 
Ist die Antwort auch JSON? Weil JSON eigentlich erweiterterte Unicode-Zeichen als "\u005c" kodiert.
Kann es sein, dass ihr für den Request eher "Content-Type: application/json" setzen solltet, um auch eine "richtige" JSON-Antwort zu erhalten? JSON sollte übrigens immer als UTF-8 kodiert sein, das sollte man nicht explizit angeben müssen.
 
Ja, wir setzen Content-Type: application/json beim Request.

Mein Problem ist, dass wenn ich den Response mit Powershell im Testing entgegeben nehme, Powershell beim empfangenden JSON wohl von der Kodierung "ISO-8859-1 " ausgeht....

Wenn ich das JSON über -raw abfange, in eine Datei schreibe und mir dann mit -utf8 wieder auslese passt auch alles aber das ist ja kenie schöne Lösung
 
Dann senden die Umlaute im JSON als JSON Text direkt mit?
Das sollte so nicht sein, denn es sollte mit \u0059 usw. kodiert sein: Beispiel "Abrahamstra\u00dfe" statt "Abrahamstraße" der Standard laut RFC für JSON ist immer UTF-8. JSON als ISO-8859-1 kodiert wäre eine Abweichung vom Standard. Im Standard werden Nicht-Ansi-Zeichen jedoch auch via \u0000 bis \uFFFF kodiert, sodass das "theoretisch" auch mit ISO-8859-1 funktionieren würde, solange man Unicode "escaped".
 
https://tools.ietf.org/html/rfc8259#section-8

8.1. Character Encoding

JSON text exchanged between systems that are not part of a closed
ecosystem MUST be encoded using UTF-8 [RFC3629].

dazu zählt dann auch, das der webserver das richtig im header angeben muss. bug-report beim bereitsteller der api aufmachen.

und als content-type solltet ihr "application/json" benutzen, das ist kein "text/html"
 
Aber die API schickt mir doch das JSON als UTF-8 zurück? Mein Problem ist imho doch eher, dass .net / powershell bei invoke-command fälschlicherweise von ISO-8859-1 ausgeht
 
ja, du hast recht. wenn der content des response aber utf-8 ist, dann muss das auch so im response stehen. ist trotzdem ein bug in der api :)
 
Nein, muss es bei APIs, die JSON nutzen, eigentlich nicht, da JSON dabei per Definition UTF-8 ist.
Der Client muss das schon richtig interpretieren, das tut Powershell jedoch nicht.
Die Lösung steht aber auch im Stackoverflow-Thread im zweiten Beitrag: Benutze eine Hilfsfunktion, die den fehlerhaft interpretierten String in ein für Powershell bekanntes UTF-8 umwandelt.
 
So, nochmal zur zusammenfassung:

Ich schick im folgendes mit:
Accept: Application/json
content-type: Application/json

+das JSON als POST

Der Antwortheader sieht wie im Anhang beschrieben aus.

Edit: Die Funtion aus dem Powershell hat bei mir nicht funktioniert...

edit2: die Funktion scheint zu funktionieren:

[system.Text.Encoding]::UTF8.GetString($response.RawContentStream.ToArray());


wobei $response der Response ist...
 

Anhänge

  • Unbenannt.png
    Unbenannt.png
    11,1 KB · Aufrufe: 303
Zuletzt bearbeitet:
ich bin kein experte in powershell, aber so in der art sollte das aussehen?

Code:
PS> $r =Invoke-WebRequest https://jsonplaceholder.typicode.com/todos/1
PS> $r.StatusCode
200


PS> $r.Headers

Key                              Value
---                              -----
Connection                       keep-alive
Vary                             Origin, Accept-Encoding
Access-Control-Allow-Credentials true
Pragma                           no-cache
X-Content-Type-Options           nosniff
CF-Cache-Status                  HIT
Age                              7177
Expect-CT                        max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect...
CF-RAY                           53c6ca50c970e608-LHR
Accept-Ranges                    bytes
Content-Length                   83
Cache-Control                    max-age=14400
Content-Type                     application/json; charset=utf-8
Date                             Wed, 27 Nov 2019 20:18:15 GMT
Expires                          -1
ETag                             W/"53-hfEnumeNh6YirfjyjaujcOPPT+s"
Set-Cookie                       __cfduid=d34d2a519ac38f53579af8a9fa09f17831574885895; expires=Fri, 27-Dec-19 20:18:...
Server                           cloudflare
Via                              1.1 vegur
X-Powered-By                     Express

PS> $json = Invoke-WebRequest https://jsonplaceholder.typicode.com/todos/1 | ConvertFrom-Json
PS> $json

userId id title              completed
------ -- -----              ---------
     1  1 delectus aut autem     False
 
Es ist nicht meine und wenn ich sie gebe werde ich gekillt :-)

Aber in deinem Beispielt steht ja in

r.headers (=der Response) ja auch Content-Type application/json; charset=utf-8

d.h. hier wird das explizit mitgegeben...
 
Zurück
Oben