Cómo configurar un encabezado personalizado en la solicitud de volea

104

¿Cómo se pueden configurar encabezados personalizados para una solicitud de Volley? Por el momento, existe una forma de establecer el contenido del cuerpo de una solicitud POST. Tengo una solicitud GET simple, pero necesito pasar los encabezados personalizados junto con. No veo cómo la clase JsonRequest lo admite. ¿Es posible en absoluto?

bianca
fuente
por favor cambie la respuesta aceptada, la actualmente aceptada es incorrecta.
Esteban

Respuestas:

119

Parece que anula public Map<String, String> getHeaders(), definido enRequest , para devolver los encabezados HTTP deseados.

CommonsWare
fuente
4
@ JuanJoséMeleroGómez el enlace está roto. 404 No encontrado
Milon
Aquí hay otro ejemplo (el fragmento al final de la página): developer.android.com/training/volley/request-custom.html . La clase GsonRequestanula el método getHeaders()para devolver un mapa con los parámetros de encabezado que pasa en el constructor.
Juan José Melero Gómez
157

La respuesta aceptada con getParams () es para configurar los datos del cuerpo POST, pero la pregunta en el título preguntaba cómo configurar los encabezados HTTP como User-Agent. Como dijo CommonsWare, anula getHeaders (). Aquí hay un código de muestra que establece el User-Agent en 'Nintendo Gameboy' y Accept-Language en 'fr':

public void requestWithSomeHttpHeaders() {
    RequestQueue queue = Volley.newRequestQueue(this);
    String url = "http://www.somewebsite.com";
    StringRequest getRequest = new StringRequest(Request.Method.GET, url, 
        new Response.Listener<String>() 
        {
            @Override
            public void onResponse(String response) {
                // response
                Log.d("Response", response);
            }
        }, 
        new Response.ErrorListener() 
        {
            @Override
            public void onErrorResponse(VolleyError error) {
                // TODO Auto-generated method stub
                Log.d("ERROR","error => "+error.toString());
            }
        }
    ) {     
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError { 
                Map<String, String>  params = new HashMap<String, String>();  
                params.put("User-Agent", "Nintendo Gameboy");  
                params.put("Accept-Language", "fr");

                return params;  
        }
    };
    queue.add(getRequest);

}
georgiecasey
fuente
¿Esta respuesta también funcionará para JSONObjectRequest? JSONObjectRequest postRequest = new JSONObjectRequest ...... porque estoy haciendo esto y mi getHeaders () no está siendo llamado ... ??? Entiendo que está creando una clase anónima y anulando los métodos. Estoy haciendo eso solo con JSONObjectRequest en lugar de StringRequest y no se llama a mi getHeaders ().
JDOaktown
¿Podemos agregar "Cookie" en el método getHeaders () también? ¿Funcionará también para solicitudes de publicación?
Arnab Banerjee
¿Dónde enviaré el resto de datos POST?
Fernando Torres
30

Si lo que necesita es publicar datos en lugar de agregar la información en la url.

public Request post(String url, String username, String password, 
      Listener listener, ErrorListener errorListener) {
  JSONObject params = new JSONObject();
  params.put("user", username);
  params.put("pass", password);
  Request req = new Request(
     Method.POST,
     url,
     params.toString(),
     listener,
     errorListener
  );

  return req;
}

Si lo que quiere hacer es editar los encabezados en la solicitud, esto es lo que quiere hacer:

// could be any class that implements Map
Map<String, String> mHeaders = new ArrayMap<String, String>();
mHeaders.put("user", USER);
mHeaders.put("pass", PASSWORD);
Request req = new Request(url, postBody, listener, errorListener) {
  public Map<String, String> getHeaders() {
    return mHeaders;
  }
}
thepoosh
fuente
44
Voté en contra ya que esto no es lo que se hizo la pregunta en absoluto. Esto es para configurar el contenido POST, no para configurar encabezados HTTP personalizados como User-Agent. Z h. Atanasov y CommonsWare tienen razón en sus getHeadersrespuestas.
georgiecasey
4
Rechacé esta respuesta porque esto no es lo que el usuario ha preguntado.
Dharmendra Pratap Singh
1
Esto es para agregar parámetros de contenido, no encabezados, lo siento, también se votó en contra. Realmente no debería ser la respuesta aceptada
Juan Cortés
1
¿Puedes echar un vistazo a mi pregunta? Es similar a esto, pero no pude hacerlo bien stackoverflow.com/a/37948318
X09
18

Puedes ver esta solución. Muestra cómo obtener / configurar cookies, pero las cookies son solo uno de los encabezados en una solicitud / respuesta. Tienes que anular una de las clases de solicitud de Volley * y establecer los encabezados requeridos engetHeaders()


Aquí está la fuente vinculada:

