| <? Php /* * Filename: httpclient. php * Created on 2012-12-21 * Created by RobinTang * To change the template for this generated file go * Window-Preferences-PHPeclipse-PHP-Code Templates */ Class SinCookie { Public $ name; // Cookie name Public $ value; // Cookie value // The following three attributes are not implemented now Public $ expires; // expiration time Public $ path; // path Public $ domain; // domain // Create a Cookie object from the Cookie string Function _ construct ($ s = false ){ If ($ s ){ $ I1 = strpos ($ s, '= '); $ I2 = strpos ($ s ,';'); $ This-> name = trim (substr ($ s, 0, $ i1 )); $ This-> value = trim (substr ($ s, $ i1 + 1, $ i2-$ i1-1 )); } } // Obtain the Cookie key-Value Pair Function getKeyValue (){ Return "$ this-> name = $ this-> value "; } } // Session Context Class SinHttpContext { Public $ cookies; // session Cookies Public $ referer; // address of the previous page Function _ construct (){ $ This-> cookies = array (); $ This-> refrer = ""; } // Set Cookie Function cookie ($ key, $ val ){ $ Ck = new SinCookie (); $ Ck-> name = $ key; $ Ck-> value = $ val; $ This-> addCookie ($ ck ); } // Add Cookie Function addCookie ($ ck ){ $ This-> cookies [$ ck-> name] = $ ck; } // Obtain the cookie string, which is used in the request Function cookiesString (){ $ Res = ''; Foreach ($ this-> cookies as $ ck ){ $ Res. = $ ck-> getKeyValue ().';'; } Return $ res; } } // Http request object Class SinHttpRequest { Public $ url; // request address Public $ method = 'get'; // Request method Public $ host; // host Public $ path; // path Public $ scheme; // protocol, http Public $ port; // port Public $ header; // Request header Public $ body; // Request body // Set the header Function setHeader ($ k, $ v ){ If (! Isset ($ this-> header )){ $ This-> header = array (); } $ This-> header [$ k] = $ v; } // Obtain the request string // Contains the header and request body // Write the socket directly after obtaining it. Function reqString (){ $ Matches = parse_url ($ this-> url ); ! Isset ($ matches ['host']) & $ matches ['host'] = ''; ! Isset ($ matches ['path']) & $ matches ['path'] = ''; ! Isset ($ matches ['query']) & $ matches ['query'] = ''; ! Isset ($ matches ['Port']) & $ matches ['Port'] = ''; $ Host = $ matches ['host']; $ Path = $ matches ['path']? $ Matches ['path']. ($ matches ['query']? '? '. $ Matches ['query']: ''):'/'; $ Port =! Empty ($ matches ['Port'])? $ Matches ['Port']: 80; $ Scheme = $ matches ['scheme ']? $ Matches ['scheme ']: 'http '; $ This-> host = $ host; $ This-> path = $ path; $ This-> scheme = $ scheme; $ This-> port = $ port; $ Method = strtoupper ($ this-> method ); $ Res = "$ method $ path HTTP/1.1 \ r \ n "; $ Res. = "Host: $ host \ r \ n "; If ($ this-> header ){ Reset ($ this-> header ); While (list ($ k, $ v) = each ($ this-> header )){ If (isset ($ v) & strlen ($ v)> 0) $ Res. = "$ k: $ v \ r \ n "; } } $ Res. = "\ r \ n "; If ($ this-> body ){ $ Res. = $ this-> body; $ Res. = "\ r \ n "; } Return $ res; } } // Http Response Class SinHttpResponse { Public $ scheme; // Protocol Public $ stasus; // status. It is OK when the request is successful. Public $ code; // status code. The value is 200 when the request is successful. Public $ header; // Response header Public $ body; // response body Function _ construct (){ $ This-> header = array (); $ This-> body = null; } Function setHeader ($ key, $ val ){ $ This-> header [$ key] = $ val; } } // HttpClient Class SinHttpClient { Public $ keepcontext = true; // whether to maintain the session Public $ context; // context Public $ request; // request Public $ response; // response Public $ debug = false; // Whether it is in Debug mode, // If it is true, the request content and the same header are printed. Function _ construct (){ $ This-> request = new SinHttpRequest (); $ This-> response = new SinHttpResponse (); $ This-> context = new SinHttpContext (); $ This-> timeout = 15; // The default timeout value is 15 s. } // Clear the last request content Function clearRequest (){ $ This-> request-> body = ''; $ This-> request-> setHeader ('content-length', false ); $ This-> request-> setHeader ('content-type', false ); } // Post method // Data is the requested data // Simulate form submission when it is a key-Value Pair // Submit data at other times in the form of xml // If you have other requirements, expand them by yourself Function post ($ url, $ data = false ){ $ This-> clearRequest (); If ($ data ){ If (is_array ($ data )){ $ Con = http_build_query ($ data ); $ This-> request-> setHeader ('content-type', 'application/x-www-form-urlencoded '); } Else { $ Con = $ data; $ This-> request-> setHeader ('content-type', 'text/xml; charset = UTF-8 '); } $ This-> request-> body = $ con; $ This-> request-> method = "POST "; $ This-> request-> setHeader ('content-length', strlen ($ con )); } $ This-> startRequest ($ url ); } // Get Method Function get ($ url ){ $ This-> clearRequest (); $ This-> request-> method = "GET "; $ This-> startRequest ($ url ); } // This method is an internal call method and does not need to be called directly. Function startRequest ($ url ){ $ This-> request-> url = $ url; If ($ this-> keepcontext ){ // Set relevant information if the context is saved $ This-> request-> setHeader ('Referer', $ this-> context-> refrer ); $ Cks = $ this-> context-> cookiesString (); If (strlen ($ cks)> 0) $ This-> request-> setHeader ('cooker', $ cks ); } // Obtain the request content $ Reqstring = $ this-> request-> reqString (); If ($ this-> debug) Echo "Request: \ n $ reqstring \ n "; Try { $ Fp = fsockopen ($ this-> request-> host, $ this-> request-> port, $ errno, $ errstr, $ this-> timeout ); } Catch (Exception $ ex ){ Echo $ ex-> getMessage (); Exit (0 ); } If ($ fp ){ Stream_set_blocking ($ fp, true ); Stream_set_timeout ($ fp, $ this-> timeout ); // Write data Fwrite ($ fp, $ reqstring ); $ Status = stream_get_meta_data ($ fp ); If (! $ Status ['timed _ out']) {// No timeout // The following loop is used to read the response header. While (! Feof ($ fp )){ $ H = fgets ($ fp ); If ($ this-> debug) Echo $ h; If ($ h & ($ h = "\ r \ n" | $ h = "\ n ")) Break; $ Pos = strpos ($ h ,':'); If ($ pos ){ $ K = strtolower (trim (substr ($ h, 0, $ pos ))); $ V = trim (substr ($ h, $ pos + 1 )); If ($ k = 'set-cookies '){ // Update Cookie If ($ this-> keepcontext ){ $ This-> context-> addCookie (new SinCookie ($ v )); } } Else { // Add to the header $ This-> response-> setHeader ($ k, $ v ); } } Else { // The first row of data // Parse the response status $ Preg = '/^ (\ S *) (. *) $ /'; Preg_match_all ($ preg, $ h, $ arr ); Isset ($ arr [1] [0]) & $ this-> response-> scheme = trim ($ arr [1] [0]); Isset ($ arr [2] [0]) & $ this-> response-> stasus = trim ($ arr [2] [0]); Isset ($ arr [3] [0]) & $ this-> response-> code = trim ($ arr [3] [0]); } } // Obtain the response body length $ Len = (int) $ this-> response-> header ['content-length']; $ Res = ''; // Read the body cyclically below While (! Feof ($ fp) & $ len> 0 ){ $ C = fread ($ fp, $ len ); $ Res. = $ c; $ Len-= strlen ($ c ); } $ This-> response-> body = $ res; } // Close the Socket Fclose ($ fp ); // Save the returned result to context Maintenance $ This-> context-> refrer = $ url; } } } // Demo // Now let begin test it $ Client = new SinHttpClient (); // create a client $ Client-> get ('HTTP: // www.baidu.com/'); // get Echo $ client-> response-> body; // echo ?> |