天天看点

Volley框架源码修改,添加头部验证Hreaders问题

应项目要求修改网络问题,为了让项目更加健壮,使用volley框架,这个android 推荐使用的网络框架,整体来说请求的方式网上都可以查的到,这里就不说,现在就说说添加头部验证,因为我们的项目在请求每一个链接的时候都会验证,所以添加头部是一个十分必要的情况。网上说让在请求里边添加getheaders()方法,方法是确实能用,但是是有前提的。

主要是使用不同的队列的问题:

    (1)volley.newrequestqueue(this)

        如果是调用这个方法的话,那么在执行stringrequest方法的时候调用的httpclientstack  这个类中的访问网络的方法:

/*

 * copyright (c) 2011 the android open source project

 *

 * licensed under the apache license, version 2.0 (the "license");

 * you may not use this file except in compliance with the license.

 * you may obtain a copy of the license at

 *      http://www.apache.org/licenses/license-2.0

 * unless required by applicable law or agreed to in writing, software

 * distributed under the license is distributed on an "as is" basis,

 * without warranties or conditions of any kind, either express or implied.

 * see the license for the specific language governing permissions and

 * limitations under the license.

 */

package com.android.volley.toolbox;

import com.android.volley.authfailureerror;

import com.android.volley.request;

import com.android.volley.request.method;

import org.apache.http.httpentity;

import org.apache.http.httpresponse;

import org.apache.http.namevaluepair;

import org.apache.http.client.httpclient;

import org.apache.http.client.methods.httpdelete;

import org.apache.http.client.methods.httpentityenclosingrequestbase;

import org.apache.http.client.methods.httpget;

import org.apache.http.client.methods.httppost;

import org.apache.http.client.methods.httpput;

import org.apache.http.client.methods.httpurirequest;

import org.apache.http.entity.bytearrayentity;

import org.apache.http.message.basicnamevaluepair;

import org.apache.http.params.httpconnectionparams;

import org.apache.http.params.httpparams;

import java.io.ioexception;

import java.util.arraylist;

import java.util.list;

import java.util.map;

