Video: Set up a REST API with CodeIgniter

Posted: 2011-03-17
Category: CodeIgniter

Tonight I started working on the RESTful API for PancakeApp - an invoicing system built in CodeIgniter - when I remembered how many people have been asking for help using REST_Controller. I wrote up an article on NetTuts last year Working with RESTful Services in CodeIgniter hoping that would cover the majority of questions but with new features like API Keys, Limiting and Logging being added I thought a quick run-through was in order. This video covers the basic implementation, HTTP Basic/Digest authentication, format switching and goes onto the new API Key and logging features.

As this is an admittedly an unplanned video I'll be accepting answers to the question "How many mistakes did I make?" on the back of a postcard. It's surprising how much time can go into screencasts, even bad ones!

Comments

Gravatar
Piers

2011-03-18

This might be a stupid question, but will the REST controller work along side a non-REST version of CI? As in, if I have my so-far developed app, I just slot in the library and use that to extend my controllers instead?

Gravatar

2011-03-18

That is exactly what this video demonstrates yes. I am dragging the "config/rest.php" and "core/Rest.php" files into a CodeIgniter application that has never had anything to do with REST before.

Those two files are all you need, nothing magical happened behind the scenes.

Gravatar
Jonob

2011-03-18

Phil,

This is cool, and just in time for a project that I am working on.

One of the things that is crucial is that validation is run in the models, and this is something that you mentioned briefly. How do you achieve this in CI?

Gravatar
Dan

2011-03-19

Hi Phil,

The RESTful system is impressive, I am sure I will find use for it in future projects. Have you ever worked with CI and SOAP services? I am interested in this for a project I am working on.

Gravatar
Reda

2011-03-20

hello, it's not a REST question , but ... if i understood well you are using an HMVC plugin for codeigniter, is it stable? can you please tell me where to get it ? as i'm looking for one to use in my application, i'm using ci 1.72
thanks

Gravatar
Dan

2011-03-20

Hi Reda,

I use 'modular extentions HMVC'. I have found it stable, working well and it can be found https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc/wiki/Home . Its simple to install and use and includes MY_Controller functionality working.

Gravatar
Boaz

2011-03-20

I love your work. However :) --
Try to place your microphone so that it doesn't pick up on so much keyboard hits / mouse clicks. Also, it was kinda hard to see the code on my screen - the resolution was a bit low and the font size was small. Maybe use one of those "zooming in" screen recorders or something?

Thanks for all your great work!

Gravatar
Alessandro Nadalin

2011-03-21

Hi Phil,

referring to the linked post ( Working with RESTful Services in CodeIgniter ), you are missing an important part of a really RESTful architecture, hypermedia, which is the most important slice of the uniform interface.

This is an HTTP interface ( a good one :) ), it isn't RESTful.

Don't be offended, I just wanted to give my 2 cents: there are common misconceptions in REST that its community is trying to fight :)

Cheers!

Gravatar

2011-03-21

This can be used to work with hypermedia just fine. Any MIME types can be used and any type of media can be served. This is entirely RESTful with support for formats, as it can support .foo and Accept / Content-Type headers.

I'd like to know what parts you believe are not RESTful, other than just mentioning "hypermedia".

Gravatar
Alessandro Nadalin

2011-03-21

Hi Phil,

I'm mainly referring at this: http://d2o0t5hpnwv4c1.cloudfront.net/552_ci/output-examples.png

When I mentioned hypermedia I was obviously talking about HATEOAS: it's not just the usage of formats which makes a service RESTful, but also the fact that its state is hypermedia-driven.

You say that this API is RESTful: I'm not able to distinguish the JSON responses very well, do they implement hypermedia controls?

Gravatar

2011-03-21

I have never seen the point of jamming links into the response, that is what documentation is for.

