http.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <?php
  2. require_once("auth_digest.php");
  3. // --------------------------------------------------------------------------------
  4. // class Qiniu_Error
  5. class Qiniu_Error
  6. {
  7. public $Err; // string
  8. public $Reqid; // string
  9. public $Details; // []string
  10. public $Code; // int
  11. public function __construct($code, $err)
  12. {
  13. $this->Code = $code;
  14. $this->Err = $err;
  15. }
  16. }
  17. // --------------------------------------------------------------------------------
  18. // class Qiniu_Request
  19. class Qiniu_Request
  20. {
  21. public $URL;
  22. public $Header;
  23. public $Body;
  24. public function __construct($url, $body)
  25. {
  26. $this->URL = $url;
  27. $this->Header = array();
  28. $this->Body = $body;
  29. }
  30. }
  31. // --------------------------------------------------------------------------------
  32. // class Qiniu_Response
  33. class Qiniu_Response
  34. {
  35. public $StatusCode;
  36. public $Header;
  37. public $ContentLength;
  38. public $Body;
  39. public function __construct($code, $body)
  40. {
  41. $this->StatusCode = $code;
  42. $this->Header = array();
  43. $this->Body = $body;
  44. $this->ContentLength = strlen($body);
  45. }
  46. }
  47. // --------------------------------------------------------------------------------
  48. // class Qiniu_Header
  49. function Qiniu_Header_Get($header, $key) // => $val
  50. {
  51. $val = @$header[$key];
  52. if (isset($val)) {
  53. if (is_array($val)) {
  54. return $val[0];
  55. }
  56. return $val;
  57. } else {
  58. return '';
  59. }
  60. }
  61. function Qiniu_ResponseError($resp) // => $error
  62. {
  63. $header = $resp->Header;
  64. $details = Qiniu_Header_Get($header, 'X-Log');
  65. $reqId = Qiniu_Header_Get($header, 'X-Reqid');
  66. $err = new Qiniu_Error($resp->StatusCode, null);
  67. if ($err->Code > 299) {
  68. if ($resp->ContentLength !== 0) {
  69. if (Qiniu_Header_Get($header, 'Content-Type') === 'application/json') {
  70. $ret = json_decode($resp->Body, true);
  71. $err->Err = $ret['error'];
  72. }
  73. }
  74. }
  75. return $err;
  76. }
  77. // --------------------------------------------------------------------------------
  78. // class Qiniu_Client
  79. function Qiniu_Client_incBody($req) // => $incbody
  80. {
  81. $body = $req->Body;
  82. if (!isset($body)) {
  83. return false;
  84. }
  85. $ct = Qiniu_Header_Get($req->Header, 'Content-Type');
  86. if ($ct === 'application/x-www-form-urlencoded') {
  87. return true;
  88. }
  89. return false;
  90. }
  91. function Qiniu_Client_do($req) // => ($resp, $error)
  92. {
  93. $ch = curl_init();
  94. $url = $req->URL;
  95. $options = array(
  96. CURLOPT_RETURNTRANSFER => true,
  97. CURLOPT_SSL_VERIFYPEER => false,
  98. CURLOPT_SSL_VERIFYHOST => false,
  99. CURLOPT_CUSTOMREQUEST => 'POST',
  100. CURLOPT_URL => $url['path']
  101. );
  102. $httpHeader = $req->Header;
  103. if (!empty($httpHeader))
  104. {
  105. $header = array();
  106. foreach($httpHeader as $key => $parsedUrlValue) {
  107. $header[] = "$key: $parsedUrlValue";
  108. }
  109. $options[CURLOPT_HTTPHEADER] = $header;
  110. }
  111. $body = $req->Body;
  112. if (!empty($body)) {
  113. $options[CURLOPT_POSTFIELDS] = $body;
  114. }
  115. curl_setopt_array($ch, $options);
  116. $result = curl_exec($ch);
  117. $ret = curl_errno($ch);
  118. if ($ret !== 0) {
  119. $err = new Qiniu_Error(0, curl_error($ch));
  120. curl_close($ch);
  121. return array(null, $err);
  122. }
  123. $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  124. $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
  125. curl_close($ch);
  126. $resp = new Qiniu_Response($code, $result);
  127. $resp->Header['Content-Type'] = $contentType;
  128. return array($resp, null);
  129. }
  130. class Qiniu_HttpClient
  131. {
  132. public function RoundTrip($req) // => ($resp, $error)
  133. {
  134. return Qiniu_Client_do($req);
  135. }
  136. }
  137. class Qiniu_MacHttpClient
  138. {
  139. public $Mac;
  140. public function __construct($mac)
  141. {
  142. $this->Mac = Qiniu_RequireMac($mac);
  143. }
  144. public function RoundTrip($req) // => ($resp, $error)
  145. {
  146. $incbody = Qiniu_Client_incBody($req);
  147. $token = $this->Mac->SignRequest($req, $incbody);
  148. $req->Header['Authorization'] = "QBox $token";
  149. return Qiniu_Client_do($req);
  150. }
  151. }
  152. // --------------------------------------------------------------------------------
  153. function Qiniu_Client_ret($resp) // => ($data, $error)
  154. {
  155. $code = $resp->StatusCode;
  156. $data = null;
  157. if ($code >= 200 && $code <= 299) {
  158. if ($resp->ContentLength !== 0) {
  159. $data = json_decode($resp->Body, true);
  160. if ($data === null) {
  161. $err_msg = function_exists('json_last_error_msg') ? json_last_error_msg() : "error with content:" . $resp->Body;
  162. $err = new Qiniu_Error(0, $err_msg);
  163. return array(null, $err);
  164. }
  165. }
  166. if ($code === 200) {
  167. return array($data, null);
  168. }
  169. }
  170. return array($data, Qiniu_ResponseError($resp));
  171. }
  172. function Qiniu_Client_Call($self, $url) // => ($data, $error)
  173. {
  174. $u = array('path' => $url);
  175. $req = new Qiniu_Request($u, null);
  176. list($resp, $err) = $self->RoundTrip($req);
  177. if ($err !== null) {
  178. return array(null, $err);
  179. }
  180. return Qiniu_Client_ret($resp);
  181. }
  182. function Qiniu_Client_CallNoRet($self, $url) // => $error
  183. {
  184. $u = array('path' => $url);
  185. $req = new Qiniu_Request($u, null);
  186. list($resp, $err) = $self->RoundTrip($req);
  187. if ($err !== null) {
  188. return array(null, $err);
  189. }
  190. if ($resp->StatusCode === 200) {
  191. return null;
  192. }
  193. return Qiniu_ResponseError($resp);
  194. }
  195. function Qiniu_Client_CallWithForm(
  196. $self, $url, $params, $contentType = 'application/x-www-form-urlencoded') // => ($data, $error)
  197. {
  198. $u = array('path' => $url);
  199. if ($contentType === 'application/x-www-form-urlencoded') {
  200. if (is_array($params)) {
  201. $params = http_build_query($params);
  202. }
  203. }
  204. $req = new Qiniu_Request($u, $params);
  205. if ($contentType !== 'multipart/form-data') {
  206. $req->Header['Content-Type'] = $contentType;
  207. }
  208. list($resp, $err) = $self->RoundTrip($req);
  209. if ($err !== null) {
  210. return array(null, $err);
  211. }
  212. return Qiniu_Client_ret($resp);
  213. }
  214. // --------------------------------------------------------------------------------
  215. function Qiniu_Client_CallWithMultipartForm($self, $url, $fields, $files)
  216. {
  217. list($contentType, $body) = Qiniu_Build_MultipartForm($fields, $files);
  218. return Qiniu_Client_CallWithForm($self, $url, $body, $contentType);
  219. }
  220. function Qiniu_Build_MultipartForm($fields, $files) // => ($contentType, $body)
  221. {
  222. $data = array();
  223. $mimeBoundary = md5(microtime());
  224. foreach ($fields as $name => $val) {
  225. array_push($data, '--' . $mimeBoundary);
  226. array_push($data, "Content-Disposition: form-data; name=\"$name\"");
  227. array_push($data, '');
  228. array_push($data, $val);
  229. }
  230. foreach ($files as $file) {
  231. array_push($data, '--' . $mimeBoundary);
  232. list($name, $fileName, $fileBody) = $file;
  233. $fileName = Qiniu_escapeQuotes($fileName);
  234. array_push($data, "Content-Disposition: form-data; name=\"$name\"; filename=\"$fileName\"");
  235. array_push($data, 'Content-Type: application/octet-stream');
  236. array_push($data, '');
  237. array_push($data, $fileBody);
  238. }
  239. array_push($data, '--' . $mimeBoundary . '--');
  240. array_push($data, '');
  241. $body = implode("\r\n", $data);
  242. $contentType = 'multipart/form-data; boundary=' . $mimeBoundary;
  243. return array($contentType, $body);
  244. }
  245. function Qiniu_escapeQuotes($str)
  246. {
  247. $find = array("\\", "\"");
  248. $replace = array("\\\\", "\\\"");
  249. return str_replace($find, $replace, $str);
  250. }
  251. // --------------------------------------------------------------------------------