/**

 * an httpstack that performs request over an {@link httpclient}.

public class httpclientstack implements httpstack {

    protected final httpclient mclient;

    private final static string header_content_type = "content-type";

    public httpclientstack(httpclient client) {

        mclient = client;

    }

    private static void addheaders(httpurirequest httprequest, map<string, string> headers) {

        for (string key : headers.keyset()) {

            httprequest.setheader(key, headers.get(key));

        }

    @suppresswarnings("unused")

    private static list<namevaluepair> getpostparameterpairs(map<string, string> postparams) {

        list<namevaluepair> result = new arraylist<namevaluepair>(postparams.size());

        for (string key : postparams.keyset()) {

            result.add(new basicnamevaluepair(key, postparams.get(key)));

        return result;

    @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);

    /**

     * 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());

                    postrequest.setheader("authorization","basic yw5vbnltb3vzojeymzq1ng==");

                    httpentity entity;

                    entity = new bytearrayentity(postbody);

                    postrequest.setentity(entity);

                    return postrequest;

                } else {

                    return new httpget(request.geturl());

                }

            }

            case method.get:

            httpget  httpget  =new httpget(request.geturl());

//             httpget.setheader("authorization","basic yw5vbnltb3vzojeymzq1ng==");

                return httpget;

            case method.delete:

            httpdelete  httpdelete =new httpdelete(request.geturl());

                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;

            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);

     * called before the request is executed using the underlying httpclient.

     *

     * <p>overwrite in subclasses to augment the request.</p>

    protected void onpreparerequest(httpurirequest request) throws ioexception {

        // nothing.

}

可以看到,这个里边是使用了httpclient    来进行访问网络,但是再他设置访问方式的时候没有调用getheaders这个方法

@override

public map<string, string> getheaders() throws authfailureerror {

map<string, string> headers = new hashmap<string, string>();

// headers.put("charset", "utf-8");

// headers.put("content-type", "application/x-javascript");

// headers.put("accept-encoding", "gzip,deflate");

headers.put("authorization", "basic yw5vbnltb3vzojeymzq1ng==");

return headers;

//设置超时

public retrypolicy getretrypolicy() {

retrypolicy retrypolicy = new defaultretrypolicy(1000,

defaultretrypolicy.default_max_retries,

defaultretrypolicy.default_backoff_mult);

return retrypolicy;

     也就不会添加你设置的头部,那么访问肯定通不过。

所以你可以再里边给添加你的头部,或是,在里边调用getheaders方法,把头部添加到相应的请求里。

(2) volley.newrequestqueue(this,new hurlstack())

       这个创建的队列他在执行的时候调用的是httpurlconnition   这种访问网络的方式,

import org.apache.http.header;

import org.apache.http.protocolversion;

import org.apache.http.statusline;

import org.apache.http.entity.basichttpentity;

import org.apache.http.message.basicheader;

import org.apache.http.message.basichttpresponse;

import org.apache.http.message.basicstatusline;

import java.io.dataoutputstream;

import java.io.inputstream;

import java.net.httpurlconnection;

import java.net.url;

import java.util.hashmap;

import java.util.map.entry;

import javax.net.ssl.httpsurlconnection;

import javax.net.ssl.sslsocketfactory;

 * an {@link httpstack} based on {@link httpurlconnection}.

public class hurlstack implements httpstack {

    private static final string header_content_type = "content-type";

     * an interface for transforming urls before use.

    public interface urlrewriter {

        /**

         * returns a url to use instead of the provided one, or null to indicate

         * this url should not be used at all.

         */

        public string rewriteurl(string originalurl);

    private final urlrewriter murlrewriter;

    private final sslsocketfactory msslsocketfactory;

    public hurlstack() {

        this(null);

     * @param urlrewriter rewriter to use for request urls

    public hurlstack(urlrewriter urlrewriter) {

        this(urlrewriter, null);

     * @param sslsocketfactory ssl factory to use for https connections

    public hurlstack(urlrewriter urlrewriter, sslsocketfactory sslsocketfactory) {

        murlrewriter = urlrewriter;

        msslsocketfactory = sslsocketfactory;

        string url = request.geturl();

        hashmap<string, string> map = new hashmap<string, string>();

        map.putall(request.getheaders());

        map.putall(additionalheaders);

        if (murlrewriter != null) {

            string rewritten = murlrewriter.rewriteurl(url);

            if (rewritten == null) {

                throw new ioexception("url blocked by rewriter: " + url);

            url = rewritten;

        url parsedurl = new url(url);

        httpurlconnection connection = openconnection(parsedurl, request);

        for (string headername : map.keyset()) {

            connection.addrequestproperty(headername, map.get(headername));

        setconnectionparametersforrequest(connection, request);

        // initialize httpresponse with data from the httpurlconnection.

        protocolversion protocolversion = new protocolversion("http", 1, 1);

        int responsecode = connection.getresponsecode();

        if (responsecode == -1) {

            // -1 is returned by getresponsecode() if the response code could not be retrieved.

            // signal to the caller that something was wrong with the connection.

            throw new ioexception("could not retrieve response code from httpurlconnection.");

        statusline responsestatus = new basicstatusline(protocolversion,

                connection.getresponsecode(), connection.getresponsemessage());

        basichttpresponse response = new basichttpresponse(responsestatus);

        response.setentity(entityfromconnection(connection));

        for (entry<string, list<string>> header : connection.getheaderfields().entryset()) {

            if (header.getkey() != null) {

                header h = new basicheader(header.getkey(), header.getvalue().get(0));

                response.addheader(h);

        return response;

     * initializes an {@link httpentity} from the given {@link httpurlconnection}.

     * @param connection

     * @return an httpentity populated with data from <code>connection</code>.

    private static httpentity entityfromconnection(httpurlconnection connection) {

        basichttpentity entity = new basichttpentity();

        inputstream inputstream;

        try {

            inputstream = connection.getinputstream();

        } catch (ioexception ioe) {

            inputstream = connection.geterrorstream();

        entity.setcontent(inputstream);

        entity.setcontentlength(connection.getcontentlength());

        entity.setcontentencoding(connection.getcontentencoding());

        entity.setcontenttype(connection.getcontenttype());

        return entity;

     * create an {@link httpurlconnection} for the specified {@code url}.

    protected httpurlconnection createconnection(url url) throws ioexception {

        return (httpurlconnection) url.openconnection();

     * opens an {@link httpurlconnection} with parameters.

     * @param url

     * @return an open connection

     * @throws ioexception

    private httpurlconnection openconnection(url url, request<?> request) throws ioexception {

        httpurlconnection connection = createconnection(url);

        connection.setconnecttimeout(timeoutms);

        connection.setreadtimeout(timeoutms);

        connection.setusecaches(false);

        connection.setdoinput(true);

        // use caller-provided custom sslsocketfactory, if any, for https

        if ("https".equals(url.getprotocol()) && msslsocketfactory != null) {

            ((httpsurlconnection)connection).setsslsocketfactory(msslsocketfactory);

        return connection;

    /* package */ static void setconnectionparametersforrequest(httpurlconnection connection,

            request<?> request) throws ioexception, authfailureerror {

            case method.deprecated_get_or_post:

                    // prepare output. there is no need to set content-length explicitly,

                    // since this is handled by httpurlconnection using the size of the prepared

                    // output stream.

                    connection.setdooutput(true);

                    connection.setrequestmethod("post");

                    connection.addrequestproperty(header_content_type,

                            request.getpostbodycontenttype());

                    dataoutputstream out = new dataoutputstream(connection.getoutputstream());

                    out.write(postbody);

                    out.close();

                break;

                // not necessary to set the request method because connection defaults to get but

                // being explicit here.

                connection.setrequestmethod("get");

                connection.setrequestmethod("delete");

            case method.post:

                connection.setrequestmethod("post");

                addbodyifexists(connection, request);

            case method.put:

                connection.setrequestmethod("put");

                throw new illegalstateexception("unknown method type.");

    private static void addbodyifexists(httpurlconnection connection, request<?> request)

            connection.setdooutput(true);

            connection.addrequestproperty(header_content_type, request.getbodycontenttype());

            dataoutputstream out = new dataoutputstream(connection.getoutputstream());

            out.write(body);

            out.close();

从这个代码中可以看到,

Volley框架源码修改,添加头部验证Hreaders问题

         可以看到这里边他调用了getheaders这个方法,会给你添加相应的头部,所以,也可以使用这个。