Being RESTful is a sliding scale and does not have to fit a criteria. What this API does it does RESTfully, and it does 90% of the CI community will need for their API's. As for HATEOAS? I don't see the point. I'd be interested to see some examples of it being useful as I've worked with the majority of current popular REST API's and not seen this in use. I'm all for following rules if they make sense, but I'm not trying to pass a validation test or get a some "REST Certification Approval" for the sake of it.

Gravatar
Alessandro Nadalin

2011-03-21

Directly from Roy Fielding (http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven):

"Think of it in terms of the Web. How many Web browsers are aware of the distinction between an online-banking resource and a Wiki resource? None of them. They don’t need to be aware of the resource types. What they need to be aware of is the potential state transitions — the links and forms — and what semantics/actions are implied by traversing those links. "

And some good point from John Heintz: http://johnheintz.blogspot.com/2007/11/just-in-rest-cant-handle-state.html
Zuelke explains HATEOAS very well: http://www.slideshare.net/Wombert/designing-http-interfaces-and-restful-web-services-phpbnl11-20110128/80

"I have never seen the point of jamming links into the response, that is what documentation is for. "

To just make an example... without using hypermedia relations you need your client to make assumptions about resource location ( such information can be retrieved on your documentation, for instance ).
When you change the implementation ( for example, URI schemas ), your client is broken: driving application's state by hypermedia means that clients are loosly coupled with your service and consume it without any assumption.

"I'm all for following rules if they make sense"

Read the first 3 slides:
http://www.slideshare.net/Wombert/designing-http-interfaces-and-restful-web-services-phpbnl11-20110128/93

As I said, the problem lies in the name you use, not the implementation.

;-)

I'm not trying to say the API you documented sucks.
Nor saying the CI community needs something better.
I'm just saying that it isn't RESTful.
Roy himself said years ago that non hypermedia-driven services aren't RESTful, so why do you need to call it that way?
Is it because REST is a cool buzzword? Oh, c'mon, your API can be great also if not RESTful, so there's no need to claim that it is something it isn't.

Cheers!

Gravatar
Alessandro Nadalin

2011-03-21

Ah, I was forgetting about another point:
"Being RESTful is a sliding scale and does not have to fit a criteria."

No, there are 5 constraints in RESTful architectures:
* communication happens between client & server
* they are stateless
* they are cacheable
* they are layered
* they implement a uniform interface

Code-On-Demand is another plus, although it is optional.

Ciao! :)

Gravatar

2011-03-21

Thanks for the link here: http://www.slideshare.net/Wombert/designing-http-interfaces-and-restful-web-services-phpbnl11-20110128/80

This explains what you were getting at nicely, but I disagree that this is anything to do with my implementation. This REST_Controller provides the tools to make an API but does not tell you what data is required, nor does it make any assumptions about where other resources are.

To say that REST_Controller should be building links to other controllers or resources automatically is like saying the CI_Controller in CodeIgniter should automatically be building sitemaps and adding in rel="next" tags to all of your pages... Hell no!

I thank you for your feedback and it has given me something to think about, but I strongly disagree that the lack of auto-magic HATEOS support in this controller code makes this a non RESTful API. If the developer who makes the API does not include those links in his output, THEN it is a non RESTful API, but that is nothing to do with this implementation.

Gravatar
Matt

2011-03-23

Are you using moduler extensions? Is that why you could load a model from a modules folder like $this->load->model('folder/model')? Also did you make pancake with pyroCMS?

Gravatar

2011-03-23

Matt: Yes this uses Modular Extensions and is based around a lot of the same libraries and architecture of PyroCMS. If you build modules for one you'll be able to build modules for the other pretty easily, but it is not litterally "built on top of" PyroCMS.

Gravatar
Alessandro Nadalin

2011-03-23

Hi Phil,

sorry for my latency, been busy :)

You right, you have the potentiality to build a RESTful API ( that video's one isn't ) with REST_Controller.
The automagic template generations feature is something discussed also in the Symfony community http://everzet.com/post/1581698750 but, like you, I'm pretty skeptic about it.

ciao!

Gravatar
Hans

2011-03-24

