set_write_stream() 공개 메소드

Sets the resource to write to while streaming down.
public set_write_stream ( resource $resource )
$resource resource (Required) The writeable resource to write to.
예제 #1
0
 /**
  * auth接口
  * @param array $options
  * @return ResponseCore
  * @throws OSS_Exception
  * @throws RequestCore_Exception
  */
 public function auth($options)
 {
     OSSUtil::validate_options($options);
     //验证Bucket,list_bucket时不需要验证
     if (!('/' == $options[self::OSS_OBJECT] && '' == $options[self::OSS_BUCKET] && 'GET' == $options[self::OSS_METHOD]) && !OSSUtil::validate_bucket($options[self::OSS_BUCKET])) {
         throw new OSS_Exception('"' . $options[self::OSS_BUCKET] . '"' . OSS_BUCKET_NAME_INVALID);
     }
     //验证Object
     if (isset($options[self::OSS_OBJECT]) && !OSSUtil::validate_object($options[self::OSS_OBJECT])) {
         throw new OSS_Exception($options[self::OSS_OBJECT] . OSS_OBJECT_NAME_INVALID);
     }
     //Object编码为UTF-8
     $tmp_object = $options[self::OSS_OBJECT];
     try {
         if (OSSUtil::is_gb2312($options[self::OSS_OBJECT])) {
             $options[self::OSS_OBJECT] = iconv('GB2312', "UTF-8//IGNORE", $options[self::OSS_OBJECT]);
         } elseif (OSSUtil::check_char($options[self::OSS_OBJECT], true)) {
             $options[self::OSS_OBJECT] = iconv('GBK', "UTF-8//IGNORE", $options[self::OSS_OBJECT]);
         }
     } catch (Exception $e) {
         try {
             $tmp_object = iconv(mb_detect_encoding($tmp_object), "UTF-8", $tmp_object);
         } catch (Exception $e) {
         }
     }
     $options[self::OSS_OBJECT] = $tmp_object;
     //验证ACL
     if (isset($options[self::OSS_HEADERS][self::OSS_ACL]) && !empty($options[self::OSS_HEADERS][self::OSS_ACL])) {
         if (!in_array(strtolower($options[self::OSS_HEADERS][self::OSS_ACL]), self::$OSS_ACL_TYPES)) {
             throw new OSS_Exception($options[self::OSS_HEADERS][self::OSS_ACL] . ':' . OSS_ACL_INVALID);
         }
     }
     //定义scheme
     $scheme = $this->use_ssl ? 'https://' : 'http://';
     if ($this->enable_domain_style) {
         $hostname = $this->vhost ? $this->vhost : ($options[self::OSS_BUCKET] == '' ? $this->hostname : $options[self::OSS_BUCKET] . '.' . $this->hostname);
     } else {
         $hostname = isset($options[self::OSS_BUCKET]) && '' !== $options[self::OSS_BUCKET] ? $this->hostname . '/' . $options[self::OSS_BUCKET] : $this->hostname;
     }
     //请求参数
     $signable_resource = '';
     $query_string_params = array();
     $signable_query_string_params = array();
     $string_to_sign = '';
     $oss_host = $this->hostname;
     if ($this->enable_domain_style) {
         $oss_host = $hostname;
     }
     $headers = array(self::OSS_CONTENT_MD5 => '', self::OSS_CONTENT_TYPE => isset($options[self::OSS_CONTENT_TYPE]) ? $options[self::OSS_CONTENT_TYPE] : 'application/x-www-form-urlencoded', self::OSS_DATE => isset($options[self::OSS_DATE]) ? $options[self::OSS_DATE] : gmdate('D, d M Y H:i:s \\G\\M\\T'), self::OSS_HOST => $oss_host);
     if (isset($options[self::OSS_CONTENT_MD5])) {
         $headers[self::OSS_CONTENT_MD5] = $options[self::OSS_CONTENT_MD5];
     }
     //增加stsSecurityToken
     if (!is_null($this->security_token) && !$this->enable_sts_in_url) {
         $headers[self::OSS_SECURITY_TOKEN] = $this->security_token;
     }
     if (isset($options[self::OSS_OBJECT]) && '/' !== $options[self::OSS_OBJECT]) {
         $signable_resource = '/' . str_replace(array('%2F', '%25'), array('/', '%'), rawurlencode($options[self::OSS_OBJECT]));
     }
     if (isset($options[self::OSS_QUERY_STRING])) {
         $query_string_params = array_merge($query_string_params, $options[self::OSS_QUERY_STRING]);
     }
     $query_string = OSSUtil::to_query_string($query_string_params);
     $signable_list = array(self::OSS_PART_NUM, self::OSS_UPLOAD_ID);
     foreach ($signable_list as $item) {
         if (isset($options[$item])) {
             $signable_query_string_params[$item] = $options[$item];
         }
     }
     if ($this->enable_sts_in_url && !is_null($this->security_token)) {
         $signable_query_string_params["security-token"] = $this->security_token;
     }
     $signable_query_string = OSSUtil::to_query_string($signable_query_string_params);
     //合并 HTTP headers
     if (isset($options[self::OSS_HEADERS])) {
         $headers = array_merge($headers, $options[self::OSS_HEADERS]);
     }
     //生成请求URL
     $conjunction = '?';
     $non_signable_resource = '';
     if (isset($options[self::OSS_SUB_RESOURCE])) {
         $signable_resource .= $conjunction . $options[self::OSS_SUB_RESOURCE];
         $conjunction = '&';
     }
     if ($signable_query_string !== '') {
         $signable_query_string = $conjunction . $signable_query_string;
         $conjunction = '&';
     }
     if ($query_string !== '') {
         $non_signable_resource .= $conjunction . $query_string;
         $conjunction = '&';
     }
     $this->request_url = $scheme . $hostname . $signable_resource . $signable_query_string . $non_signable_resource;
     //创建请求
     $request = new RequestCore($this->request_url);
     $user_agent = OSS_NAME . "/" . OSS_VERSION . " (" . php_uname('s') . "/" . php_uname('r') . "/" . php_uname('m') . ";" . PHP_VERSION . ")";
     $request->set_useragent($user_agent);
     // Streaming uploads
     if (isset($options[self::OSS_FILE_UPLOAD])) {
         if (is_resource($options[self::OSS_FILE_UPLOAD])) {
             $length = null;
             if (isset($options[self::OSS_CONTENT_LENGTH])) {
                 $length = $options[self::OSS_CONTENT_LENGTH];
             } elseif (isset($options[self::OSS_SEEK_TO])) {
                 $stats = fstat($options[self::OSS_FILE_UPLOAD]);
                 if ($stats && $stats[self::OSS_SIZE] >= 0) {
                     $length = $stats[self::OSS_SIZE] - (int) $options[self::OSS_SEEK_TO];
                 }
             }
             $request->set_read_stream($options[self::OSS_FILE_UPLOAD], $length);
             if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded') {
                 $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
             }
         } else {
             $request->set_read_file($options[self::OSS_FILE_UPLOAD]);
             $length = $request->read_stream_size;
             if (isset($options[self::OSS_CONTENT_LENGTH])) {
                 $length = $options[self::OSS_CONTENT_LENGTH];
             } elseif (isset($options[self::OSS_SEEK_TO]) && isset($length)) {
                 $length -= (int) $options[self::OSS_SEEK_TO];
             }
             $request->set_read_stream_size($length);
             if (isset($headers[self::OSS_CONTENT_TYPE]) && $headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded') {
                 $mime_type = self::get_mime_type($options[self::OSS_FILE_UPLOAD]);
                 $headers[self::OSS_CONTENT_TYPE] = $mime_type;
             }
         }
     }
     if (isset($options[self::OSS_SEEK_TO])) {
         $request->set_seek_position((int) $options[self::OSS_SEEK_TO]);
     }
     if (isset($options[self::OSS_FILE_DOWNLOAD])) {
         if (is_resource($options[self::OSS_FILE_DOWNLOAD])) {
             $request->set_write_stream($options[self::OSS_FILE_DOWNLOAD]);
         } else {
             $request->set_write_file($options[self::OSS_FILE_DOWNLOAD]);
         }
     }
     if (isset($options[self::OSS_METHOD])) {
         $request->set_method($options[self::OSS_METHOD]);
         $string_to_sign .= $options[self::OSS_METHOD] . "\n";
     }
     if (isset($options[self::OSS_CONTENT])) {
         $request->set_body($options[self::OSS_CONTENT]);
         if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded') {
             $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
         }
         $headers[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
         $headers[self::OSS_CONTENT_MD5] = base64_encode(md5($options[self::OSS_CONTENT], true));
     }
     uksort($headers, 'strnatcasecmp');
     foreach ($headers as $header_key => $header_value) {
         $header_value = str_replace(array("\r", "\n"), '', $header_value);
         if ($header_value !== '') {
             $request->add_header($header_key, $header_value);
         }
         if (strtolower($header_key) === 'content-md5' || strtolower($header_key) === 'content-type' || strtolower($header_key) === 'date' || isset($options['self::OSS_PREAUTH']) && (int) $options['self::OSS_PREAUTH'] > 0) {
             $string_to_sign .= $header_value . "\n";
         } elseif (substr(strtolower($header_key), 0, 6) === self::OSS_DEFAULT_PREFIX) {
             $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
         }
     }
     $string_to_sign .= '/' . $options[self::OSS_BUCKET];
     $string_to_sign .= $this->enable_domain_style ? $options[self::OSS_BUCKET] != '' ? $options[self::OSS_OBJECT] == '/' ? '/' : '' : '' : '';
     $string_to_sign .= rawurldecode($signable_resource) . urldecode($signable_query_string);
     $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->access_key, true));
     $request->add_header('Authorization', 'OSS ' . $this->access_id . ':' . $signature);
     if (isset($options[self::OSS_PREAUTH]) && (int) $options[self::OSS_PREAUTH] > 0) {
         $signed_url = $this->request_url . $conjunction . self::OSS_URL_ACCESS_KEY_ID . '=' . rawurlencode($this->access_id) . '&' . self::OSS_URL_EXPIRES . '=' . $options[self::OSS_PREAUTH] . '&' . self::OSS_URL_SIGNATURE . '=' . rawurlencode($signature);
         return $signed_url;
     } elseif (isset($options[self::OSS_PREAUTH])) {
         return $this->request_url;
     }
     if ($this->debug_mode) {
         $request->debug_mode = $this->debug_mode;
     }
     $request->send_request();
     $response_header = $request->get_response_header();
     $response_header['oss-request-url'] = $this->request_url;
     $response_header['oss-redirects'] = $this->redirects;
     $response_header['oss-stringtosign'] = $string_to_sign;
     $response_header['oss-requestheaders'] = $request->request_headers;
     $data = new ResponseCore($response_header, $request->get_response_body(), $request->get_response_code());
     //retry if OSS Internal Error
     if ((int) $request->get_response_code() === 500) {
         if ($this->redirects <= $this->max_retries) {
             //设置休眠
             $delay = (int) (pow(4, $this->redirects) * 100000);
             usleep($delay);
             $this->redirects++;
             $data = $this->auth($options);
         }
     }
     $this->redirects = 0;
     return $data;
 }
