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; } }