Frage Volley - wie man DELETE Anfrageparameter sendet?


Ich versuche, Volley zu verwenden, um eine Anforderung vom Typ DELETE an meinen Server zu senden und der Anforderung Parameter hinzuzufügen. Bisher war ich dazu nicht in der Lage.

Das Erstellen einer benutzerdefinierten Anforderung und das Überschreiben der Methode "getParams ()" hat mir nicht weitergeholfen, da diese Methode nicht für die Anforderung vom Typ DELETE aufgerufen wird.

Wie kann ich einer DELETE-Anfrage in Volley Parameter hinzufügen?


10
2018-04-02 06:59


Ursprung


Antworten:


Das gleiche Problem hier, aber ich habe die Lösung gefunden.

Das Problem ist die Implementierung der createHttpRequest-Methode in com.android.volley.toolbox.HttpClientStack.java, die den Rumpf nur dann hinzufügt, wenn die Anfrage-Methode POST, PUT oder PATCH ist.

/**
 * Creates the appropriate subclass of HttpUriRequest for passed in request.
 */
@SuppressWarnings("deprecation")
/* protected */ static HttpUriRequest createHttpRequest(Request<?> request,
        Map<String, String> additionalHeaders) throws AuthFailureError {
    switch (request.getMethod()) {
        case Method.DEPRECATED_GET_OR_POST: {
            // This is the deprecated way that needs to be handled for backwards compatibility.
            // If the request's post body is null, then the assumption is that the request is
            // GET.  Otherwise, it is assumed that the request is a POST.
            byte[] postBody = request.getPostBody();
            if (postBody != null) {
                HttpPost postRequest = new HttpPost(request.getUrl());
                postRequest.addHeader(HEADER_CONTENT_TYPE, request.getPostBodyContentType());
                HttpEntity entity;
                entity = new ByteArrayEntity(postBody);
                postRequest.setEntity(entity);
                return postRequest;
            } else {
                return new HttpGet(request.getUrl());
            }
        }
        case Method.GET:
            return new HttpGet(request.getUrl());
        case Method.DELETE:
            return new HttpDelete(request.getUrl());
        case Method.POST: {
            HttpPost postRequest = new HttpPost(request.getUrl());
            postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
            setEntityIfNonEmptyBody(postRequest, request);
            return postRequest;
        }
        case Method.PUT: {
            HttpPut putRequest = new HttpPut(request.getUrl());
            putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
            setEntityIfNonEmptyBody(putRequest, request);
            return putRequest;
        }
        case Method.HEAD:
            return new HttpHead(request.getUrl());
        case Method.OPTIONS:
            return new HttpOptions(request.getUrl());
        case Method.TRACE:
            return new HttpTrace(request.getUrl());
        case Method.PATCH: {
            HttpPatch patchRequest = new HttpPatch(request.getUrl());
            patchRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
            setEntityIfNonEmptyBody(patchRequest, request);
            return patchRequest;
        }
        default:
            throw new IllegalStateException("Unknown request method.");
    }
}

Sie müssen also Ihre eigene Implementierung von HttpStack.java verwenden oder die HttpClientStack-Klasse überschreiben.

Zuallererst sollten Sie Ihre Initialisierung von RequestQueue ersetzen

RequestQueue requestQueue = Volley.newRequestQueue(sContext);

zu

    String userAgent = "volley/0";
    try {
        String packageName = getContext().getPackageName();
        PackageInfo info = getContext().getPackageManager().getPackageInfo(packageName, 0);
        userAgent = packageName + "/" + info.versionCode;
    } catch (PackageManager.NameNotFoundException e) {}
    HttpStack httpStack = new OwnHttpClientStack(AndroidHttpClient.newInstance(userAgent));
    RequestQueue requesQueue = Volley.newRequestQueue(sContext, httpStack);

und schreiben Sie Ihre eigene Implementierung von HttpClientStack, wo Sie den Fall von "Method.POST:" in der Methode createHttpRequest () ändern. Sie müssen auch ein Objekt wie "OwnHttpDelete" als Erweiterung von HttpEntityEnclosingRequestBase erstellen, um die Methode setEntityIfNonEmptyBody () zu verwenden.

public class OwnHttpClientStack extends com.android.volley.toolbox.HttpClientStack {
    private final static String HEADER_CONTENT_TYPE = "Content-Type";

    public OwnHttpClientStack(HttpClient client) {
        super(client);
    }