예제 #2
0
 /**
  * Authorization
  * @param array $options (Required)
  * @throws OSS_Exception
  * @author xiaobing.meng@alibaba-inc.com
  * @since 2012-05-31
  */
 public function auth($options)
 {
     //开始记录LOG
     $msg = "---LOG START---------------------------------------------------------------------------\n";
     //验证Bucket,list_bucket时不需要验证
     if (!('/' == $options[self::OSS_OBJECT] && '' == $options[self::OSS_BUCKET] && 'GET' == $options[self::OSS_METHOD]) && !$this->validate_bucket($options[self::OSS_BUCKET])) {
         throw new OSS_Exception('"' . $options[self::OSS_BUCKET] . '"' . OSS_BUCKET_NAME_INVALID);
     }
     //验证Object
     if (isset($options[self::OSS_OBJECT]) && !$this->validate_object($options[self::OSS_OBJECT])) {
         throw new OSS_Exception($options[self::OSS_OBJECT] . OSS_OBJECT_NAME_INVALID);
     }
     //Object编码为UTF-8
     if ($this->is_gb2312($options[self::OSS_OBJECT])) {
         $options[self::OSS_OBJECT] = iconv('GB2312', "UTF-8", $options[self::OSS_OBJECT]);
     } elseif ($this->check_char($options[self::OSS_OBJECT], true)) {
         $options[self::OSS_OBJECT] = iconv('GBK', "UTF-8", $options[self::OSS_OBJECT]);
     }
     //验证ACL
     if (isset($options[self::OSS_HEADERS][self::OSS_ACL]) && !empty($options[self::OSS_HEADERS][self::OSS_ACL])) {
         if (!in_array(strtolower($options[self::OSS_HEADERS][self::OSS_ACL]), self::$OSS_ACL_TYPES)) {
             throw new OSS_Exception($options[self::OSS_HEADERS][self::OSS_ACL] . ':' . OSS_ACL_INVALID);
         }
     }
     //定义scheme
     $scheme = $this->use_ssl ? 'https://' : 'http://';
     //匹配bucket
     if (strpos($options[self::OSS_BUCKET], "-") !== false) {
         //bucket 带"-"的时候
         $this->set_enable_domain_style(false);
     } else {
         $this->set_enable_domain_style(true);
     }
     if ($this->enable_domain_style) {
         $hostname = $this->vhost ? $this->vhost : ($options[self::OSS_BUCKET] == '' ? $this->hostname : $options[self::OSS_BUCKET] . '.' . $this->hostname);
     } else {
         $hostname = isset($options[self::OSS_BUCKET]) && '' !== $options[self::OSS_BUCKET] ? $this->hostname . '/' . $options[self::OSS_BUCKET] : $this->hostname;
     }
     //请求参数
     $resource = '';
     $sub_resource = '';
     $signable_resource = '';
     $query_string_params = array();
     $signable_query_string_params = array();
     $string_to_sign = '';
     $headers = array(self::OSS_CONTENT_MD5 => '', self::OSS_CONTENT_TYPE => isset($options[self::OSS_CONTENT_TYPE]) ? $options[self::OSS_CONTENT_TYPE] : 'application/x-www-form-urlencoded', self::OSS_DATE => isset($options[self::OSS_DATE]) ? $options[self::OSS_DATE] : gmdate('D, d M Y H:i:s \\G\\M\\T'), self::OSS_HOST => $this->enable_domain_style ? $hostname : $this->hostname);
     if (isset($options[self::OSS_OBJECT]) && '/' !== $options[self::OSS_OBJECT]) {
         $signable_resource = '/' . str_replace('%2F', '/', rawurlencode($options[self::OSS_OBJECT]));
     }
     if (isset($options[self::OSS_QUERY_STRING])) {
         $query_string_params = array_merge($query_string_params, $options[self::OSS_QUERY_STRING]);
     }
     $query_string = $this->to_query_string($query_string_params);
     $signable_list = array('partNumber', 'uploadId');
     foreach ($signable_list as $item) {
         if (isset($options[$item])) {
             $signable_query_string_params[$item] = $options[$item];
         }
     }
     $signable_query_string = $this->to_query_string($signable_query_string_params);
     //合并 HTTP headers
     if (isset($options[self::OSS_HEADERS])) {
         $headers = array_merge($headers, $options[self::OSS_HEADERS]);
     }
     //生成请求URL
     $conjunction = '?';
     $non_signable_resource = '';
     if (isset($options[self::OSS_SUB_RESOURCE])) {
         $signable_resource .= $conjunction . $options[self::OSS_SUB_RESOURCE];
         $conjunction = '&';
     }
     if ($signable_query_string !== '') {
         $signable_query_string = $conjunction . $signable_query_string;
         $conjunction = '&';
     }
     if ($query_string !== '') {
         $non_signable_resource .= $conjunction . $query_string;
         $conjunction = '&';
     }
     $this->request_url = $scheme . $hostname . $signable_resource . $signable_query_string . $non_signable_resource;
     $msg .= "--REQUEST URL:----------------------------------------------\n" . $this->request_url . "\n";
     //创建请求
     $request = new RequestCore($this->request_url);
     // Streaming uploads
     if (isset($options[self::OSS_FILE_UPLOAD])) {
         if (is_resource($options[self::OSS_FILE_UPLOAD])) {
             $length = null;
             if (isset($options[self::OSS_CONTENT_LENGTH])) {
                 $length = $options[self::OSS_CONTENT_LENGTH];
             } elseif (isset($options[self::OSS_SEEK_TO])) {
                 $stats = fstat($options[self::OSS_FILE_UPLOAD]);
                 if ($stats && $stats[self::OSS_SIZE] >= 0) {
                     $length = $stats[self::OSS_SIZE] - (int) $options[self::OSS_SEEK_TO];
                 }
             }
             $request->set_read_stream($options[self::OSS_FILE_UPLOAD], $length);
             if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded') {
                 $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
             }
         } else {
             $request->set_read_file($options[self::OSS_FILE_UPLOAD]);
             $length = $request->read_stream_size;
             if (isset($options[self::OSS_CONTENT_LENGTH])) {
                 $length = $options[self::OSS_CONTENT_LENGTH];
             } elseif (isset($options[self::OSS_SEEK_TO]) && isset($length)) {
                 $length -= (int) $options[self::OSS_SEEK_TO];
             }
             $request->set_read_stream_size($length);
             if (isset($headers[self::OSS_CONTENT_TYPE]) && $headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded') {
                 $extension = explode('.', $options[self::OSS_FILE_UPLOAD]);
                 $ext = array_pop($extension);
                 $mime_type = MimeTypes::get_mimetype($ext);
                 $headers[self::OSS_CONTENT_TYPE] = $mime_type;
             }
         }
         $options[self::OSS_CONTENT_MD5] = '';
     }
     if (isset($options[self::OSS_SEEK_TO])) {
         $request->set_seek_position((int) $options[self::OSS_SEEK_TO]);
     }
     if (isset($options[self::OSS_FILE_DOWNLOAD])) {
         if (is_resource($options[self::OSS_FILE_DOWNLOAD])) {
             $request->set_write_stream($options[self::OSS_FILE_DOWNLOAD]);
         } else {
             $request->set_write_file($options[self::OSS_FILE_DOWNLOAD]);
         }
     }
     if (isset($options[self::OSS_METHOD])) {
         $request->set_method($options[self::OSS_METHOD]);
         $string_to_sign .= $options[self::OSS_METHOD] . "\n";
     }
     if (isset($options[self::OSS_CONTENT])) {
         $request->set_body($options[self::OSS_CONTENT]);
         if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded') {
             $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
         }
         $headers[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
         $headers[self::OSS_CONTENT_MD5] = $this->hex_to_base64(md5($options[self::OSS_CONTENT]));
     }
     uksort($headers, 'strnatcasecmp');
     foreach ($headers as $header_key => $header_value) {
         $header_value = str_replace(array("\r", "\n"), '', $header_value);
         if ($header_value !== '') {
             $request->add_header($header_key, $header_value);
         }
         if (strtolower($header_key) === 'content-md5' || strtolower($header_key) === 'content-type' || strtolower($header_key) === 'date' || isset($options['self::OSS_PREAUTH']) && (int) $options['self::OSS_PREAUTH'] > 0) {
             $string_to_sign .= $header_value . "\n";
         } elseif (substr(strtolower($header_key), 0, 6) === self::OSS_DEFAULT_PREFIX) {
             $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
         }
     }
     $string_to_sign .= '/' . $options[self::OSS_BUCKET];
     $string_to_sign .= $this->enable_domain_style ? $options[self::OSS_BUCKET] != '' ? $options[self::OSS_OBJECT] == '/' ? '/' : '' : '' : '';
     $string_to_sign .= rawurldecode($signable_resource) . urldecode($signable_query_string);
     $msg .= "STRING TO SIGN:----------------------------------------------\n" . $string_to_sign . "\n";
     $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->access_key, true));
     $request->add_header('Authorization', 'OSS ' . $this->access_id . ':' . $signature);
     if (isset($options[self::OSS_PREAUTH]) && (int) $options[self::OSS_PREAUTH] > 0) {
         return $this->request_url . $conjunction . self::OSS_URL_ACCESS_KEY_ID . '=' . $this->access_id . '&' . self::OSS_URL_EXPIRES . '=' . $options[self::OSS_PREAUTH] . '&' . self::OSS_URL_SIGNATURE . '=' . rawurlencode($signature);
     } elseif (isset($options[self::OSS_PREAUTH])) {
         return $this->request_url;
     }
     if ($this->debug_mode) {
         $request->debug_mode = $this->debug_mode;
     }
     $msg .= "REQUEST HEADERS:----------------------------------------------\n" . serialize($request->request_headers) . "\n";
     $request->send_request();
     $response_header = $request->get_response_header();
     $response_header['x-oss-request-url'] = $this->request_url;
     $response_header['x-oss-redirects'] = $this->redirects;
     $response_header['x-oss-stringtosign'] = $string_to_sign;
     $response_header['x-oss-requestheaders'] = $request->request_headers;
     $msg .= "RESPONSE HEADERS:----------------------------------------------\n" . serialize($response_header) . "\n";
     $data = new ResponseCore($response_header, $request->get_response_body(), $request->get_response_code());
     if ((int) $request->get_response_code() === 400 || (int) $request->get_response_code() === 500 || (int) $request->get_response_code() === 503) {
         if ($this->redirects <= $this->max_retries) {
             //设置休眠
             $delay = (int) (pow(4, $this->redirects) * 100000);
             usleep($delay);
             $this->redirects++;
             $data = $this->auth($options);
         }
     }
     $msg .= "RESPONSE DATA:----------------------------------------------\n" . serialize($data) . "\n";
     $msg .= date('Y-m-d H:i:s') . ":---LOG END---------------------------------------------------------------------------\n";
     //add log
     $this->log($msg);
     $this->redirects = 0;
     return $data;
 }