public class StringRequest extends com.android.volley.toolbox.StringRequest {

private final Map<String, String> _params;

/**
 * @param method
 * @param url
 * @param params
 *            A {@link HashMap} to post with the request. Null is allowed
 *            and indicates no parameters will be posted along with request.
 * @param listener
 * @param errorListener
 */
public StringRequest(int method, String url, Map<String, String> params, Listener<String> listener,
        ErrorListener errorListener) {
    super(method, url, listener, errorListener);

    _params = params;
}

@Override
protected Map<String, String> getParams() {
    return _params;
}

/* (non-Javadoc)
 * @see com.android.volley.toolbox.StringRequest#parseNetworkResponse(com.android.volley.NetworkResponse)
 */
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
    // since we don't know which of the two underlying network vehicles
    // will Volley use, we have to handle and store session cookies manually
    MyApp.get().checkSessionCookie(response.headers);

    return super.parseNetworkResponse(response);
}

/* (non-Javadoc)
 * @see com.android.volley.Request#getHeaders()
 */
@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>();
    }

    MyApp.get().addSessionCookie(headers);

    return headers;
}

}

Y la clase MyApp:

public class MyApp extends Application {
    private static final String SET_COOKIE_KEY = "Set-Cookie";
    private static final String COOKIE_KEY = "Cookie";
    private static final String SESSION_COOKIE = "sessionid";

    private static MyApp _instance;
    private RequestQueue _requestQueue;
    private SharedPreferences _preferences;

    public static MyApp get() {
        return _instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        _instance = this;
            _preferences = PreferenceManager.getDefaultSharedPreferences(this);
        _requestQueue = Volley.newRequestQueue(this);
    }

    public RequestQueue getRequestQueue() {
        return _requestQueue;
    }


    /**
     * Checks the response headers for session cookie and saves it
     * if it finds it.
     * @param headers Response Headers.
     */
    public final void checkSessionCookie(Map<String, String> headers) {
        if (headers.containsKey(SET_COOKIE_KEY)
                && headers.get(SET_COOKIE_KEY).startsWith(SESSION_COOKIE)) {
                String cookie = headers.get(SET_COOKIE_KEY);
                if (cookie.length() > 0) {
                    String[] splitCookie = cookie.split(";");
                    String[] splitSessionId = splitCookie[0].split("=");
                    cookie = splitSessionId[1];
                    Editor prefEditor = _preferences.edit();
                    prefEditor.putString(SESSION_COOKIE, cookie);
                    prefEditor.commit();
                }
            }
    }

    /**
     * Adds session cookie to headers if exists.
     * @param headers
     */
    public final void addSessionCookie(Map<String, String> headers) {
        String sessionId = _preferences.getString(SESSION_COOKIE, "");
        if (sessionId.length() > 0) {
            StringBuilder builder = new StringBuilder();
            builder.append(SESSION_COOKIE);
            builder.append("=");
            builder.append(sessionId);
            if (headers.containsKey(COOKIE_KEY)) {
                builder.append("; ");
                builder.append(headers.get(COOKIE_KEY));
            }
            headers.put(COOKIE_KEY, builder.toString());
        }
    }

}
Z h. Atanasov
fuente
7

En Kotlin,

Tienes que anular el método getHeaders () como:

val volleyEnrollRequest = object : JsonObjectRequest(GET_POST_PARAM, TARGET_URL, PAYLOAD_BODY_IF_YOU_WISH,
            Response.Listener {
                // Success Part  
            },

            Response.ErrorListener {
                // Failure Part
            }
        ) {
            // Providing Request Headers

            override fun getHeaders(): Map<String, String> {
               // Create HashMap of your Headers as the example provided below

                val headers = HashMap<String, String>()
                headers["Content-Type"] = "application/json"
                headers["app_id"] = APP_ID
                headers["app_key"] = API_KEY

                return headers
            }
        }
devDeejay
fuente
1
Este es el único recurso que pude encontrar para anular encabezados en Kotlin. ¡Gracias!
Mathew Sonke
@MathewSonke te siento hermano. Por cierto, intente Retrofit para redes en Android.
devDeejay
6

Buscando una solución a este problema también. vea algo aquí: http://developer.android.com/training/volley/request.html

¿Es una buena idea usar ImageRequest directamente en lugar de ImageLoader? Parece que ImageLoader lo usa internamente de todos modos. ¿Falta algo importante además del soporte de caché de ImageLoader?

ImageView mImageView;
String url = "http://i.imgur.com/7spzG.png";
mImageView = (ImageView) findViewById(R.id.myImage);
...

// Retrieves an image specified by the URL, displays it in the UI.
mRequestQueue = Volley.newRequestQueue(context);;
ImageRequest request = new ImageRequest(url,
  new Response.Listener() {
      @Override
      public void onResponse(Bitmap bitmap) {
          mImageView.setImageBitmap(bitmap);
      }
  }, 0, 0, null,
  new Response.ErrorListener() {
      public void onErrorResponse(VolleyError error) {
          mImageView.setImageResource(R.drawable.image_load_error);
      }
  })   {
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> params = new Map<String, String>();
        params.put("User-Agent", "one");
        params.put("header22", "two");

        return params;
    };
