[CI] 使用CodeIgniter框架搭建RESTful API服务

在2011年8月的时候,我写了一篇博客《使用CodeIgniter框架搭建RESTful API服务》,介绍了RESTful的设计概念,以及使用CodeIgniter框架实现RESTful API的方法。转眼两年过去了,REST在这两年里有了很大的改进。我对于前一篇博客中的某些方面不是很满意,所以希望能利用这次机会写一个更加完善的版本。
我的项目基于Phil Sturgeon的CodeIgniter REST Server,遵循他自己的DBAD协议。Phil的这个项目很棒,干净利落,简单实用,并且极具特色,解决了我自己项目中两个问题:在请求中查询语句的使用,以及复杂的身份验证方法。正如我前面所说,我的项目基于Phil的项目开发,并且只有一个方面不同:我给每个资源分别分配一个控制器,而不是用一个独立庞大的控制器进行统一管理。使用多个独立控制器的好处是维护起来更加简单方便。
完整的项目源码可以在awhitney42/codeigniter-restserver-resources下载。
RESTful在深入探讨之前,我们先来回顾一下TESTful的概念。REST全名Representational State Transfer,中文可以译为:表现层状态转化,是一种网络服务的架构工具,而不仅仅是一套接口规范。
使用名词而不是动词你的RESTful接口应该提供访问而不是方法。
所以,这样是不可取的:
/createCustomer
/getCustomer?id=666
应该这样:
POST /customers
GET  /customers/666
所有东西都应该有IDREST的优点之一就是简洁,一定程度上来讲,REST只是一个URI的集合,每个资源都需要一个独一无二的ID作为一个标识。
GET /customers/666
GET /products/4234
使用动词进行操作在REST里,使用不同的HTTP动词进行增删改查的操作:
[td]
动词        操作
POST        新建一个资源
GET        读取一个资源
PUT        更新一个资源
DELETE        删除一个资源
使用这个REST服务的映射表来设计接口,在开发客户端的时候可以轻松上手,不用深入理解接口的含义。这套标准十分适用于REST,符合面向服务架构(SOA)的核心设计思想:服务抽离、松耦合、可复用、可发现、健全性。
通过这个一致的映射关系,客户端也知道哪个动词是幂等(Idempotent)的。幂等是指这个操作可以重复多次,并且每次都会得到相同的结果。参照HTTP规范,GET、PUT和DELETE操作是幂等的,POST操作不是幂等的。这也就是为什么在REST中使用POST来进行添加操作,而使用PUT来进行更新操作。
把东西链接起来REST中的一个核心概念是HATEOAS(Hypermedia As The Engine Of Application State),即“超媒体即应用状态引擎”。这意味着应该始终使用链接(超媒体)来获取资源信息,然后客户端通过这个链接就可以获取到不同的资源。
所以,相关的资源应当返回一条链接,而不是返回整个资源的内容。
也就是,该这样:

<officer id="1">
   <name>James T. Kirk</name>
   <rank>Captain</rank>
   <subordinates>
      <link ref="http://ncc1701/api/officers/2">
      <link ref="http://ncc1701/api/officers/3">
   </subordinates>
</officer>
而不该这样:
<officer id="1">
   <name>James T. Kirk</name>
   <rank>Captain</rank>
   <subordinates>
      <officer id="2">
         <name>Spock</name>
         <rank>Commander</rank>
      </officer>
      <officer id="3">
         <name>Doctor Leonard McCoy</name>
         <rank>Commander</rank>
      </officer>
   </subordinates>
</officer>

  返回资源的链接应该用完整的URI地址而不是相对路径,这要求客户端请求这些资源的当前状态,维持HATEOAS原则。使用完整的URI地址的好处是客户端不需要额外的了解API相关的内容,只需要简单的访问这些链接就可以了。
提供多种资源表现方式REST中的R代表Representational,即表现层,这意味着REST服务应该提供不同的表现方式,以全面支持不同的客户端请求。在一次HTTP请求中,服务器可以通过指定的表现方式返回资源,REST服务应该使用标准的表现方式,以便客户端之间的信息互通。
比如可以通过如下请求XML格式的数据:
GET /customers/666
Accept: application/xml
或者vcard格式:
GET /customers/666
Accept: application/vcard
或者pdf格式:
GET /customers/666
Accept: application/pdf
或者自定义格式:
GET /customers/666
Accept: application/vnd.mycompany.customer-v1+json
使用状态码作为回复HTTP的状态码提供了一套标准化方案,用来反馈请求的状态。
[td]