So Alessandro, to make this RESTful, a client send an Accept header to tell it what format (xml, json, etc, though I know true-REST is advocating XML as the best) and version of the "API" to use? Then in the response, we add a "Content-Type:" response and all other links would need a "type" with a similar content-type? Is that all that's missing from Phil's implementation? I'm experimenting and would like to hit as close to true REST as I can, though if I can't, I'm still going ahead and calling this a PHILful API implementation. :)

Gravatar

2011-03-24

Hans: Alessandro is saying that the quick example API I built in the video is not fully RESTful and he is quite right. The guy who coined the term RESTful says an API needs HATEOS and there are a few ways to do this, but the main part is setting a version in the mime type (which you can do) and returning links (which you can do).

This example covers the basics. If I covered everything you can do with this REST_Controller I would still be recording a week later.

One thing to remember is that while the example API is not fully RESTful, it is as RESTful as Twitter, Facebook, Flickr, etc and if those guys are wrong... hell I don't mind being wrong too.

Gravatar
Hans

2011-03-24

Phil: I agree, but I'd love to build something that can stand up years from now and I liked the idea of embedding a version and format (xml, json, etc) in the URL (so people could connect to an older API, like how Google does theirs). I couldn't conceptualize how to tell what version of the API to use or format without url embedding, but I see now. Pretty cool.

I guess another argument is that I could pass any URL on my existing web site as is. A URL like http://myfakewebsite.org/members/surveys/ would show HTML with a menu, sidebar, survey list, etc, if the "Accept: text/html" was sent. The same URL could return XML/json if the Accept header was something that identified the format differently, maybe "Accept: text/json+v1.23". Then the resource location is consistent and lives long time.

Thanks to this page and conversation, I'm beginning to get the last elusive 10% about REST. And all because I was looking for a RESTful controller for CI... well done.

Gravatar
Wil Moore Iii

2011-03-26

Just a quick FYI:

Alessandro's image is wrong:
http://d2o0t5hpnwv4c1.cloudfront.net/552_ci/output-examples.png

He does mention HATEOAS but actually ignores a very simple component...Resources.
This URI: /users/format/json mixes in "/format/json" with the resource which should just be "/users". The format should be derived via the Accept / Content-Type headers as you (Phil) mentioned earlier.

Gravatar

2011-03-26

/format/json is a quick hack that was added in a long time ago but is not required. That was done to easily demonstrate the ability to switch format types. users.json and the Accept header are supported exactly the same meaning "Resources" are fully supported.

This is a quick "how-to" for everyone that has been trying to use some of the features but got stuck, not "This is an advanced guide on how all of REST works", so quit picking holes in it. The CodeIgniter community has been very happy with this, but the REST trolls are just being a pain.

Gravatar
Alessandro Nadalin

2011-03-26

Hi Wil,

that image is, actually, what I tried to point **against**. It's embedded in the post mentioned above ( "Working with RESTful Services in CodeIgniter" ).

URI schemas don't really matter, although they're a good exercise: for example, jim webber ( http://jim.webber.name/ ) states that it could be reasonable to use messy URI ( hard to guess ) for security reasons.

Gravatar
James

2011-03-31

For a better resolution of the video try the following link:

http://philsturgeon.blip.tv/file/4899981?filename=Philsturgeon-SetUpARESTAPIWithCodeIgniter863.m4v

Gravatar
Calvin Froedge

2011-03-31

Thanks for the vid, Phil. Took me all of 20 mins to implement thanks to you!

Gravatar
Feng

2011-04-13

i can not open the video , can you provide a link to download or upload to youtube?thanks

Gravatar
Ardani

2011-04-13

please tutorial video resolution is enlarged. I can not see the video clearly.thAnks

Gravatar
Anonymous

2011-05-18

The best contribution to CI community I've seen thus far.

Gravatar
Abs

2011-05-22

Hi Phil,

Excellent work. Really excited to try it out but I can't seem to get past one thing. How do you deal with different versions of an API? I was hoping to use multi level controllers:

http://localhost/api/v1/user
http://localhost/api/v2/user
http://localhost/api/v3/user

How would you approach this notion of multi level controllers?

I was hoping to make use of a multi level controller and made use of this class which was intended for 1.7.x: http://glennpratama.wordpress.com/2009/10/20/multi-level-subfolder-for-controller-in-codeigniter/. However, having read around the forum some have suggested a change to set_directory to get it working for 2.0. This all seems hacky...is there a better way?

Gravatar
Phil Sturgeon

2011-05-22

Abs: This is pretty easy if you move away from the idea that URL has to match controller structure. Make controllers/api_1 and controllers/api_2 and use routes to make it api/1/ if you like.

Or faff around with HTTP headers as explained in a link above.

Gravatar
Abs

2011-05-22

AAH! I get it, thanks for that bit of insight, it allowed me to move away from the line of thought I was previously glued to!

Thank you. :)

