PATCH request with Volley does not work

0

I tried to update the data of my server with Volley by means of the PATCH method sending the data in a body, the form is the following:

String url = getString(R.string.ws_base) + getString(R.string.ws_ip) + getString(R.string.ws_servicios);
    String wsUsuario ="";
    if(SingletonUsuario.getInstance().getUsuario().getTipoUsuario() == Usuario.TIPO_CONDUCTOR){
        wsUsuario = getString(R.string.ws_conductores);
    }else {
        wsUsuario = getString(R.string.ws_pasajeros);
    }
    url +=  wsUsuario + SingletonUsuario.getInstance().getUsuario().getDni()+"/";

    MyApplication.volleyQueueInstance.cancelRequestInQueue(SEND_REGISTRATION_TOKEN_SERVER);

    JSONObject body = new JSONObject();
    try {
        body.put("firebase_token", token);
    } catch (JSONException e) { e.printStackTrace(); }

    //build Get url of Place Autocomplete and hit the url to fetch result.
    HashMap<String, String> head = new HashMap<String, String>();

    head.put(HEADER_CONTENT_TYPE, HEADER_JSON);
    head.put(HEADER_AUTHORIZATION, TOKEN + " " + SingletonUsuario.getInstance().getUsuario().getTokenOauth());
    VolleyJSONRequest request = new VolleyJSONRequest(Request.Method.PATCH, url, body.toString(), head, MyFirebaseInstanceIDService.this, MyFirebaseInstanceIDService.this);

    //Give a tag to your request so that you can use this tag to cancle request later.
    request.setTag(SEND_REGISTRATION_TOKEN_SERVER);

    MyApplication.volleyQueueInstance.addToRequestQueue(request);

In the server it says to me like that it can not read the body, the same request I do it with HttpClient and it works correctly, in the following way: (I send the same variables that I used in the previous code)

RestCustomer r = new RestCustomer(this, url, body, Constantes.PATCH,     SingletonUsuario.getInstance().getUsuario().getTokenOauth());
    r.execute();

And within my RestCustomer I have:

protected String doInBackground(Void... params) {
    String objetoRespuesta = null;
    try {
        HttpClient hc = new DefaultHttpClient();
        String message = body.toString();

        HttpUriRequest request = null;
        switch (metodo) {
            case Constantes.POST:
                HttpPost httpPost = new HttpPost(url.toString());
                httpPost.setEntity(new StringEntity(message, "UTF8"));
                httpPost.setHeader("Content-type", "application/json");
                if (header != null) {
                    httpPost.addHeader("Authorization", "Token " + header);
                }
                request = httpPost;
                break;
            case Constantes.GET:
                HttpGet httpGet = new HttpGet(url.toString());
                //httpGet.setEntity(new StringEntity(message, "UTF8"));
                httpGet.setHeader("Content-type", "application/json");
                request = new HttpGet(url.toString());
                break;
            case Constantes.PATCH:
                HttpClientStack.HttpPatch httpPatch = new HttpClientStack.HttpPatch(url.toString());
                httpPatch.setEntity(new StringEntity(message, "UTF8"));
                httpPatch.setHeader("Content-type", "application/json");
                if (header != null) {
                    httpPatch.addHeader("Authorization", "Token " + header);
                }
                request = httpPatch;
        }


        //p.setEntity(new StringEntity(message, "UTF8"));
        //p.setHeader("Content-type", "application/json");
        HttpResponse resp = hc.execute(request);
        if (resp != null) {
            if (resp.getStatusLine().getStatusCode() == 204)
                result = resp.getStatusLine().toString();
        }
        objetoRespuesta = EntityUtils.toString(resp.getEntity());
        Log.d("Status line", "" + resp.getStatusLine().getStatusCode());

    } catch (Exception e) {
        Log.e("RestCustomer: ", e.getMessage(), e);
        result = e.getMessage();
    }

    return objetoRespuesta;
} 

This is correct, the only difference I see is that the message (body) sends the "UTF8", how could I send it in my Volley? I leave the Volley class I use:

public class VolleyJSONRequest extends JsonRequest<String> {

String mUrl;
private Response.Listener<String> listener;
private Response.ErrorListener errorListener;
private Map<String, String> headers = new HashMap<>();


public VolleyJSONRequest(int method, String url, String params, HashMap<String, String> head, Response.Listener<String> listener, Response.ErrorListener errorListener) {

    super(method, url, params, listener, errorListener);
    this.listener = listener;
    this.errorListener = errorListener;
    this.mUrl = url;

    if(head!=null){
        headers.putAll(head);
    }

    headers.put("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; google_sdk Build/MR1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30");
    headers.put("Accept", "application/json");
}


@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    return headers;
}