含义        解释
200        OK        确认GET、PUT和DELETE操作成功
201        Created        确认POST操作成功
304        Not Modified        用于条件GET访问,告诉客户端资源没有被修改
400        Bad Request        通常用于POST或者PUT请求,表明请求的内容是非法的
401        Unauthorized        需要授权
403        Forbidden        没有访问权限
404        Not Found        服务器上没有资源
405        Method Not Allowed        请求方法不能被用于请求相应的资源
409        Conflict        访问和当前状态存在冲突
CodeIgniterCodeIgniter是一个流行的MVC框架,很适合用来进行RESTful API开发。控制器(Controller)处理客户端的请求并返回内容,模型(Model)进行增删改查(CRUD)的操作,视图(View)用来处理资源的表现格式。不过在这个例子里,我们没有用模型,而是直接用控制器进行格式处理,这样整个项目更干净更简单。
代码可以直接在Github中获取:codeigniter-restserver-resources。
在接下来的例子里,我们用到了REST_Controller这个库,继承自原生的CI_Controller。它可以完成绝大部分繁杂的工作:处理请求、调用模块、格式化内容、返回数据。你的每个资源控制器都应该继承自REST_Controller这个类。
下面我们来看一个例子,我们假设要提供一个Widgets资源的RESTful接口:

class Widgets extends REST_Controller
get()Widgets类中的第一个函数是get(),用来响应HTTP的GET请求。这个函数调用了父类的protected函数_get(),用来获取请求中的参数ID。然后这个函数根据是否有参数ID使用widgets_model调用getWidgets()或者getWidget($id)方法,模型的返回值将会通过父类的response()函数返回,返回的内容包含对应的状态码和符合格式的数据。

[mw_shl_code=php,true]function get()
{
    $id = $this->_get(‘id‘);
    if(!$id)
    {
        $widgets = $this->widgets_model->getWidgets();
        if($widgets)
            $this->response($widgets, 200); // 200 being the HTTP response code
        else
            $this->response(array(‘error‘ => ‘Couldn\‘t find any widgets!‘), 404);
    }
    $widget = $this->widgets_model->getWidget($id);
    if($widget)
        $this->response($widget, 200); // 200 being the HTTP response code
    else
        $this->response(array(‘error‘ => ‘Widget could not be found‘), 404);
}

  cURL是一个很好的命令行工具,我们可以用来测试REST服务,返回一个JSON格式的数据:

则会返回如下内容:
HTTP/1.1 200 OK
Status: 200
Content-Type: application/json
{"1":{"id":1,"name":"sprocket"},"2":{"id":2,"name":"gear"}}
请求特定的资源也很简单,这次我们去请求ID为2的widget并且通过XML格式返回:
$ curl -i -H "Accept: application/xml" -X GET http://foo.com/index.php/api/widgets/id/2
返回如下内容:

HTTP/1.1 200 OK
Status: 200
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8"?>
<xml><id>2</id><name>gear</name></xml>
如果请求一个不存在的资源就会返回404的错误码:

HTTP/1.1 404 Not Found
Status: 404
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8"?>
<xml><error>Widget could not be found</error></xml>
post()接下来的函数是post(),用来处理创建widget的POST请求。可以通过$this->_post_args获取请求的数据。父类通过Format.php对请求的数据进行处理并把它们放到了$this->_post_args里。接下来post()方法使用widgets_model模型调用createWidgets($data)函数,如果数据非法或者请求冲突,widgets_model模型会抛出异常并且返回异常的内容。如果调用成功,则会调用getWidget($id)函数获取最新的widget,在返回的时候会将返回值和201 (Created)的状态码一起返回。

function post()
{
    $data = $this->_post_args;
    try {
        $id = $this->widgets_model->createWidget($data);
    } catch (Exception $e) {
        // Here the model can throw exceptions like the following:
        // * Invalid input data:
                    //   throw new Exception(‘Invalid request data‘, 400);
        // * Conflict when attempting to create, like a resubmit:
                    //   throw new Exception(‘Widget already exists‘, 409)
        $this->response(array(‘error‘ => $e->getMessage()),
                                    $e->getCode());
    }
    if ($id) {
        $widget = $this->widgets_model->getWidget($id);
        $this->response($widget, 201); // 201 is the HTTP response code
    } else
        $this->response(array(‘error‘ => ‘Widget could not be created‘),
                                    404);
}

  

时间: 2024-08-07 00:14:33

[CI] 使用CodeIgniter框架搭建RESTful API服务的相关文章

使用CodeIgniter框架搭建RESTful API服务

使用CodeIgniter框架搭建RESTful API服务 发表于 2014-07-12   |   分类于 翻译笔记   |   6条评论 在2011年8月的时候,我写了一篇博客<使用CodeIgniter框架搭建RESTful API服务>,介绍了RESTful的设计概念,以及使用CodeIgniter框架实现RESTful API的方法.转眼两年过去了,REST在这两年里有了很大的改进.我对于前一篇博客中的某些方面不是很满意,所以希望能利用这次机会写一个更加完善的版本. 我的项目基于P