예제 #3
0
 private function invoke($method, $args = array(), $holder, $location = NULL)
 {
     $api = API::$API[$method];
     if (!$api) {
         throw new Ks3ClientException($method . " Not Found API");
     }
     if (count($args) !== 0) {
         if (count($args) > 1 || !is_array($args[0])) {
             throw new Ks3ClientException("this method only needs one array argument");
         }
         $args = $args[0];
     }
     if (isset($api["redirect"])) {
         $api = API::$API[$api["redirect"]];
     }
     $request = new Ks3Request();
     if (empty($args["Bucket"])) {
         if ($api["needBucket"]) {
             throw new Ks3ClientException($method . " this api need bucket");
         }
     } else {
         $request->bucket = $args["Bucket"];
     }
     $position = "Key";
     //position主要为queryadp接口用的
     if (isset($api["objectPostion"])) {
         $position = $api["objectPostion"];
     }
     if (empty($args[$position])) {
         if ($api["needObject"]) {
             throw new Ks3ClientException($method . " this api need " . $position);
         }
     } else {
         $key = $args[$position];
         $preEncoding = mb_detect_encoding($key, array("ASCII", "UTF-8", "GB2312", "GBK", "BIG5"));
         $holder->msg .= "key encoding " . $preEncoding . "\r\n";
         if (strtolower($preEncoding) != "utf-8") {
             $key = iconv($preEncoding, "UTF-8", $key);
         }
         $request->key = $key;
     }
     $method = $api["method"];
     if ($method == "Method") {
         if (empty($args["Method"])) {
             $request->method = "GET";
         } else {
             $request->method = $args["Method"];
         }
     } else {
         $request->method = $api["method"];
     }
     if (KS3_API_USE_HTTPS) {
         $request->scheme = "https://";
     } else {
         $request->scheme = "http://";
     }
     $request->endpoint = $this->endpoint;
     //add subresource
     if (!empty($api["subResource"])) {
         $request->subResource = $api["subResource"];
     }
     //add query params
     if (isset($api["queryParams"])) {
         foreach ($api["queryParams"] as $key => $value) {
             $required = FALSE;
             if (substr($value, 0, 1) === "!") {
                 $required = TRUE;
                 $value = substr($value, 1);
             }
             $index = explode("->", $value);
             $curIndexArg = $args;
             $add = TRUE;
             $curkey = "";
             foreach ($index as $key1 => $value1) {
                 if (!isset($curIndexArg[$value1]) && $value1 !== "*") {
                     $add = FALSE;
                 } else {
                     $curkey = $value1;
                     //星号表示所有,按照暂时的业务,默认星号后面就没了
                     if ($curkey == "*") {
                         foreach ($curIndexArg as $queryK => $queryV) {
                             if (!is_array($queryV)) {
                                 $request->addQueryParams($queryK, $queryV);
                             }
                         }
                         $add = FALSE;
                         $required = FALSE;
                         break;
                     } else {
                         $curIndexArg = $curIndexArg[$value1];
                     }
                 }
             }
             if (!empty($curIndexArg) && $add) {
                 $request->addQueryParams($curkey, $curIndexArg);
                 continue;
             }
             if ($required) {
                 throw new Ks3ClientException($method . " param " . $value . " is required");
             }
         }
     }
     if (isset($api["body"])) {
         if (isset($api["body"]["builder"])) {
             $builderName = $api["body"]["builder"];
             $builder = new $builderName();
             $request->body = $builder->build($args);
         } else {
             if (isset($api["body"]["position"])) {
                 $position = $api["body"]["position"];
                 $index = explode("->", $position);
                 $curIndexArg = $args;
                 $add = TRUE;
                 $curkey = "";
                 foreach ($index as $key1 => $value1) {
                     if (!isset($curIndexArg[$value1])) {
                         $add = FALSE;
                     } else {
                         $curIndexArg = $curIndexArg[$value1];
                         $curkey = $value1;
                     }
                 }
                 if (!empty($curIndexArg) && $add) {
                     $request->body = $curIndexArg;
                 }
             }
         }
     }
     //add ext headers
     //TODO
     //sign request
     $signer = NULL;
     if (isset($api["signer"])) {
         $signers = explode("->", $api["signer"]);
         foreach ($signers as $key => $value) {
             $signer = new $value();
             $log = $signer->sign($request, array("accessKey" => $this->accessKey, "secretKey" => $this->secretKey, "args" => $args));
             if (!empty($log)) {
                 $holder->msg .= $log . "\r\n";
             }
         }
     }
     if ($signer === NULL || !$signer instanceof QueryAuthSigner) {
         $url = $request->toUrl($this->endpoint);
         if ($location != NULL) {
             $url = $location;
         }
         $httpRequest = new RequestCore($url);
         if (KS3_API_DEBUG_MODE === TRUE) {
             $httpRequest->debug_mode = TRUE;
         }
         $httpRequest->set_method($request->method);
         foreach ($request->headers as $key => $value) {
             $httpRequest->add_header($key, $value);
         }
         $httpRequest->request_body = $request->body;
         if (isset($args["writeCallBack"])) {
             $httpRequest->register_streaming_write_callback($args["writeCallBack"]);
         }
         if (isset($args["readCallBack"])) {
             $httpRequest->register_streaming_read_callback($args["readCallBack"]);
         }
         $read_stream = $request->read_stream;
         $read_length = $request->getHeader(Headers::$ContentLength);
         $seek_position = $request->seek_position;
         if (isset($read_stream)) {
             $httpRequest->set_read_stream($read_stream, $read_length);
             $httpRequest->set_seek_position($seek_position);
             $httpRequest->remove_header(Headers::$ContentLength);
         }
         $write_stream = $request->write_stream;
         if (isset($write_stream)) {
             $httpRequest->set_write_stream($write_stream);
         }
         $holder->msg .= "request url->" . serialize($httpRequest->request_url) . "\r\n";
         $holder->msg .= "request headers->" . serialize($httpRequest->request_headers) . "\r\n";
         $holder->msg .= "request body->" . $httpRequest->request_body . "\r\n";
         $holder->msg .= "request read stream length->" . $read_length . "\r\n";
         $holder->msg .= "request read stream seek position->" . $seek_position . "\r\n";
         $httpRequest->send_request();
         //print_r($httpRequest);
         $body = $httpRequest->get_response_body();
         $data = new ResponseCore($httpRequest->get_response_header(), Utils::replaceNS2($body), $httpRequest->get_response_code());
         if ($data->status == 307) {
             $respHeaders = $httpRequest->get_response_header();
             $location = $respHeaders["location"];
             if (substr($location, 0, 4) == "http") {
                 $holder->msg .= "response code->" . $httpRequest->get_response_code() . "\r\n";
                 $holder->msg .= "response headers->" . serialize($httpRequest->get_response_header()) . "\r\n";
                 $holder->msg .= "response body->" . $body . "\r\n";
                 $holder->msg .= "retry request to " . $location . "\r\n";
                 //array($args)详见invoke开头
                 return $this->invoke($method, array($args), $holder, $location);
             }
         }
         $holder->msg .= "response code->" . $httpRequest->get_response_code() . "\r\n";
         $holder->msg .= "response headers->" . serialize($httpRequest->get_response_header()) . "\r\n";
         $holder->msg .= "response body->" . $body . "\r\n";
         $handlers = explode("->", $api["handler"]);
         foreach ($handlers as $key => $value) {
             $handler = new $value();
             $data = $handler->handle($data);
         }
         return $data;
     } else {
         $url = $request->toUrl($this->endpoint);
         $holder->msg .= $url . "\r\n";
         return $url;
     }
 }