php+socket模拟表单发送请求
1 <?php 2 /** 3 * http请求类(php + socket) 4 * @todo 这里还有很多未完善的地方,仅有简单的get post head请求 5 * @author chuangrain@gmail.com 6 * @version 1.0.0 7 */ 8 9 class HttpClient { 10 11 const CRLF = "\r\n"; 12 private $fh = null; //socket handle 13 private $errno = -1; //socket open error no 14 private $errstr = ''; //socket open error message 15 private $timeout = 30; //socket open timeout 16 private $line = array(); //request line 17 private $header = array();//request header 18 private $body = array(); //request body 19 private $url = array(); //request url 20 private $response = ''; //response 21 private $version = '1.1'; //http version 22 23 public function __construct() { 24 25 } 26 27 /** 28 * 发送HTTP get请求 29 * @access public 30 * @param string $url 请求的url 31 */ 32 public function get($url = '') { 33 $this->setUrl($url); 34 $this->setLine(); 35 $this->setHeader(); 36 $this->request(); 37 return $this->response; 38 } 39 40 /** 41 * 发送HTTP post请求 42 * @access public 43 */ 44 public function post() { 45 $this->setLine('POST'); 46 $this->request(); 47 return $this->response; 48 } 49 50 /** 51 * HTTP -> HEAD 方法,取得服务器响应一个 HTTP 请求所发送的所有标头 52 * @access public 53 * @param string $url 请求的url 54 * @param int $fmt 数据返回形式,关联数组与普通数组 55 * @return array 返回响应头信息 56 */ 57 public function head($url = '', $fmt = 0) { 58 $headers = null; 59 if (is_string($url)) { 60 $headers = get_headers($url, $fmt); 61 } 62 return $headers; 63 } 64 65 /** 66 * 设置要请求的 url 67 * @todo 这里未做url验证 68 * @access public 69 * @param string $url request url 70 * @return bool 71 */ 72 public function setUrl($url = '') { 73 if (is_string($url)) { 74 $this->url = parse_url($url); 75 if (!isset($this->url['port'])) {//设置端口 76 $this->url['port'] = 80; 77 } 78 } else { 79 return false; 80 } 81 } 82 83 /** 84 * 设置HTTP协议的版本 85 * @access public 86 * @param string $version HTTP版本,default value = 1.1 87 * @return bool 如果不在范围内返回false 88 */ 89 public function setVersion($version = "1.1") { 90 if ($version == '1.1' || $version == '1.0' || $version == '0.9') { 91 $this->version = $version; 92 } else { 93 return false; 94 } 95 } 96 97 /** 98 * 设置HTTP请求行 99 * @access public 100 * @param string $method 请求方式 default value = GET 101 */ 102 private function setLine($method = "GET") { 103 //请求空:Method URI HttpVersion 104 if (isset($this->url['query'])) { 105 $this->line[0] = $method . " " . $this->url['path'] . "?" . $this->url['query'] . " HTTP/" . $this->version; 106 } else { 107 $this->line[0] = $method . " " . $this->url['path'] . " HTTP/" . $this->version; 108 } 109 } 110 111 /** 112 * 设置HTTP请求头信息 113 * @access public 114 * @param array $header 请求头信息 115 */ 116 public function setHeader($header = null) { 117 $this->header[0] = "Host: " . $this->url['host']; 118 if (is_array($header)) { 119 foreach($header as $k => $v) { 120 $this->setHeaderKeyValue($k, $v); 121 } 122 } 123 } 124 125 /** 126 * HTTP请求主体 127 * @access public 128 * @param array $body 请求主体 129 */ 130 public function setBody($body = null) { 131 if (is_array($body)) { 132 foreach ($body as $k => $v) { 133 $this->setBodyKeyValue($k, $v); 134 } 135 } 136 } 137 138 /** 139 * 单条设置HTTP请求主体 140 * @access public 141 * @param string $key 请求主体的键 142 * @param string $value 请求主体的值 143 */ 144 public function setBodyKeyValue($key, $value) { 145 if (is_string($key)) { 146 $this->body[] = $key . "=" . $value; 147 } 148 } 149 150 /** 151 * 单条设置HTTP请求头信息 152 * @access public 153 * @param string $key 请求头信息的键 154 * @param string $value 请求头信息的键 155 */ 156 public function setHeaderKeyValue($key, $value) { 157 if (is_string($key)) { 158 $this->header[] = $key . ": " . $value; 159 } 160 } 161 162 /** 163 * socket连接host, 发送请求 164 * @access private 165 */ 166 private function request() { 167 //构造http请求 168 if (!empty($this->body)) { 169 $bodyStr = implode("&", $this->body); 170 $this->setHeaderKeyValue("Content-Length", strlen($bodyStr)); 171 $this->body[] = $bodyStr; 172 $req = array_merge($this->line, $this->header, array(""), array($bodyStr), array("")); 173 } else { 174 $req = array_merge($this->line, $this->header, array(""), $this->body, array("")); 175 } 176 $req = implode(self::CRLF, $req); 177 178 //socket连接host 179 $this->fh = fsockopen($this->url['host'], $this->url['port'], $this->errno, $this->errstr, $this->timeout); 180 181 if (!$this->fh) { 182 echo "socket connect fail!"; 183 return false; 184 } 185 186 //写请求 187 fwrite($this->fh, $req); 188 189 //读响应 190 while (!feof($this->fh)) { 191 $this->response .= fread($this->fh, 1024); 192 } 193 } 194 195 /** 196 * 关闭socket连接 197 * @access public 198 */ 199 public function __destruct() { 200 if ($this->fh) { 201 fclose($this->fh); 202 } 203 } 204 205 } 206 207 208 $url = "http://localhost/xdebug/post_test.php"; 209 210 /** get test **/ 211 $http1 = new HttpClient(); 212 var_dump($http1->get($url)); 213 214 /** post test **/ 215 $http2 = new HttpClient(); 216 $header = array( 217 "Content-Type" => "application/x-www-form-urlencoded" 218 ); 219 $body = array( 220 "username" => "1234", 221 "submit" => "Login" 222 ); 223 $http2->setUrl($url); 224 $http2->setHeader($header); 225 $http2->setBody($body); 226 var_dump($http2->post()); 227 228 /** head test **/ 229 $http3 = new HttpClient(); 230 var_dump($http3->head($url, 1)); 231 post_test.php code list 232 [php] view plaincopyprint? 233 <?php 234 235 var_dump($_POST); 236 237 ?> 238 239 <!DOCTYPE html> 240 <html> 241 <head> 242 <title>post request test</title> 243 </head> 244 <body> 245 <form action="" method="post"> 246 <input type="text" name="username"> 247 <input type="submit" name="submit" value="Login"> 248 </form> 249 </body> 250 </html>
you are the best!