Go实战--通过gin-gonic框架搭建restful api服务(github.com/gin-gonic/gin)

生命不止,继续 go go go !!! 先插播一条广告,给你坚持学习golang的理由: <2017 软件开发薪酬调查:Go 和 Scala 是最赚钱的语言> 言归正传! 之前写过使用golang实现简单的restful api相关的博客: Go实战–实现简单的restful api(The way to go) 其中,使用了github.com/gorilla/mux,今天要跟大家介绍的是gin-gonic/gin. gin-gonic/gin 介绍: Gin is a HTTP web

基于gin web框架搭建RESTful API服务

这篇主要学习go项目中的项目结构.项目规范等知识,ROM采用的database/sql的写法. 1.技术框架 利用的是ginweb框架,然后ROM层选用database/sql,安装mysql驱动.安装方式如下: //使用github上的gin托管地址 $ go get -u github.com/gin-gonic/gin $ go get github.com/go-sql-driver/mysql 2.项目结构如下 项目结构分析: 1.main.go主要是存放路由,启动项目: 2.rout

【重学Node.js 第1&amp;2篇】本地搭建Node环境并起RESTful Api服务

本地搭建Node环境并起RESTful Api服务 课程介绍看这里:https://www.cnblogs.com/zhangran/p/11963616.html 项目github地址:https://github.com/hellozhangran/happy-egg-server 说明:本想分两章讲环境搭建和起api服务,但操作下来确实过于简单.但考虑到整个系列的完整性也不能不讲,那就把这两篇合二为一吧 本地搭建Node环境 开发环境主要是指Node.MongoDB.本人是用的mac电脑,

开放接口/RESTful/Api服务的设计和安全方案

总体思路 这个涉及到两个方面问题:一个是接口访问认证问题,主要解决谁可以使用接口(用户登录验证.来路验证)一个是数据数据传输安全,主要解决接口数据被监听(HTTPS安全传输.敏感内容加密.数字签名) 用户身份验证:Token与Session开放接口Api服务其实就是客户端与服务端无状态交互的一种形式,这有点类似REST(Representational State Transfer)风格.普通网站应用一般使用session进行登录用户信息的存储和验证(有状态),而开放接口服务/REST资源请求则

玩转 SpringBoot 2 快速搭建 | RESTful Api 篇

概述 RESTful 是一种架构风格,任何符合 RESTful 风格的架构,我们都可以称之为 RESTful 架构.我们常说的 RESTful Api 是符合 RESTful 原则和约束的 HTTP 协议的Web 接口,需要注意的是它和 HTTP 协议并非绑定关系.我的个人理解就是:通过HTTP协议不同请求方法(GET.POST.PUT.Patch,DELETE)来判断如何操作统一命名的资源,并且通过不同的响应码来知道执行的状态. 关于 RESTful API 具体详细介绍,我推荐阅读下面 3

maven+SpringMVC搭建RESTful后端服务框架

今天来尝试一下搭建基于SpringMVC的RESTful标准的后端服务. 首先,什么是MVC?M-model,模型,指业务数据层,具体一点就是业务逻辑与数据库的交互:V-view,视图,用来展示数据,传统SpringMVC中控制器有返回类型ModelAndView,即返回含有数据模型与页面视图的jsp文件:C-controller,控制器,通常负责处理与用户间的交互,控制从数据库取数与返回结果到用户等. 那么,什么是REST风格的服务呢?REST(Representational State T

搭建RESTful API来使用Fabric Node SDK 开篇

在Balance-Transfer中,有关于Node SDK比较完备的例子. SDK的官方文档在这里:https://fabric-sdk-node.github.io/ Balance-Transfer中的各项配置项都已经准备了,如果需要重新生成artifacts,务必在生成之后相应的修改docker-compose.yaml,network-config.yaml 启动网络 运行./runApp.sh后,得到类似的结果: Stopping peer1.org1.example.com ...

三分钟学会API接口设计 之 Compass 的Restful API 快速入门指南 -- 使用Flask框架

声明: 本博客欢迎转载,但请保留原作者信息! 作者:曾国仕 团队:华为杭州OpenStack团队 引子 大部分开源框架基本上都是使用Curl + RPC的方式构筑系统,以提供对外\对内的交互能力. 这种设计,本人认为更多地是出于层次化与模块化设计的考量,简化整个架构,使得开发轻量简单化. 本文主要介绍Compass的REST API的设计与实现. 通过本文档,读者至少能快速搭建一个属于自己的REST API 框架,并且能够基于该框架进行功能扩展以建立一个完整的系统. Compass的结构简介 图