@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
    try {
        // Volley does not handle null properly, so implement null response
        // check
        if (response.data.length == 0) {
            byte[] responseData = "{}".getBytes("UTF8");
            response = new NetworkResponse(response.statusCode,
                    responseData, response.headers, response.notModified);
        }


        String jsonString = new String(response.data,
                HttpHeaderParser.parseCharset(response.headers));


        return Response.success(
                jsonString,
                parseIgnoreCacheHeaders(response));

    } catch (UnsupportedEncodingException e) {
        System.out.println("VolleyQueue: Encoding Error for " + getTag()
                + " (" + getSequence() + ")");
        return Response.error(new ParseError(e));
    }
}


/**
 * Extracts a {@link Cache.Entry} from a {@link NetworkResponse}.
 * Cache-control headers are ignored. SoftTtl == 15 mins, ttl == 24 hours.
 *
 * @param response The network response to parse headers from
 * @return a cache entry for the given response, or null if the response is
 * not cacheable.
 */
public Cache.Entry parseIgnoreCacheHeaders(NetworkResponse response) {
    long now = System.currentTimeMillis();

    Map<String, String> headers = response.headers;
    long serverDate = 0;
    String serverEtag = null;
    String headerValue;

    headerValue = headers.get("Date");
    if (headerValue != null) {
        serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
    }
    serverEtag = headers.get("ETag");

    long cacheHitButRefreshed = 0;
    long cacheExpired = 0;

    cacheExpired = 0;   //change value if caching required
    cacheHitButRefreshed = 0;

    final long softExpire = now + cacheHitButRefreshed;
    final long ttl = now + cacheExpired;

    Cache.Entry entry = new Cache.Entry();
    entry.data = response.data;
    entry.etag = serverEtag;
    entry.softTtl = softExpire;
    entry.ttl = ttl;
    entry.serverDate = serverDate;
    entry.responseHeaders = headers;

    return entry;
}

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

@Override
public void deliverError(VolleyError error) {
    super.deliverError(error);
}

}

Class from which Volley extends:

public abstract class JsonRequest<T> extends Request<T> {
/** Default charset for JSON request. */
protected static final String PROTOCOL_CHARSET = "utf-8";

/** Content type for request. */
private static final String PROTOCOL_CONTENT_TYPE =
    String.format("application/json; charset=%s", PROTOCOL_CHARSET);

private Listener<T> mListener;
private final String mRequestBody;

/**
 * Deprecated constructor for a JsonRequest which defaults to GET unless {@link #getPostBody()}
 * or {@link #getPostParams()} is overridden (which defaults to POST).
 *
 * @deprecated Use {@link #JsonRequest(int, String, String, Listener, ErrorListener)}.
 */
public JsonRequest(String url, String requestBody, Listener<T> listener,
        ErrorListener errorListener) {
    this(Method.DEPRECATED_GET_OR_POST, url, requestBody, listener, errorListener);
}

public JsonRequest(int method, String url, String requestBody, Listener<T> listener,
        ErrorListener errorListener) {
    super(method, url, errorListener);
    mListener = listener;
    mRequestBody = requestBody;
}

@Override
protected void onFinish() {
    super.onFinish();
    mListener = null;
}

@Override
protected void deliverResponse(T response) {
    if (mListener != null) {
        mListener.onResponse(response);
    }
}

@Override
abstract protected Response<T> parseNetworkResponse(NetworkResponse response);

/**
 * @deprecated Use {@link #getBodyContentType()}.
 */
@Override
public String getPostBodyContentType() {
    return getBodyContentType();
}

/**
 * @deprecated Use {@link #getBody()}.
 */
@Override
public byte[] getPostBody() {
    return getBody();
}

@Override
public String getBodyContentType() {
    return PROTOCOL_CONTENT_TYPE;
}

@Override
public byte[] getBody() {
    try {
        return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);
    } catch (UnsupportedEncodingException uee) {
        VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
                mRequestBody, PROTOCOL_CHARSET);
        return null;
    }
}

}

The server returns 415, does not understand what I send in the body.

Any help is welcome, thank you very much. Greetings.

    
asked by Emanuel Duprat 29.10.2016 в 00:07
source

1 answer

0

The Error 415 that reports your code when you make the request refers to a Media Type not supported.

The requests that you have defined in your code are configured to be typo "application/json"

You must ensure that the url is actually a% file% of%

    
answered by 29.10.2016 в 00:59