GithubHelp home page GithubHelp logo

wetransfer / apiculture Goto Github PK

View Code? Open in Web Editor NEW
12.0 36.0 3.0 134 KB

Honey-tasting REST API toolkit for Sinatra

License: MIT License

Ruby 97.23% Mustache 2.77%
wt-branch-protection-default

apiculture's Introduction

apiculture

A little toolkit for building RESTful API backends on top of Rack.

CI

Ideas

A simple API definition DSL with simple premises:

  • Endpoint URLs should be visible in the actual code. The reason for that is with nested blocks you inevitably end up setting up context somewhere far away from the terminal route that ends up using that context.
  • Explicit allowed/required parameters (both payload/query string and body)
  • Explicit description in front of the API action definition
  • Wrap the actual work into Actions, so that the API definition is mostly routes

A taste of honey

class Api::V2 < Apiculture::App

  use Rack::Parser, :content_types => {
    'application/json'  => JSON.method(:load).to_proc
  }

  extend Apiculture

  desc 'Create a Contact'
  required_param :name, 'Name of the person', String
  param :email, 'Email address of the person', String
  param :phone, 'Phone number', String, cast: ->(v) { v.scan(/\d/).flatten.join }
  param :notes, 'Notes about this person', String
  api_method :post, '/contacts' do
    # anything allowed within Sinatra actions is allowed here, and
    # works exactly the same - but we suggest using Actions instead.
    action_result CreateContact # uses Api::V2::CreateContact
  end

  desc 'Fetch a Contact'
  route_param :id, 'ID of the person'
  responds_with 200, 'Contact data', {name: 'John Appleseed', id: "ac19...fefg"}
  api_method :get, '/contacts/:id' do | person_id |
    json Person.find(person_id).to_json
  end
end

Generating documentation

For the aforementioned example:

File.open('API.html', 'w') do |f|
  f << Api::V2.api_documentation.to_html
end

or to get it in Markdown:

File.open('API.md', 'w') do |f|
  f << Api::V2.api_documentation.to_markdown
end

Running the tests

$ bundle exec rspec

If you want to also examine the HTML documentation that gets built during the test, set SHOW_TEST_DOC in env:

$ SHOW_TEST_DOC=yes bundle exec rspec

Note that this requires presence of the open commandline utility (should be available on both OSX and Linux).

Contributing to apiculture

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
  • Fork the project.
  • Start a feature/bugfix branch.
  • Commit and push until you are happy with your contribution.
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Copyright

Copyright (c) 2015-2018 WeTransfer. See LICENSE.txt for further details.

apiculture's People

Contributors

arnofleming avatar bermannoah avatar dennisvdvliet avatar depfu[bot] avatar grdw avatar hnhv avatar idanci avatar jeffisabelle avatar julik avatar luca-suriano avatar nyku avatar wjwh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apiculture's Issues

Support regexes in URL

api_method :get, '^\/transfers\/(?<id>\w+)\/(?<recipient_id>\w+)\/(?<security_hash>\w+{6})$' do |id, recipient_id, security_hash |
    bye([id, recipient_id, security_hash])
end

This now fails because the validator for route params does not understand these regexes

Feature: Output routes in "rake routes" look and feel

Something this:

routes = Alligator::V1.apiculture_stack.select{|d| d.is_a? Apiculture::ActionDefinition}
prefix = Alligator::V1.instance_variable_get(:@apiculture_mounted_at)
format = "%7s %-75s %-50s\n"
routes.each do |route|
  printf format % [route.http_verb.upcase, prefix + route.path, route.description]
end

But a little less hacky

Apiculture improvements

Apiculture Improvements

General guidelines

  • short endpoints, with at most a few lines inside
  • routes should be concise and straight-forward (no nesting/wildcards/etc)
  • a thin sugar coating that can be applied to most Rack frameworks
  • some out-of-the-box middlewares for a slightly opinionated framework

Documentation

  • Document thoroughly all stuff (halt, bail, action_result + args, json etc)

Actions

  • Variables passed to action_result are instance variables in the action class
  • Consider using service objects instead and call them in the endpoint itself (get rid of actions)

Error handling

  • out-of-the-box, should just work, with only defining a mapping between errors and status codes/messages
  • door open for logging/monitoring/exception tracking

Route listing

  • List all API routes with some command (maybe grouped in Rails app)

Testing

  • RSpec matchers (call endpoint, call action etc.)
  • Integration with testing framework (allow get/post/status/halt in the action as if it is mounted in a dummy sinatra app -- maybe treat the action as a standalone Sinatra app extension?)
  • Automatic RSpec test generator?

DSL

  • Better param types

    String/Integer/etc. would look nicer as :string, :integer

param :email, 'Email address of the person', String
  • Better endpoint definition

    endpoint or just post/get instead of api_method

api_method :post, '/contacts'
  • Better required params

    route_param/required_param are not visually distinctive. Would make :required as an argument to param (the DSL would then have param/param :required/route_param)

route_param :id, 'Subscription ID'
required_param :street_and_number, 'Street and number', String
  • Better responses

    json should accept anything and make a JSON out of it (so no more json foo.to_json). We currently deal with raw_json_response/json_response/json

  • Better status codes

    Automagic messages for status codes, check http://httpstatus.es

responds_with 200, 'Contact data'
  • Better endpoint descriptions

    Automagic description, from verb and resource, according to some standards

  • Authentication/authorization helpers

    Helpers like authenticate!/authorize! (maybe in a gem extension to apiculture). Maybe even the possibility to define an endpoint as authenticated (should return 401 otherwise)

swagger / openapi integration

Out of the box apiculture supports generating documentation in HTML format.

For more seamless cooperation with consumers of an API it would be nice if we can not only generate documentation in HTML format but also in the form of a swagger or openapi definition.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.