2016-06-29 17 views
0

Ich versuche gerade, einen RESTful Client zu implementieren, der dem HATEOAS Prinzip-Modul folgt, um in meiner Android App zu verwenden. Ich habe Googles Volley in meinem Ansatz verwendet. Ich habe die Request-Klasse von Volley erweitert, um ein benutzerdefiniertes Response-Objekt zu liefern. Hier sind die beiden Klassen:Volley behandelt keine mehrwertigen Header richtig

individuellen Anfrageklasse:

public class RestRequest extends Request<RestResponse> 
{ 
    private final Map<String, String> headers; 
    private final Response.Listener<RestResponse> listener; 

    public RestRequest(int requestType, String url, Map<String, String> headers, 
         Response.Listener<RestResponse> listener, 
         Response.ErrorListener error) 
    { 
     super(requestType, url, error); 
     this.listener = listener; 
     this.headers = headers; 
    } 

    @Override 
    public Map<String, String> getHeaders() throws AuthFailureError 
    { 
     return this.headers != null ? this.headers : super.getHeaders(); 
    } 

    @Override 
    protected Response<RestResponse> parseNetworkResponse(NetworkResponse response) 
    { 
     String responseBody = null; 
     try 
     { 
      responseBody = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); 
     } 
     catch (UnsupportedEncodingException e) 
     { 
      responseBody = new String(response.data); 
     } 
     for (Map.Entry<String, String> entry : response.headers.entrySet()) 
     { 
      System.out.println(entry.getKey() + " " + entry.getValue()); 
     } 
     return Response.success(new RestResponse(response.headers, 
               responseBody), HttpHeaderParser.parseCacheHeaders(response)); 
    } 

    @Override 
    protected void deliverResponse(RestResponse response) 
    { 
     listener.onResponse(response); 
    } 
} 

Benutzerdefinierte Antwortklasse:

public class RestResponse 
{ 
    private Map<String, String> responseHeaders; 
    private String responseBody; 

    public RestResponse(Map<String, String> responseHeaders, String responseBody) 
    { 
     this.responseHeaders = responseHeaders; 
     this.responseBody = responseBody; 
    } 

    public Map<String, String> getResponseHeaders() 
    { 
     return responseHeaders; 
    } 

    public String getResponseBody() { 
     return responseBody; 
    } 
} 

Wie Sie sehen, ich versuche, die response zu speichern speichern und die Response in meinem RestResponse Klasse. Meine Anfragen werden mit meiner RestRequest-Klasse fehlerfrei und fehlerfrei verarbeitet.

Das einzige Problem, mit dem ich konfrontiert bin, ist, dass ResponseHeaders nicht richtig gespeichert werden, oder zumindest das ist, wo ich etwas falsch mache. Aber wie kann man in sehen

protected Response<RestResponse> parseNetworkResponse(NetworkResponse response)

Ich gebe mein erstellt RestResponse die response Objekt aus response.headers kommen.

die abgerufenen Karte Wenn man durch den Header enthält, zeigt mir folgende:

I/System.out: Content-Length 0 
I/System.out: Date Wed, 29 Jun 2016 17:27:59 GMT 
I/System.out: link <https://LINK_1>;rel="link-1" 
I/System.out: Server Apache-Coyote/1.1 
I/System.out: X-Android-Received-Millis 1467221322063 
I/System.out: X-Android-Response-Source NETWORK 200 
I/System.out: X-Android-Selected-Protocol http/1.1 
I/System.out: X-Android-Sent-Millis 1467221322031 

Aber es soll noch einige Links in dem Link-Header zurück, wie wenn diese Anforderung durch Postman machen:

Content-Length →0 
Date →Wed, 29 Jun 2016 17:33:22 GMT 
Server →Apache-Coyote/1.1 
link →<LINK_1>;rel="link-1", <LINK_2>;rel="link-2", <LINK_3>;rel="link-3" 

Ich ersetzte offensichtlich die tatsächlichen Links durch Platzhalter, aber alles andere ist von echten Anrufen. Volley gibt mir immer nur einen Link und ich weiß nicht warum. Ist es eine falsche Implementierung in Volley oder mache ich hier etwas falsch? Vielen Dank im Voraus!

EDIT: Die System.out.print, wo es nach dem Protokoll platziert wurde hinzugefügt.

+0

Was schreibt diese System.out-Zeilen? – muratgu

+0

Diese stammen direkt von der parseNetworkResponse-Methode, ich habe sie einfach im obigen Beispiel entfernt, sollte ich meine Frage bearbeiten und sie zur besseren Übersicht wieder einfügen? Es ist eigentlich nur jeden Eintrag von response.headers und Drucken "Schlüsselwert" – kasokz

+0

@ kasolz vielleicht, wie sie gedruckt werden, ist falsch. Hast du die aktuellen Werte im Debugger-Watch-Fenster gesehen? – muratgu

Antwort

0

Ich denke, das Problem liegt wirklich bei Volley. Ich schaute in die Quelle von Volley, wo das NetworkResponse-Objekt erstellt wird, und fand heraus, dass der Header [], der vom HttpResponse-Objekt kommt, in eine Map konvertiert wird. Da Maps nur eindeutige Schlüssel haben können, führt dies zu fehlerhaftem Verhalten, da die Link-Header mehrwertig sein können. Stellen Sie sich vor, Sie fügen folgende Header in eine Map ein, wobei der Headername der Schlüssel und der Headerwert der Wert ist.

link: <http://example.com>; rel="example" 
link: <http://example1.com>; rel="example1" 
link: <http://example2.com>; rel="example2" 

Offensichtlich wird es nur eine linkheader links, weil der Standard-Map-Verhalten sein.