Right-Size Your RESTful API: More Flexibility Without GraphQL

If you publish a RESTful API and there are situations when you need less (or more!) detail in the API responses from your API – then this post is for you. When I run into this with the teams I advise, the initial problem statement usually arrives more like “We need to move to GraphQL”, but this is a solution, not a problem to solve. The problem usually turns out to be either or both of:

  • the API responses are simply too large for some of the clients or uses cases, users need to select just the fields they want
  • the API doesn’t have enough information in the response payload for this client or use case, users need to choose to include nested data

GraphQL is one way to achieve these things, but this post is about the RESTful way to provide the right level of detail in an API response. Continue reading

Querying the GitHub GraphQL API

In a recent project around open source contributors, I wanted to take a look at which projects a particular user (actually a few of them, but I wrote a wrapper to repeat the process for each handle) maintains. GitHub doesn’t show this maintainer relationship, so instead I used the v4 GraphQL API and looked at pull request comments on repositories that the user has access to. I’m sharing my query and the Python script I used to make the API calls to. Continue reading

What Does URI Stand For?

I get a lot of complaints about an API that I maintain (http://api.joind.in) which is “missing” the ID field. This ID field is the database’s primary key; if the user doesn’t have access to the database (they don’t), then it seems to me that the primary key probably isn’t all that useful.

Instead, the API publishes each record with a unique uri field. If this record is referred to by another record, then this full identifier will be used in every case. If this record should be included in a collection, this exact same identifier will be used there, too. You can reach the resource directly by requesting its URI. In the same way that we might refer to a website by its URL, we refer to records in RESTful systems by their URI*. If you need to store these somewhere for your own use, you can use whatever key you like with the local storage, you may even choose to use the uri field as it is unique.

* URI stands for Unique Resource Identifier

Are Subqueries RESTful?

Twitter is great for one-liners, but it’s very difficult to carry on any kind of advanced conversation there. Therefore when I saw this tweet yesterday, I knew I’d be picking a different medium to reply:

The blog seems like a good place, as I can put examples and all kinds other things here, and waffle at length (which is really why I like it!). Because when condensed to tweet form, the answer is really “it depends”.

The Problem(s)

REST is all about representations of resources. They might come in different formats, and they might appear at their own URI as well as in one or more collections, but essentially you just get a representation of a thing. This is great, apart from when it isn’t.

  • What if you want a smaller result set with only a limited number of fields?
  • What if you want related data? For every resource in a collection?

Continue reading

Five Clues That Your API isn’t RESTful

I get a lot of emails asking me to get involved with API projects, and that means I see a lot of both implemented and planned “RESTful” APIs. Now, I absolutely love REST and for a data-driven application, it would be my first choice. A service of some other description may work better for other scenarios or skill sets, and non-RESTful services can be very, very useful. If you tell me that your service is RESTful, then I expect it to be. If you’re not sure, look out for these clues:

It has a single endpoint

I don’t really care what else is going on in your API, any “RESTful” API which has a statement such as “all requests are made to http://example.com/rest” is … not RESTful. REST is all about handling representations of resources, each is represented by its own URI and we operate directly on that. If it looks like “pretty URLs”, then it’s probably along the right lines. Continue reading

Building A RESTful PHP Server: Understanding the Request

Once upon a time, what seems like a lifetime ago, I was away for a couple of weeks, and I wrote a series of posts about serving RESTful APIs from PHP to keep my blog going while I was away. Fast forward a few years and those posts are outdated and still wildly popular – so I thought it was about time I revisited this and showed how I’m writing RESTful PHP servers today!

In the first part of this (probably) 3-part series, we’ll begin with the basics. It might seem boring, but the most important thing to get right with REST is parsing all the various elements of the HTTP request and responding accordingly. I’ve put in code samples from from a small-scale toy project I created to make me think about the steps involved (should I put the code somewhere so you can see it? Let me know). Without further ado, let’s dive in and begin by sending all requests through one bootstrap script: Continue reading

GETting RESTful collections – may I filter?

At work at Ibuildings recently, I’ve been teaching some classes on web services, and its a topic that I’ve spoken about once or twice at conferences. But something has always bothered me, so I find myself in the unusual position of blogging a question.

RESTful collections

So, when you are retrieving information from a RESTful service. You have two options: retrieve a specific resource, whose URL you know; or retrieve a collection, which may contain a list of resources. I’ve also seen some nice ways of filtering collections, by creating kind of “sub collections” or “views”, similar to what twitter does with the URL of lists, for example http://twitter.com/dpcon/speakers10 which is like a filtered list of twitter users.

What if I want to search and sort?

Is it RESTful to add GET parameters to a collection in order to add functionality such as filtering, sorting, or pagination? What I have in mind is a URL that looks something like this:

  • http://example.com/users?orderby=firstname&start=0
  • http://example.com/users?start=0&limit=25
  • http://example.com/users?active=1&orderby=join_date&limit=12

This is what I would do with a search results page in a web application, and I use the same approach to web services which works really well and I recommend it to everyone! But is it RESTful?

I am also wondering where OpenSearch would fit into the answer for all this, I only noticed it recently but the more I look at it the more I think it could be an interesting addition!

Thoughts, links for me to RTFM, and all other additions are welcome in the comments box :)