mRequestQueue.add(request);
lannyf
fuente
Sería muy apreciado y más útil si pudiera señalar por qué cree que la pregunta es incorrecta o que la solución planteada tiene un problema, en lugar de simplemente darle un "-1".
lannyf
1
El mapa es abstracto. Debería ser HashMap
superuserdo
4

prueba esto

{
    @Override
       public Map<String, String> getHeaders() throws AuthFailureError {
           String bearer = "Bearer ".concat(token);
            Map<String, String> headersSys = super.getHeaders();
            Map<String, String> headers = new HashMap<String, String>();
            headersSys.remove("Authorization");
            headers.put("Authorization", bearer);
            headers.putAll(headersSys);
            return headers;
       }
};
AntuJorge
fuente
4

Puede crear una clase Request personalizada que amplíe StringRequest y anule el método getHeaders () dentro de ella de esta manera:

public class CustomVolleyRequest extends StringRequest {

    public CustomVolleyRequest(int method, String url,
                           Response.Listener<String> listener,
                           Response.ErrorListener errorListener) {
        super(method, url, listener, errorListener);
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = new HashMap<>();
        headers.put("key1","value1");
        headers.put("key2","value2");
        return headers;
    }
}
Khashayar Motarjemi
fuente
1
public class CustomJsonObjectRequest  extends JsonObjectRequest
{
    public CustomJsonObjectRequest(int method, String url, JSONObject jsonRequest,Response.Listener listener, Response.ErrorListener errorListener)
    {
        super(method, url, jsonRequest, listener, errorListener);
    }


@Override
public Map getHeaders() throws AuthFailureError {
    Map headers = new HashMap();
    headers.put("AppId", "xyz");

    return headers;
}

}
Navneet Boghani
fuente
1

Además, me gustaría compartir algo que encontré con respecto a Content-Type: Además de

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
.
.
.
return params;
}

Tuve que agregar:

@Override
public String getBodyContentType() {
return /*(for exmaple)*/ "application/json";
}

No me preguntes por qué, solo pensé que podría ayudar a algunos otros que no pueden hacer bien el Content-Typeset.

Jack
fuente
0

Aquí se configuran los encabezados de la muestra de github:

StringRequest myReq = new StringRequest(Method.POST,
                       "http://ave.bolyartech.com/params.php",
                        createMyReqSuccessListener(),
                        createMyReqErrorListener()) {

 protected Map<String, String> getParams() throws 
         com.android.volley.AuthFailureError {
                        Map<String, String> params = new HashMap<String, String>();
                        params.put("param1", num1);
                        params.put("param2", num2);
                        return params;
                    };
                };
                queue.add(myReq);
M.Kouchi
fuente
0

prueba esto

 public void VolleyPostReqWithResponseListenerwithHeaders(String URL,final Map<String, String> params,final Map<String, String> headers,Response.Listener<String> responseListener) {


    String url = URL;

    Log.i("url:", ":" + url);
    StringRequest mStringRequest = new StringRequest(Request.Method.POST,
            url, responseListener, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // error


            //Log.d("Error.Response", error.getLocalizedMessage());
        }
    }){
        @Override
        protected Map<String, String> getParams() {
            return params;
        }

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



    mStringRequest.setRetryPolicy(new DefaultRetryPolicy(
            60000,
            DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

    mStringRequest.setShouldCache(true);



    //  dialog.show();
    SingletonRequestQueue.getInstance(context).addToRequestQueue(mStringRequest);
}
Yigit Yuksel
fuente
@Override public Map <String, String> getHeaders () arroja AuthFailureError {encabezados de retorno; }};
Osama Ibrahim
¿Dónde está el encabezado?
Osama Ibrahim
En signutare, puede configurarlo cuando llame con los encabezados Map <String, String>
Yigit Yuksel
0

Ese es mi código, no olvides = objeto: si no pones no funciona

val queue = Volley.newRequestQueue(this)
        val url = "http://35.237.133.137:8080/lamarrullaWS/rest/lamarrullaAPI"
        // Request a string response from the provided URL.
        val jsonObjectRequest = object: JsonObjectRequest(Request.Method.GET, url, null,
                Response.Listener { response ->
                    txtPrueba.text = "Response: %s".format(response.toString())
                },
                Response.ErrorListener { txtPrueba.text = "That didn't work!" }
        )
        {
            @Throws(AuthFailureError::class)
            override fun getHeaders(): Map<String, String> {
                val headers = HashMap<String, String>()
                headers.put("Content-Type", "application/json")
                return headers
            }
        }
        queue.add(jsonObjectRequest)
Dave Rincón
fuente