    @Override
    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
            throws IOException, AuthFailureError {
        HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders);
        addHeaders(httpRequest, additionalHeaders);
        addHeaders(httpRequest, request.getHeaders());
        onPrepareRequest(httpRequest);
        HttpParams httpParams = httpRequest.getParams();
        int timeoutMs = request.getTimeoutMs();
        // TODO: Reevaluate this connection timeout based on more wide-scale
        // data collection and possibly different for wifi vs. 3G.
        HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
        HttpConnectionParams.setSoTimeout(httpParams, timeoutMs);
        return mClient.execute(httpRequest);
    }

    private static void addHeaders(HttpUriRequest httpRequest, Map<String, String> headers) {
        for (String key : headers.keySet()) {
            httpRequest.setHeader(key, headers.get(key));
        }
    }

    static HttpUriRequest createHttpRequest(Request<?> request, Map<String, String> additionalHeaders) throws AuthFailureError {
        switch (request.getMethod()) {
            case Request.Method.DEPRECATED_GET_OR_POST: {
                byte[] postBody = request.getPostBody();
                if (postBody != null) {
                    HttpPost postRequest = new HttpPost(request.getUrl());
                    postRequest.addHeader(HEADER_CONTENT_TYPE, request.getPostBodyContentType());
                    HttpEntity entity;
                    entity = new ByteArrayEntity(postBody);
                    postRequest.setEntity(entity);
                    return postRequest;
                } else {
                    return new HttpGet(request.getUrl());
                }
            }
            case Request.Method.GET:
                return new HttpGet(request.getUrl());
            case Request.Method.DELETE:
                OwnHttpDelete deleteRequest =  new OwnHttpDelete(request.getUrl());
                deleteRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
                setEntityIfNonEmptyBody(deleteRequest, request);
                return deleteRequest;
            case Request.Method.POST: {
                HttpPost postRequest = new HttpPost(request.getUrl());
                postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
                setEntityIfNonEmptyBody(postRequest, request);
                return postRequest;
            }
            case Request.Method.PUT: {
                HttpPut putRequest = new HttpPut(request.getUrl());
                putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
                setEntityIfNonEmptyBody(putRequest, request);
                return putRequest;
            }
            case Request.Method.HEAD:
                return new HttpHead(request.getUrl());
            case Request.Method.OPTIONS:
                return new HttpOptions(request.getUrl());
            case Request.Method.TRACE:
                return new HttpTrace(request.getUrl());
            case Request.Method.PATCH: {
                HttpPatch patchRequest = new HttpPatch(request.getUrl());
                patchRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
                setEntityIfNonEmptyBody(patchRequest, request);
                return patchRequest;
            }
            default:
                throw new IllegalStateException("Unknown request method.");
        }
    }

    private static void setEntityIfNonEmptyBody(HttpEntityEnclosingRequestBase httpRequest,
                                                Request<?> request) throws AuthFailureError {
        byte[] body = request.getBody();
        if (body != null) {
            HttpEntity entity = new ByteArrayEntity(body);
            httpRequest.setEntity(entity);
        }
    }

    private static class OwnHttpDelete extends HttpPost {
        public static final String METHOD_NAME = "DELETE";

        public OwnHttpDelete() {
            super();
        }

        public OwnHttpDelete(URI uri) {
            super(uri);
        }

        public OwnHttpDelete(String uri) {
            super(uri);
        }

        public String getMethod() {
            return METHOD_NAME;
        }
    }
}

Ich hoffe mein Code wird jemandem helfen. Es sollte auch möglich sein, Parameter zu einer HEAD-Anfrage hinzuzufügen.


12
2018-04-24 07:34



Nach einigem Lesen und ein wenig Durchforschen von Volleys Code, bin ich zu dem Schluss gekommen, dass es keine Möglichkeit gibt, Parameter an eine DELETE-Anfrage in Volley anzuhängen - höchstwahrscheinlich als Design-Wahl, da es verpönt scheint allgemein.

Ich wollte herausfinden, wie es geht, weil ich einen API-Schlüssel an jede Art von Anfrage, die ich an meinen Server sende, anhängen wollte.

Wenn jemand mit einem ähnlichen Problem konfrontiert wird, dann was ich getan habe (und ich bin mir ziemlich sicher, dass das der Weg ist, hier zu gehen) ist, senden Sie den API-Schlüssel im Header-Teil der Anfrage. Speziell in Volley bedeutet dies, die Methode "getHeaders ()" zu überschreiben und die benötigten Parameter hinzuzufügen.

Hier ist mein Code:

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    Map<String, String> headers = super.getHeaders();

    if (headers == null
            || headers.equals(Collections.emptyMap())) {
        headers = new HashMap<String, String>();
    }

    headers.put("API_KEY", apiKey);

    return headers;
}

2
2018-04-03 07:30