Gravatar
Abs

2011-05-22

Hi Phil,

Is there a reason you hard coded the api key variable name as "API-Key" - I tried to set my own key in the rest.php config file as:

$config['rest_key_name'] = 'api_key';

However, I find that in the REST_Controller you have this line:

if ($key = isset($this->_args['API-Key']) ? $this->_args['API-Key'] : $this->input->server($key_name))

Meaning it always has to be "API-Key"? I might be wrong but this is how it looks to me as I can't use any other variable i.e. api_key.

Thanks.

Gravatar
Toopay

2011-06-08

IMO, dictated by HTTP verb in any API class function, will be lil bit tricky, especially based by how CodeIgniter works. Lets say, for example, if i had an user API class already, i will get a mess when i try to expand some user picture data (assume we want the "logic" uri like http://foo.com/api/user/id/1234/pictures, which actually represent http://foo.com/api/pictures?user=1234/). I mean, it lil bit tricky to apply some proxy technique in CI (not like in Kohana, for example), and i thought because you already create "different" behaviour function, like $this->response, there is a chance to apply some proxy technique to other API class(eg : picture API) from some API class (eg : user), if we didnt dictate by HTTP verb.

Also i wonder, why you didnt implement/support some abstract class to force any child class to have uniformal function.

Overall, you did a nice RESTful, i repeat : RESTful, implementation.



Gravatar
Phil Sturgeon

2011-06-08

Toopay: I'm not entirely sure what you are talking about but I'll try to answer the questions I think you have asked.

1. URL's can be whatever you like. This is CodeIgniter, so URL segments, GET variables or URI's with zany routes all work perfectly. Do whatever you want, this was a demo showing how most people can get it done.

2. Base classes, go for it! Do base classes however you like, this is nothing to do with the RESTful implementation I have demonstrated here. I do have a blog article on that if you'd like to Google it.

3. "if we didnt dictate by HTTP verb" I'd be interested to know how you are making your requests if they don't have any HTTP verb. Is that HTTP 2.0?

Gravatar
Toopay

2011-06-09

Again, seems you misinterpret me. Language barrier, i guessed (as usual). Let me repeat my opinion, about your REST implementation.

About URL. I know how Codeigniter can handle any url routing (either by set up a regex rule on routes file or bypass CI route by a hook function). But this is not the "clean" way(for me, at least). You already create '$this->response' function to build an HTTP output/response for any method calls, and what happen is : i just expect more from it. I tought that function is similar with how "other framework"'s (let say, Kohana) 'request-response' behaviour.

About (DICTATED BY) PUTTING HTTP's VERB IN FUNCTION's NAMES. The easy example, about these is like below case :
With your implementation, someone has created two working API class, let say 'User API' and 'Picture API'. They have uri similar with these (lets say they have set up routes or hook for this) :
- http://foo.com/api/user/1 - for access user resource with id 1
- http://foo.com/api/picture?user=1 - for access picture resource of user with id 1

And if that guy want to do something like FB did, provide a (logic) url like :
- http://foo.com/api/user/1/picture - for access picture resource of user with id 1

Then that guy may think that easily he can create, in his 'User API' class, some function named 'user_image', along with existed 'user_get', 'user_post', etc, and calling, with some proxy technique, 'Picture API' from there. Unfortunately, since your implementation DICTATES TO PUTTING HTTP's VERB IN FUNCTION's NAMES, those guy can't do what he want. Well, he have two option : create a route or hook for that, or licking his laptop LCD !!! :p

Last, about abstract class (not base class in your perspective). I just thought, you may define your REST_Controller class as 'abstract ' class, so that all methods marked abstract in the parent's class declaration must be defined by the child.
In the result, if you define :
abstract public function index_get();
abstract public function index_post();
abstract public function index_put();
abstract public function index_delete();
in REST_Controller, then all child class would have to implements "Uniform Interface" (as one of REST constraints), and the REST troll can live happily ever after.

But off course this is just about style (and taste). I've done, designing some REST architectural style in Kohana, and seeing generous guy like you, sharing something cool-awesome-shit like these, make me wonder if i can do the same :)

PS : For God sake, if you ever started your response with "I'm not entirely sure what you are talking about" again, because my english's syntactically like shit, i will take some English Course Class! :(

Gravatar
Toopay

2011-06-09

By the way, In addition, i will commented out at Alessandro Nadalin claim, that Phil's implementation isn't REST.

"that non hypermedia-driven services aren't RESTful" , he said (quoting RF statement). This is some multi-interpretation statement, since in his dessertation, RF said "The REST interface is designed to be efficient for large-
grain hypermedia data transfer, optimizing for the common case of the Web". So, "Efficient for large-grain hypermedia data transfer" is the result or impact of REST Architectural style, not some of "REST Certification Approval" provision.

Gravatar
Frank

2011-06-13

Hello Phil,

Is it me or is this video taking forever to begin streaming and also pauses for a long time? I also tried downloading it for offline viewing with the same results.

Thx.

Gravatar
Stefan

2011-07-13

Just a quick question: is it possible to have binary data like an image as response? so the case could be calling the api from an app and returning an image from the server...

Gravatar
Test

2011-08-09

Thanks for this, very helpful. Task for the future:
- Complete a sentence WITHOUT saying "errmm" or "umm" every-other word.

Gravatar
Phil Sturgeon

2011-08-09

It so easy to be a smart-ass when you are anonymous isn't it? Post a better video.

Gravatar
Odin Chen

2011-08-17

Thanks for the video. It really helped me a lot.

Just for your information, this is a good adjustment for your API example. Took me a while to find this when I tried to work with database.

http://codeigniter.com/forums/viewthread/157000/

Just implemented all your REST API stuffs to RedHat OpenShift along with MySQL. Works like a charm :D

Gravatar
Amizya

2011-08-22

Hello,

Thanks for this video and thanks for the great REST Library, im working with it in my project. but got some problems when i POST to a controller i got the following error:

Uncaught exception 'Exception' with message 'Format class does not support conversion from "php".'

Can you help please ? :>

Gravatar
Cor Bosman

2011-09-25

Hey Phil, im trying to be more RESTful by using a header for version information:

GET /api/users
Accept: application/json; version=1.0

But this provides a bit of a challenge. How do you nicely separate the different api versions inside api.php? Or even better, how can I make CI load different controllers based on the Accept: header? Like have an api_1.0.php, api_1.1.php etc.

Any thoughts on this?

Gravatar
Blessy

2011-10-17

Hello Phil,

I have sucessfuly implemented REST API in CI 2.0.3.But How can I set up keys?what is the use of this keys? can you please explain me?

When to use these keys ? Is it for securing My API ? please help me

Gravatar
Sirfilip

2011-11-08

Brilliant!

Gravatar
Drazen Mokic

2012-01-06

Firstly (is this a word?) i wanna thank you for this library, it`s so useful.

Watching the video, i`m curious if your model needs to return data in a certain way, so that your library can return it in xml or json.

In the video it looks like magic, it just works.

Gravatar
Andy Ferras

2012-01-17

Hey, any tutorials on how I would incorporate token authentication into this?

Gravatar
Zac

2012-01-24

Thank you for this video. It really helped me out!

Gravatar
James Andrews

2012-03-07

Before I go bastardizing a copy of Form_validation.php, are there any hooks to allow for validating PUT data? am using form_validation library on POST data, but I would like that on PUT data I validate the data as well, since I am forcing all data to be passed on a put before update. Ideas?

BTW, very cool, saved me a lot of work. Much appreciated.

Gravatar
Pattarawat Chormai

2012-03-09

Can i check the key and user is match together ?

Gravatar
Tan Nguyen

2012-04-27

Hi Greate video!
I was wondering if there is possibility to get rest login usernamses and passwords from the database.
Or is it only static. Because i wanna use my user table as auth.

Gravatar
Phil Sturgeon

2012-04-27

Just add a "user_id" field in there and join it on to the main user field. Don't over-think authentication, the key just needs to link to a user somehow.

Gravatar
Tan Nguyen

2012-04-27

Can you show some examples please?
because i want to fill the $config['rest_valid_logins'] = array('admin' => '1234'); with values from the database. Thanks

Gravatar
Phil Sturgeon

2012-04-27

Just use API keys instead.

Gravatar
Axel

2012-10-26

Hey Phil,

Can I hire you for some consulting help around this? I'm trying to post to a controller with HTTPClient, but whenever i do, it bombs on me, and tells me a general error has was encountered, and the action i've requested is not allowed"

Its an internal server error.

the error does not happen when i leave the post body blank in http client.

Thanks in advance, please email me directly and maybe we could hop on a 5 min screen share.

Gravatar
George

2012-11-19

Hi Phil,

Lately I tried to use your rest client-server solution and I discovered that you don't encode the requests from the client to the server. Basically the request to the server can be intercepted and reproduced.

Maybe it's a good idea to use a public key for identifying the client and a private key to encode the request on the client, send the encoded request to server and the server job is first to decode the request using the private key (identified from server db by public key) and finally run the request.

Hope you understood my english :)

