HTTP类的实现

 HTTP类:

本类里面最后重要的方法为send方法,send方法是使用Bot包的程序进入HTTP类的主要入口点。通过请求Web服务器检索并发送数据。send方法会启动一个称为lowLevelSend发送命令。

send方法主要负责Cookie和自动重定向ixangde管理。

详细代码清单如下:

  1. package com.heaton.bot;
  2. import java.util.zip.*;
  3. import java.net.*;
  4. import java.io.*;
  5. /**
  6.  * This class implements an HTTP handler.  The low-level
  7.  * details are left to a derived(衍生) class.  Most likely you
  8.  * will be using the HTTPSocket class, which derives from
  9.  * this one.  This class handles these specific issues(具体的问题):
  10.  *
  11.  * + Cookies
  12.  * + The referrer tag
  13.  * + HTTP User Authentication(用户验证)
  14.  * + Automatic Redirection(自动重定向)
  15.  * + Parsing headers(剖析标题)
  16.  */
  17. public abstract class HTTP {
  18.   /**
  19.    * The body data that was downloaded during the last send.
  20.    */
  21.   protected byte body[];
  22.   /**
  23.    * The raw(原有的、生的) header text that was recieved during 
  24.    * the last send.
  25.    */
  26.   protected StringBuffer header = new StringBuffer();
  27.   /**
  28.    * The URL that was ultimately used during the last send.
  29.    */
  30.   protected String url;
  31.   /**
  32.    * True if the HTTP class should automatically follow HTTP
  33.    * redirects.
  34.    */
  35.   protected boolean autoRedirect = true;
  36.   /**
  37.    * The cookies that are being tracked by this HTTP session.
  38.    */
  39.   protected AttributeList cookieStore = new AttributeList();
  40.   /**
  41.    * The client headers, these are the headers that are sent
  42.    * to the server.
  43.    */
  44.   protected AttributeList clientHeaders = new AttributeList();
  45.   /**
  46.    * The server headers, these are the the headers that the
  47.    * server sends back.
  48.    */
  49.   protected AttributeList serverHeaders = new AttributeList();
  50.   /**
  51.    * True if session(会话) cookies should be used.
  52.    */
  53.   protected boolean useCookies = false;
  54.   /**
  55.    * True if permanent cookies should be used.
  56.    */
  57.   protected boolean usePermCookies = false;
  58.   /**
  59.    * The HTTP response(i.e. OK).  If NOT okay, this response is
  60.    * thrown as an exception.
  61.    */
  62.   protected String response;
  63.   /**
  64.    * The timeout in milliseconds.
  65.    */
  66.   protected int timeout = 30000;
  67.   /**
  68.    * The page previously on.  Used to accurately(准确地) represent the
  69.    * referrer header(网址标头).
  70.    */
  71.   protected String referrer = null;
  72.   /**
  73.    * The agent(or browser) that the HTTP class is reporting
  74.    * to the server.
  75.    */
  76.   protected String agent = "Mozilla/4.0";
  77.   /**
  78.    * The user being reported for HTTP authentication(验证).
  79.    */
  80.   protected String user = "";
  81.   /**
  82.    * The password being reported for user authentication.
  83.    */
  84.   protected String password = "";
  85.   /**
  86.    * The max size that a HTTP body can be.
  87.    */
  88.   protected int maxBodySize = -1;
  89.   /**
  90.    * The actual page that was requested, URL may have been redirected
  91.    * elsewhere.
  92.    */
  93.   protected String rootURL;
  94.   protected int err;
  95.   /**
  96.    * The copy method is used to create a new copy of this HTTP handler.
  97.    * This method is implemented abstract and should be implemented by
  98.    * derived classes.
  99.    *
  100.    * @return A new HTTP handler.
  101.    */
  102.   abstract HTTP copy();
  103.   /**
  104.    * This method actually sends the data.  This is where derived
  105.    * classes implement their own low-level(低级别) send.
  106.    *
  107.    * @param url The URL to send data to.
  108.    * @param post Any data that is to be posted.  If no data is posted, this method
  109.    * does an HTTP GET.
  110.    * @exception java.net.UnknownHostException Thrown if the host can not be located.
  111.    * @exception java.io.IOException Thrown if a network error occurs.
  112.    */
  113.   abstract protected void lowLevelSend(String url,String post)
  114.   throws java.net.UnknownHostException, java.io.IOException;
  115.   /**
  116.    * This method is called to clear any cookies that this HTTP
  117.    * object might be holding.
  118.    */
  119.   public void clearCookies()
  120.   {
  121.     cookieStore.clear();
  122.   }
  123.   /**
  124.    * This method is called to add any applicable(实用的) cookies to the
  125.    * header.
  126.    */
  127.   protected void addCookieHeader()
  128.   {
  129.     int i=0;
  130.     String str="";
  131.     if ( cookieStore.get(0)==null )
  132.       return;
  133.     while ( cookieStore.get(i) != null ) {
  134.       CookieParse cookie;
  135.       if ( str.length()!=0 )
  136.         str+="; ";// add on ; if needed
  137.       cookie = (CookieParse)cookieStore.get(i);
  138.       str+=cookie.toString();
  139.       i++;
  140.     }
  141.     clientHeaders.set("Cookie",str);
  142.     Log.log(Log.LOG_LEVEL_TRACE,"Send cookie: " + str );
  143.   }
  144.   /**
  145.    * This method is called to add the user authorization headers
  146.    * to the HTTP request.
  147.    * 增加经过认证的标题。
  148.    */
  149.   protected void addAuthHeader()
  150.   {
  151.     if ( (user.length()==0) || (password.length()==0) )
  152.       return;
  153.     String hdr = user + ":" + password;
  154.     String encode = URLUtility.base64Encode(hdr);
  155.     clientHeaders.set("Authorization","Basic " + encode );
  156.   }
  157.   /**
  158.    * Send is the public interface to this class that actually sends
  159.    * an HTTP request.
  160.    * http类中最有分量的一个方法。
  161.    *
  162.    * @param url The URL being sent to.
  163.    * @param post Any data to post.
  164.    * @exception java.net.UnknownHostException
  165.    * @exception java.io.IOException
  166.    */
  167.   public void send(String requestedURL,String post)
  168.   throws HTTPException,java.net.UnknownHostException,java.io.IOException
  169.   {
  170.     int rtn; // the return value
  171.     if ( post==null )
  172.       Log.log(Log.LOG_LEVEL_NORMAL,"HTTP GET " + requestedURL );
  173.     else
  174.       Log.log(Log.LOG_LEVEL_NORMAL,"HTTP POST " + requestedURL );
  175.     rootURL = requestedURL;
  176.     setURL(requestedURL);
  177.     if ( clientHeaders.get("referrer")==null )
  178.       if ( referrer!=null )
  179.         clientHeaders.set("referrer",referrer.toString());
  180.     if ( clientHeaders.get("Accept")==null )
  181.       clientHeaders.set("Accept","image/gif,"
  182.                         + "image/x-xbitmap,image/jpeg, "
  183.                         + "image/pjpeg, application/vnd.ms-excel,"
  184.                         + "application/msword,"
  185.                         + "application/vnd.ms-powerpoint, */*");
  186.     if ( clientHeaders.get("Accept-Language")==null )
  187.       clientHeaders.set("Accept-Language","en-us");
  188.     if ( clientHeaders.get("User-Agent")==null )
  189.       clientHeaders.set("User-Agent",agent);
  190.     while ( true ) {
  191.       if ( useCookies )
  192.         addCookieHeader();
  193.       addAuthHeader();
  194.       lowLevelSend(this.url,post);
  195.       if ( useCookies )
  196.         parseCookies();
  197.       Attribute encoding = serverHeaders.get("Content-Encoding");
  198.       if ( (encoding!=null) && "gzip".equalsIgnoreCase(encoding.getValue()) )
  199.         processGZIP();
  200.       Attribute a = serverHeaders.get("Location");
  201.       if ( (a==null) || !autoRedirect ) {
  202.         referrer = getURL();
  203.         return;
  204.       }
  205.       URL u = new URL(new URL(url),a.getValue());
  206.       Log.log(Log.LOG_LEVEL_NORMAL,"HTTP REDIRECT to " + u.toString() );
  207.       setURL(u.toString());
  208.     }
  209.   }
  210.   /**
  211.    * This method is called to get the body data that was returned
  212.    * by this request as a string.
  213.    *
  214.    * @return The body data for the last request.
  215.    */
  216.   public String getBody()
  217.   {
  218.     return new String(body);
  219.   }
  220.   /**
  221.    * This method is called to get the body data that was returned
  222.    * by this request as an encoded(编码,加密) string.
  223.    * @param enc How to encode the string.
  224.    * @exception UnsupportedEncodingException
  225.    * @return The body data for the last request.
  226.    */
  227.   public String getBody(String enc)
  228.   throws UnsupportedEncodingException
  229.   {
  230.     return new String(body,enc);
  231.   }
  232.   /**
  233.    * This method is called to get the body data that was returned
  234.    * by this request as a byte-array. This is more efficent than
  235.    * getting the data as a sting, as the data is stored internally
  236.    * as a byte-array.
  237.    *
  238.    * @return The body data for the last request.
  239.    */
  240.   public byte[] getBodyBytes()
  241.   {
  242.     return body;
  243.   }
  244.   /**
  245.    * Get the URL that was ultimately requested. You might get a
  246.    * different URL than was requested if auto redirection is
  247.    * enabled.
  248.    */
  249.   public String getURL()
  250.   {
  251.     return url;
  252.   }
  253.   /**
  254.    * Called to set the internal URL that is kept for the last
  255.    * request.
  256.    *
  257.    * @param u The new URL.
  258.    */
  259.   public void setURL(String u)
  260.   {
  261.     url = u;
  262.   }
  263.   /**
  264.    * Used to determine if the HTTP class should automatically
  265.    * resolve any HTTP redirects.
  266.    *
  267.    * @param b True to resolve redirects, false otherwise.
  268.    */
  269.   public void SetAutoRedirect(boolean b)
  270.   {
  271.     autoRedirect = b;
  272.   }
  273.   /**
  274.    * This method will return an AttributeLIst of client headers.
  275.    *
  276.    * @return An AttributeList of client headers.
  277.    */
  278.   public AttributeList getClientHeaders()
  279.   {
  280.     return clientHeaders;
  281.   }
  282.   /**
  283.    * This method will return an AttributeList of server headers.
  284.    *
  285.    * @return An AttributeList of server headers.
  286.    */
  287.   public AttributeList getServerHeaders()
  288.   {
  289.     return serverHeaders;
  290.   }
  291.   /**
  292.    * This method is called internally to parse any cookies and add
  293.    * them to the cookie store.
  294.    */
  295.   protected void parseCookies()
  296.   {
  297.     Attribute a;
  298.     int i=0;
  299.     while ( (a = serverHeaders.get(i++)) != null ) {
  300.       if ( a.getName().equalsIgnoreCase("set-cookie") ) {
  301.         CookieParse cookie = new CookieParse();
  302.         cookie.source=new StringBuffer(a.getValue());
  303.         cookie.get();
  304.         cookie.setName(cookie.get(0).getName());
  305.         if ( cookieStore.get(cookie.get(0).getName())==null ) {
  306.           if ( (cookie.get("expires")==null) ||
  307.                ( cookie.get("expires")!=null) && usePermCookies )
  308.             cookieStore.add(cookie);
  309.         }
  310.         Log.log(Log.LOG_LEVEL_TRACE,"Got cookie: " + cookie.toString() );
  311.       }
  312.     }
  313.   }
  314.   /**
  315.    * This method is called uncompress a GZIP encoded document.
  316.    */
  317.   protected void processGZIP()
  318.   throws IOException
  319.   {
  320.     ByteArrayInputStream bis = new ByteArrayInputStream(body);
  321.     GZIPInputStream is = new GZIPInputStream(bis);
  322.     StringBuffer newBody = new StringBuffer();
  323.     ByteList byteList = new ByteList();
  324.     byteList.read(is,-1);      
  325.     body = byteList.detach();
  326.   }
  327.   /**
  328.    * This method is used to access a specific cookie.
  329.    *
  330.    * @param name The name of the cookie being sought.
  331.    * @return The cookie being sought, or null.
  332.    */
  333.   public CookieParse getCookie(String name)
  334.   {
  335.     return((CookieParse)cookieStore.get(name));
  336.   }
  337.   /**
  338.    * This method controls the use of cookies by this HTTP object.
  339.    *
  340.    * @param session True to use session cookies, false not to.
  341.    * @param perm True to use permanent cookies, false not to.
  342.    */
  343.   public void setUseCookies(boolean session,boolean perm)
  344.   {
  345.     useCookies = session;
  346.     usePermCookies = perm;
  347.   }
  348.   /**
  349.    * This method allows you to determine if session cookies
  350.    * are being used.
  351.    *
  352.    * @return True if session cookies are being used.
  353.    */
  354.   public boolean getUseCookies()
  355.   {
  356.     return useCookies;
  357.   }
  358.   /**
  359.    * This method allows you to determine if permanent cookies
  360.    * are being used.
  361.    *
  362.    * @return Returns true if permanent cookies are being used, false otherwise.
  363.    */
  364.   public boolean getPerminantCookies()
  365.   {
  366.     return usePermCookies;
  367.   }
  368.   protected void processResponse(String name)
  369.   throws java.io.IOException
  370.   {
  371.     int i1,i2;
  372.     response = name;
  373.     i1 = response.indexOf(' ');
  374.     if ( i1!=-1 ) {
  375.       i2 = response.indexOf(' ',i1+1);
  376.       if ( i2!=-1 ) {
  377.         try {
  378.           err=Integer.parseInt(response.substring(i1+1,i2));
  379.         } catch ( Exception e ) {
  380.         }
  381.       }
  382.     }
  383.     Log.log(Log.LOG_LEVEL_TRACE,"Response: " + name );
  384.   }
  385.   /**
  386.    * This method is called internally to process user headers.
  387.    *
  388.    * @exception java.io.IOException Thrown if a network error occurs.
  389.    */
  390.   protected void parseHeaders()
  391.   throws java.io.IOException
  392.   {
  393.     boolean first;
  394.     String name,value;
  395.     int l;
  396.     first = true;
  397.     serverHeaders.clear();
  398.     name = "";
  399.     String parse = new String(header);
  400.     for ( l=0;l<parse.length();l++ ) {
  401.       if ( parse.charAt(l)=='/n' ) {
  402.         if ( name.length()==0 )
  403.           return;
  404.         else {
  405.           if ( first ) {
  406.             first = false;
  407.             processResponse(name);
  408.           } else {
  409.             int ptr=name.indexOf(':');
  410.             if ( ptr!=-1 ) {
  411.               value = name.substring(ptr+1).trim();
  412.               name = name.substring(0,ptr);
  413.               Attribute a = new Attribute(name,value);
  414.               serverHeaders.add(a);
  415.               Log.log(Log.LOG_LEVEL_TRACE,"Sever Header:" + name + "=" + value);
  416.             }
  417.           }
  418.         }
  419.         name = "";
  420.       } else if ( parse.charAt(l)!='/r' )
  421.         name+=parse.charAt(l);
  422.     }
  423.   }
  424.   /**
  425.    * This method is called to set the amount of time that the
  426.    * HTTP class will wait for the requested resource.
  427.    *
  428.    * @param i The timeout in milliseconds.
  429.    */
  430.   public void setTimeout(int i)
  431.   {
  432.     timeout = i;
  433.   }
  434.   /**
  435.    * This method will return the amount of time in milliseconds
  436.    * that the HTTP object will wait for a timeout.
  437.    */
  438.   public int getTimeout()
  439.   {
  440.     return timeout;
  441.   }
  442.   /**
  443.    * This method will set the maximum body size
  444.    * that will be downloaded.
  445.    *
  446.    * @param i The maximum body size, or -1 for unlimted.
  447.    */
  448.   public void setMaxBody(int i)
  449.   {
  450.     maxBodySize = i;
  451.   }
  452.   /**
  453.    * This method will return the maximum body size
  454.    * that will be downloaded.
  455.    *
  456.    * @return The maximum body size, or -1 for unlimted.
  457.    */
  458.   public int getMaxBody()
  459.   {
  460.     return maxBodySize;
  461.   }
  462.   /**
  463.    * Returns the user agent being reported by this HTTP class.
  464.    * The user agent allows the web server to determine what
  465.    * software the web-browser is using.
  466.    *
  467.    * @return The agent string being presented to web servers.
  468.    */
  469.   public String getAgent()
  470.   {
  471.     return agent;
  472.   }
  473.   /**
  474.    * This method is called to set the agent reported to the browser.
  475.    *
  476.    * @param a The user agent string to be reported to servers.
  477.    */
  478.   public void setAgent(String a)
  479.   {
  480.     agent = a;
  481.   }
  482.   /**
  483.    * This method is called to set the user id for HTTP user
  484.    * authentication.
  485.    *
  486.    * @param u The user id.
  487.    */
  488.   public void setUser(String u)
  489.   {
  490.     user = u;
  491.   }
  492.   /**
  493.    * This method is used to set the user's password for HTTP
  494.    * user authentificaiton.
  495.    *
  496.    * @param p The password.
  497.    */
  498.   public void setPassword(String p)
  499.   {
  500.     password = p;
  501.   }
  502.   /**
  503.    * This method is used to return the user id that is being
  504.    * used for HTTP authentification.
  505.    *
  506.    * @return The user id.
  507.    */
  508.   public String getUser()
  509.   {
  510.     return user;
  511.   }
  512.   /**
  513.    * This method is used to get the password that is being used
  514.    * for user authentication.
  515.    *
  516.    * @return The password.
  517.    */
  518.   public String getPassword()
  519.   {
  520.     return password;
  521.   }
  522.   /**
  523.    * This method is used to get the referrer header
  524.    *
  525.    * @return The referrer header.
  526.    */
  527.   public String getReferrer()
  528.   {
  529.     return referrer;
  530.   }
  531.   /**
  532.    * This method is used to set the referrer header
  533.    *
  534.    * @param p The referrer header.
  535.    */
  536.   public void setReferrer(String p)
  537.   {
  538.     referrer = p;
  539.   }
  540.   /**
  541.    * This method will return an AttributeList of cookies.
  542.    *
  543.    * @return An AttributeList of server headers.
  544.    */
  545.   public AttributeList getCookies()
  546.   {
  547.     return cookieStore;
  548.   }
  549.   /**
  550.    * This method will return the first URL that was requested. This
  551.    * will be different than the current URL when redirection has occured.
  552.    *
  553.    * @return The root URL.
  554.    */
  555.   public String getRootURL()
  556.   {
  557.     return rootURL;
  558.   }
  559.   
  560.   public String getContentType()
  561.   {
  562.       Attribute a = serverHeaders.get("Content-Type");
  563.       if( a==null )
  564.           return null;
  565.       else
  566.           return a.getValue();
  567.   }
  568. }

send方法里面的那个while(true)无限循环,直到所有的重定向都被解析。

那也来说一下重定向吧:

重定向,从实质上看可以分为临时性重定向以及永久性重定向,顾名思义,如果你想让一个地址,永久性地跳转到另一个地址,那么就应该用永久性重定向,反之,如果只是短时间内指向目标地址,就使用临时性重定向。

我们在这里就把重定向看成是链接应该是没有错的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值