Adding PUT variables to Request Object in Zend Framework

When I wrote recently about testing web services within Zend Framework, I missed out a really key piece of information! I didn’t explain how I was reading the PUT vars in my controller code in the first place – so I’ll rectify that omission now.

Its very simple: I have extended Zend_Controller_Action with my own, and all controllers inherit from here. This has a routeAction() which grabs the incoming variables from a PUT request and sets them as parameters within the usual $this->getRequest() scope, then forwards on the request. Here is my class:

class My_Controller_Action extends Zend_Controller_Action
{
    public function routeAction()    
    {
        // handle grabbing PUT vars
        if($this->getRequest()->isPut()) {
            parse_str($this->getRequest()->getRawBody(), $params);
            foreach($params as $key => $value) {
                $this->getRequest()->setParam($key, $value);
            }
        }
        $this->_forward(strtolower($this->getRequest()->getMethod()));
    }
}

So in my controller code, I simply call out to $this->getRequest()->getParam(‘name’) or whatever, and in my tests I can set those parameters as I showed in my other article.

I hope this makes sense, its one of those things I set up once and use a lot (and now I’ll be able to refer to how I did it!), if you have any queries, comments, improvements or if this helps you then please leave a comment – I haven’t come across anyone else doing anything similar but I know there must be, so let me know!

Using Zend_Test for Web Services

Recently I had cause to develop a web service and so I wrote some tests to go along with it – or I was about to. When I looked at the asserts available in Zend_Test, they were all geared towards HTML/CSS output – but we can test just as effectively on another output.

Using Zend_Test, I set up the request object I wanted to send, and dispatched it. Then I retrieved the body and, since this service returns JSON, I json_decoded it. This gives me an object – and I can go ahead and use all the functionality of PHPUnit, with or without Zend_Test’s additions, to test my service. Its perhaps easiest to show this in a few steps.

Setting up the request object

The idea here is that you set up any parameters you need to including the HTTP verb to use and cookies if needed, then despatch the request. Here’s a few examples, first a simple GET method, with a cookie.

        $request = $this->getRequest();
        $request->setMethod('GET');
        $request->setCookie('token','xxxx');
        $this->dispatch('/user/24');

Including data with a POST request:

        $request = $this->getRequest();
        $request->setMethod('POST');
        $request->setPost(array(
            'name' => 'new user',
            'organisation' => 49
            ));
        $this->dispatch('/user');

This is a REST service, so I also tested PUT and DELETE methods. DELETE just needs the setMethod() call since it doesn’t have any data with it, but PUT was a bit trickier – here’s an example of what I used:

        $request = $this->getRequest();
        $request->setMethod('PUT');
        $params = array('name' => 'Harry Potter');
        $request->setRawBody(http_build_query($params));
        $this->dispatch('/user/48');

Decoding the Response

This is the easy part, all I do is check the status code is what was expected, and then decode the response. My web service returns JSON so this part of each test looks something like:

        $this->assertResponseCode('200');

        $response = json_decode($this->getResponse()->getBody());

Testing the content of the response

Here we get into classic PHPUnit territory and simply use the assertTrue and assertEquals calls we’d use when testing anything else, an example is included for completeness:

        $this->assertEquals($response->contentType, 'user');
        $this->assertTrue(is_numeric($response->id));
        $this->assertEquals($response->name, 'new user');
        $this->assertEquals($response->organisation, 49);

In Conclusion

By combining the request/response awareness of Zend_Test with standard PHPUnit testing strategies, its easy to test web services as well as web pages. I hope the examples are helpful – if they help you or if you have anything to add, then leave a comment!