No REST for the wicked

Howtos, Tricks and Tips to build REST Servers

Gavin Mogan

Code Monkey @ Sauce Labs

@halkeye

https://www.gavinmogan.com

Whats going on?

  • Demonstration
  • How HTTP Works (basics)
  • Examples
  • "Best" Practices

Live Demo time

I need a volunteer

How does it work?

HTTP is made up of headers and bodies. Both on the request and the response side of things.

Request

          
            GET /index.html HTTP/1.1
            Host: www.example.com
            Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
            Accept-Language: en-CA,en;q=0.8
            Cache-Control: max-age=0
            User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103
            Safari/537.36
          
        

Response

          
            HTTP/1.1 200 OK
            Date: Mon, 23 May 2005 22:38:34 GMT
            Content-Type: text/html; charset=UTF-8
            Content-Encoding: UTF-8
            Content-Length: 138
            Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
            Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
            ETag: "3f80f-1b6-3e1cb03b"

            <html>
            <head>
            <title>An Example Page</title>
            </head>
            <body>Hello World, this is a very simple HTML document.</body>
            </html>
          
        

Live Demo time

Okay, backup time

              
                telnet localhost 8000
              
            
              
                GET / HTTP/1.0
              
            

Okay, backup time

              
                telnet google.com 80
              
            
              
                GET / HTTP/1.0
              
            

Types of HTTP Requests (1.0 - Simplified)

  • Getting Data
  • Should not change state
  • Should be repeatable
  • Just returns header, no body
  • Not really going to cover
  • Sending Data
  • Modifies state
  • No guarantees if sending again will do the same thing

HTTP/1.1 Added More

  • OPTIONS
  • PUT
  • DELETE
  • TRACE
  • CONNECT
  • Idempotent
  • "Save"
  • "Store at this location"
  • Idempotent
  • Delete this item (if exists)

Okay, how do I do it?

  • Sinatra (ruby)
  • Flask (python)
  • Express/Connect (node)
  • PHP
  • Rails (ruby)
  • Django (python)
  • Express + Sequalize (node)
  • Kohana (php)
  • Sympony (php)

Bare Bones

Sinatra (ruby)
              
                require 'sinatra'

                get '/hi' do
                  "Hello World!"
                end
              
            
Express (node)
              
                var express = require('express');
                var app = express();

                app.get('/', function (req, res) {
                  res.send('Hello World!');
                });

                app.listen(3000, function () {
                  console.log('Example app listening on port 3000!');
                });
              
            
Flask (python)
              
                from flask import Flask
                app = Flask(__name__)

                @app.route("/")
                def hello():
                  return "Hello World!"

                if __name__ == "__main__":
                app.run()
              
            
PHP
              
                <?php echo "Hello World";
              
            

Rails (ruby)

          
            $ rails new blog
            # it does some stuff
            $ cd blog
            $ ls
            app bin config config.ru db Gemfile Gemfile.lock lib log public Rakefile README.rdoc test tmp vendor
            $ bin/rails generate controller Welcome index
                  create  app/controllers/welcome_controller.rb
                   route  get "welcome/index"
                  invoke  erb
                  create    app/views/welcome
                  create    app/views/welcome/index.html.erb
                  invoke  test_unit
                  create    test/controllers/welcome_controller_test.rb
                  invoke  helper
                  create    app/helpers/welcome_helper.rb
                  invoke    test_unit
                  create      test/helpers/welcome_helper_test.rb
                  invoke  assets
                  invoke    coffee
                  create      app/assets/javascripts/welcome.js.coffee
                  invoke    scss
                  create      app/assets/stylesheets/welcome.css.scss
            $ rails server
            => Booting WEBrick
            => Rails 4.0.4 application starting in development on http://0.0.0.0:3000
            => Run `rails server -h` for more startup options
            => Ctrl-C to shutdown server
            [2016-07-18 22:06:05] INFO WEBrick 1.3.1
            [2016-07-18 22:06:05] INFO ruby 2.0.0 (2014-11-13) [x86_64-linux]

          
        

"Best" Practices

URL Schemas

  • GET /resource - should return all
  • GET /resource/id - should return one

  • POST /resource - should add one

  • PUT/POST /resource/id - should update/store one

  • DELETE /resource/id - should delete one

Response Code

  • 200 - All good
  • 201 - Created Successfully
  • 301 - Always look here instead
  • 302 - Look here instead
  • 401 - Security pls. Who are you?
  • 402 - Not allowed
  • 404 - Not found
  • 418 - I'm a little tea pot
  • 500 - PANIC ERROR HAS HAPPENED

https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

JSON
vs
XML
vs
YAML

Tooling

Browser Tools

Documentation

  • Github self documents all their urls
    • See https://api.github.com/repos/appium/appium
  • Swagger, Blueprint, Probably more
  • Lots of companies roll their own.
  • Documentation is hard
  • Provide Examples
    • Snippets
    • Downloadable examples