PS: Search on net.tutsplus: Creating an API-Centric Web Application

BR,
George

Gravatar
Brian

2012-11-20

Great tutorial and great work on the REST API Integraion with CI!

After following your tutorial, i am somewhat stuck on getting results back from my database by their 'id'. I am able to get responses back from ALL the data in my database but when I run this code :

$data = $this->my_model->get($this->get('id'));

It says that the method GET is undefined in my model.

Could you possibly shed some light on how to setup a database model to work with the REST API?

Thanks!

Gravatar
Usman

2012-11-21

Hello,
its really a vet nice article and helped me alot.
I have only one confusion.Can you please explain me

1. what are the levels?
2. Why we are using these levels?
3. What value i have to provide into the level field in database.
4. Why we ahve provided these thing in the Keys controller:

protected $methods = array(
'index_put' => array('level' => 10, 'limit' => 10),
'index_delete' => array('level' => 10),
'level_post' => array('level' => 10),
'regenerate_post' => array('level' => 10),
);

It will really help me out.

Thanx

Gravatar

2012-11-26

Brian: This is CodeIgniter so do it however you normally do. Make sure your model either A) has that method or B) extends a class that does. REST_Controller has nothing to do with your database interaction.

Gravatar

2012-11-26

George: There is no need for me to encode requests, that is what HTTPS is for. Use that.

Usman: Levels are arbitrary numbers. The level number of the key must be higher or equal to whatever level is defined in the array you posted.

Gravatar
Chris

2012-12-28

can i use this REST_Controller to make 2 different CI installations talk to each other?

I have it setup and working on its own installation just fine.
but whenever i try to use curl from a seperate CI install, i get nothing

my other question is if i am using api keys from a seperate install, where do i pass that through to api?

great video btw. thank you!

Posting comments after three months has been disabled.