Yii Framework Forum: 关于400 Bad Request的问题 - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

关于400 Bad Request的问题 API request Rate Topic: -----

#1 User is offline   winson kong 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 13
  • Joined: 25-October 10

Posted 08 January 2013 - 12:47 PM

你们好,小弟这里有个问题想请教。
我的网页现在需要链接mobile API,他们只是需要我的网页回复他们的XML data,

例如
1. User Sign Up (function = signUP)
Submit($_POST): first name, last name, password, email address, gender, date of birth,function=""
Return(XML Format): Sign Up status (successful with user ID, failed, or email taken, etc)

2. User Sign In (function = signIn)
Submit($_POST): email, password
Return(XML Format): Sign In status (successful with user ID or failed)

小弟本身没有XML的经验,所以接开发了XML(controllers/model/CRUD)
然后就在xml/index等候他们的$_POST 请求

Quote

if(isset($_POST['function']))
{
$function = $_POST['function'];

switch ($function) {
case "signUp":
$first_name = $_POST['first_name'];
$last_name = $_POST['last_name'];
$email = $_POST['email'];
$gender = $_POST['gender'];
$password = $_POST['password'];
$attr=array(
'first_name'=>$first_name,
'last_name'=>$last_name,
'email'=>$email,
'gender'=>$gender,
'password'=>$password);
echo Xml::model()->signUp($attr);
break;
.
.
.

我本身也测试了自己的$_POST

Quote

<form action="/pointcow/index.php?r=xmlRequest/index" method="post">
<input type="text" name="first_name" value="name">
<input type="text" name="last_name" value="last name">
<input type="text" name="email" value="name@email.com">
<input type="text" name="gender" value="male">
<input type="text" name="password" value="123456">
<input type="text" name="verifypassword" value="123456">
<input type="text" name="function" value="signUp">
</form>


然后server回复如下;

Quote

<div id="content">
<!--?xml version="1.0"?-->
<xmlreturn type="documentary">
<return>
<signup_status>success</signup_status>
<user_id>45</user_id>
</return>
</xmlreturn>
</div>

我问了mobile的开发员这样的格式是否正确,他们也说可以。
问题当他们正真测试的时候,他们回复说:
400 bad request,
Posted Image

是否需要config urlmanager?
0

#2 User is offline   yiqing95 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 587
  • Joined: 27-December 10
  • Location:china

Posted 08 January 2013 - 01:25 PM

顶起先 :lol:

没这方面经验 所以期待 其他人解答了 ;

不过 从以往资料来看 手机连接到你网站应该到一个唯一route上
比如 api/xml api/json api/html 控制器的actionXxx 处理不同格式的数据。 这些都应该是唯一访问点 你不要搞出多种来 比如 user/login user/signup 等..

然后 这些action中都只是 监听而已 需要架设server(RPC server) 比如:
class ApiController extends CController
{

    public function actionRpc(){
      //  die(__METHOD__);
        Yii::log("enter ". __METHOD__, CLogger::LEVEL_INFO);
        Yii::import('application.vendors.json_rpc.jsonRPCServer');

        $serviceProxy = YsService::instance();

        jsonRPCServer::handle($serviceProxy)
            or print 'no request';
        Yii::log("end ". __METHOD__, CLogger::LEVEL_INFO);
        die();
    }


} 

然后然后 有中心service来处理不同的请求 rpc 远程过程调用会跟本地类似的 这里需要一个映射表

格式如: apiName => apiServiceImplementCallable

键值应该是 api的外部调用的名字 比如 user_login user_signUP .. 全部是字符串 但你要做某些前缀用来区分模块 防止 以后出现名字冲突 。
值 部分 绑定的是 php callable (你自己查 常见的 有 方法名, 类名::静态方法名 array($obj,'methodName')) 所以你要考虑如何将外部apiName 映射到本机上的函数 静态方法名 或者 对象的方法上 。 你搜索下 php RPC 应该可以找到相关库 很多的。

你最好 在提供一个service层 底层调用相应的Ar的功能; 比如 UserService 调用User 类来完成相关的业务方法 比如 siginIn 等对外暴露的服务方法。 但注意返回值 不能是ar了 转换成数组先 然后有好多库 可以辅助将 数组转换为xml或者json 格式 。难点在 复杂类型处理上 比如引用 关系型($photo->user )可能需要递归转换 .. 还有考虑 分页问题 反正要考虑的太多了 。

我没这方面经验 所以只是我的想法而已 仅供参考。 下面给出我的 YsService 类的实现:
class YsService extends CApplicationComponent
{

    /**
     * @static
     * @return YsService
     */
    public static function instance()
    {
        if (!isset(Yii::app()->service)) {

            Yii::app()->setComponents(array(
                'service' => array(
                    'class' => __CLASS__,
                   // 'mode' => self::MODE_LOCAL,
                ),
            ), false);
        }
        return Yii::app()->service;
    }

    const MODE_JSON_RPC = 'json_rpc';
    const MODE_XML_RPC = 'xml_rpc';
    /**
     * @see http://www.phprpc.org/zh_CN/
     */
    const MODE_PHP_RPC = 'php_rpc';
    const MODE_LOCAL = 'local';
    /**
     * @see http://code.google.com/p/fastcgirpc/
     */
    const MODE_FAST_RPC = 'fast_rpc';

    /**
     * @static
     * @param string $moduleId
     * @param string $serviceName
     * @param array $params
     * @return mixed|void
     */
    static public function call($moduleId = '', $serviceName = '', $params = array())
    {
         return self::instance()->callModuleService($moduleId,$serviceName,$params);
    }

    public $mode = self::MODE_LOCAL;

    protected $modulePath = array();


    public function callModuleService($moduleId = '', $serviceName = '', $params = array())
    {

        if ($this->mode = self::MODE_LOCAL) {
            return $this->callLocalModuleService($moduleId, $serviceName, $params);
        } elseif ($this->mode = self::MODE_JSON_RPC) {
            return $this->callJsonRpcModuleService($moduleId,$serviceName,$params);
        } else {
            throw new CException("the {$this->model} is not supported yet");
        }
    }

    /**
     * @param string $moduleId
     * @param string $serviceName
     * @param array $params
     * @return mixed
     */
    protected function callLocalModuleService($moduleId = '', $serviceName = '', $params = array())
    {
        $modulePath = $this->getModulePath($moduleId);
        if (($pos = strpos($serviceName, '.')) !== false) {
            $serviceClassName = ucfirst(substr($serviceName, 0, $pos)) . "Service";
            $serviceMethodName = substr($serviceName, $pos + 1);
        } else {
            $serviceClassName = ucfirst($moduleId) . "Service";
            $serviceMethodName = $serviceName;
        }
        $servicePath = $modulePath . DIRECTORY_SEPARATOR . 'services' . DIRECTORY_SEPARATOR . "{$serviceClassName}.php";

        require_once($servicePath);

        $serviceObj = new $serviceClassName();
        // setMode
        if($serviceObj instanceof IModuleService){
            $serviceObj->setProcessMode($this->mode);
        }
        return call_user_func_array(array($serviceObj, $serviceMethodName), $params);
    }

    /**
     * @param $moduleId 目前只支持平面化module 不支持更深层次的module嵌套了
     * @return string
     * 如果通过moduleId 去找模块的路径 影响单元测试的 很麻烦
     * 所以模块下的service 不要通过 module本身来提供 dolphin是module自身提供serviceXXX方法的
     */
    protected function getModulePath($moduleId = '')
    {
        // return  dirname(Yii::app()->getModule($moduleId)->getModulePath());
        $modulePath = Yii::app()->getModulePath();
        return $modulePath . DIRECTORY_SEPARATOR . $moduleId;
    }

    protected function callJsonRpcModuleService($moduleId = '', $serviceName = '', $params = array())
    {
        Yii::import('application.vendors.json_rpc.jsonRPCClient');
        //$serviceRemoteProxy = new jsonRPCClient($this->createAbsoluteUrl('/api/rpc'),true);
        $serviceRemoteProxy = new jsonRPCClient($this->createAbsoluteUrl('/api/rpc'));

        try {
            echo $serviceRemoteProxy->callModuleService($moduleId,$serviceName,$params);

        } catch (Exception $e) {
            echo nl2br($e->getMessage()).'<br />'."\n";
        }
    }

}


0

#3 User is offline   yiqing95 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 587
  • Joined: 27-December 10
  • Location:china

Posted 08 January 2013 - 01:31 PM

还有 现在跟第三方交互 都趋于 json或者二进制了 建议最好不要用soap 虽然这种方法很通用 但xml格式数据浪费数据很严重的 我倾向使用 json 。 现在php也有 json rpc 实现 其他语言也有 当然手机可能也有 你自己搜索吧
0

#4 User is offline   winson kong 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 13
  • Joined: 25-October 10

Posted 08 January 2013 - 09:40 PM

View Postyiqing95, on 08 January 2013 - 01:31 PM, said:

还有 现在跟第三方交互 都趋于 json或者二进制了 建议最好不要用soap 虽然这种方法很通用 但xml格式数据浪费数据很严重的 我倾向使用 json 。 现在php也有 json rpc 实现 其他语言也有 当然手机可能也有 你自己搜索吧


谢谢你的建议哈
因为刚学习YII,没想到这么快就要学别的语言。
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users