2017-08-21 4 views
3

Ich habe einen REST-API-Dienst geschrieben, der erfordert, dass alle Antworten JSON sind. Wenn der Go HTTP-Anfrageparser jedoch einen Fehler feststellt, wird 400 als Nur-Text-Antwort zurückgegeben, ohne dass jemals ein Handler aufgerufen wird. Beispiel:Wie kann ich Golong http 400 Antworten für Parse-Fehler anpassen?

> curl -i -H 'Authorization: Basic hi  
there' 'http://localhost:8080/test' -v 
* Trying ::1... 
* TCP_NODELAY set 
* Connected to localhost (::1) port 8080 (#0) 
> GET /test HTTP/1.1 
> Host: localhost:8080 
> User-Agent: curl/7.54.0 
> Accept: */* 
> Authorization: Basic hi 
> there 
> 
< HTTP/1.1 400 Bad Request 
HTTP/1.1 400 Bad Request 
< Content-Type: text/plain; charset=utf-8 
Content-Type: text/plain; charset=utf-8 
< Connection: close 
Connection: close 

< 
* Closing connection 0 

Beachten Sie die ungültige Autorisierungskopfzeile. Natürlich ist 400 die richtige Antwort, aber es ist natürlich Text/Ebene. Gibt es eine Möglichkeit, den Go http-Parser so zu konfigurieren, dass er benutzerdefinierte Fehlerreaktions-Medientypen und -körper verwendet?

+0

Verwenden Sie ein Framework von einer Art? Ich habe dieses Verhalten noch nie mit dem http-Handler stdlib gesehen. – Adrian

+0

Nein. Hier ist ein [dummes einfaches Beispiel] (https://play.golang.org/p/5iOUCklUeH). – theory

Antwort

1

Sie können nicht. Sie können diese http Quelle in net/finden, es geschieht nur, wenn der Antrag war fehlerhaft:

https://github.com/golang/go/blob/master/src/net/http/server.go#L1744

Ich denke, Ihr Problem eine neue Zeile in der Kopfzeile sein könnten Sie in curl hinzugefügt werden?

401, 403, 404, 500 Fehler können Sie mit json antworten, aber schlechte Anfragen oder schlechte Header (zu lang, fehlerhaft) werden innerhalb von server.go behandelt.

Es gibt derzeit keine Möglichkeit, solche Fehler abzufangen, obwohl es unter consideration ist, so dass Ihre einzige Lösung darin wäre, die Quelle stdlib zu patchen (ich empfehle das nicht). Da dieser Fehler jedoch nur angezeigt wird, wenn der Client einen Fehler gemacht hat und die Anforderung falsch ist, ist dies wahrscheinlich kein großes Problem. Der Grund für die Textantwort ist, dass ein Browser oder ein ähnlicher Client (wie curl ohne -v) nicht nur eine leere Antwort sieht. Sie könnten einen Proxy wie nginx vor Ihre App stellen, aber dann würden Sie die Anfrage nie sehen, da es sich um eine schlechte Anfrage handelt, Ihr Proxy würde damit umgehen.

Möglicherweise könnten Sie es mit einem Proxy wie Nginx vor tun, obwohl Sie eine bestimmte statische Fehlerseite für 400 Fehler einrichten und eine von Ihnen angegebene 400.json-Datei bereitstellen? Das ist die einzige Lösung, die mir einfällt. Eine Richtlinie so etwas wie dies könnte für nginx arbeiten:

error_page 400 /400.json; 

Wenn Sie diese Fehler in der Lage sein möchten, anpassen, vielleicht um einen Kommentar zu dem Thema hinzufügen verknüpft sie wissen lassen Sie dieses spezielle Problem hatte.

+0

Ich hatte Angst, das wäre die Antwort. Ja, der Zeilenumbruch ist der Fehler. Nein, es ist kein großes Problem, außer dass ich die API als "immer JSON zurückgeben muss, es sei denn, Go https gibt einen Fehler zurück, bevor mein Code die Anfrage jemals sieht". Ich schätze es, dass ich einen Körper in die Antwort mit einbeziehen möchte (obwohl es hier an Details mangelt, ich brauchte eine Weile, um den Fehler zu finden), aber im Idealfall könnte ich den Inhaltstyp und den Inhalt aller Antworten kontrollieren. Ich werde das Problem kommentieren, danke! – theory

-2

Wenn Sie die Standard-net/http-Bibliothek verwenden, können Sie den folgenden Code verwenden. Werfen Sie einen Blick auf diese Antwort Showing custom 404 error page with standard http package @Mostafa zu dem habe ich dieses Beispiel aus

func homeHandler(w http.ResponseWriter, r *http.Request) { 
    if r.URL.Path != "/" { 
     errorHandler(w, r, http.StatusNotFound) 
     return 
    } 
    fmt.Fprint(w, "welcome home") 
} 

func errorHandler(w http.ResponseWriter, r *http.Request, status int) { 
    w.WriteHeader(status) 
    if status == http.StatusNotFound { 
     // JSON Out here 
    } 
} 
+0

400 und 404 sind nicht das Gleiche. Bitte lesen Sie die Frage. – Adrian