Class CloudKit::Service

  1. lib/cloudkit/service.rb
Parent: Object

A CloudKit Service is Rack middleware providing a REST/HTTP 1.1 interface to a Store. Its primary purpose is to initialize and adapt a Store for use in a Rack middleware stack.

Examples

A rackup file exposing items and things as REST collections:

require 'cloudkit'
expose :items, :things

The same as above, adding OpenID and OAuth/Discovery:

require 'cloudkit'
contain :items, :things

An explicit setup, without using the Rack::Builder shortcuts:

require 'cloudkit'
use Rack::Session::Pool
use CloudKit::OAuthFilter
use CloudKit::OpenIDFilter
use CloudKit::Service, :collections => [:items, :things]
run lambda{|env| [200, {'Content-Type' => 'text/html'}, ['Hello']]}

For more examples, including the use of different storage implementations, see the Table of Contents in the examples directory.

Included modules

  1. ResponseHelpers

Attributes

store [R]

Public class methods

new (app, options)
[show source]
    # File lib/cloudkit/service.rb, line 34
34:     def initialize(app, options)
35:       @app         = app
36:       @collections = options[:collections]
37:     end

Public instance methods

call (env)
[show source]
    # File lib/cloudkit/service.rb, line 39
39:     def call(env)
40:       @@lock.synchronize do
41:         @store = Store.new(:collections => @collections)
42:       end unless @store
43: 
44:       request = Request.new(env)
45:       unless bypass?(request)
46:         return auth_config_error if (request.using_auth? && auth_missing?(request))
47:         return not_implemented unless @store.implements?(request.request_method)
48:         send(request.request_method.downcase, request) rescue internal_server_error
49:       else
50:         @app.call(env)
51:       end
52:     end

Protected instance methods

auth_config_error ()
[show source]
     # File lib/cloudkit/service.rb, line 153
153:     def auth_config_error
154:       json_error_response(500, 'server auth misconfigured').to_rack
155:     end
auth_missing? (request)
[show source]
     # File lib/cloudkit/service.rb, line 141
141:     def auth_missing?(request)
142:       request.current_user == nil
143:     end
bypass? (request)
[show source]
     # File lib/cloudkit/service.rb, line 157
157:     def bypass?(request)
158:       collection = @collections.detect{|type| request.path_info.match("/#{type.to_s}")}
159:       !collection && !request.uri.meta_uri?
160:     end
delete (request)
[show source]
    # File lib/cloudkit/service.rb, line 89
89:     def delete(request)
90:       @store.delete(
91:         request.uri,
92:         {}.filter_merge!(
93:           :remote_user => request.current_user,
94:           :etag        => request.if_match)).to_rack
95:     end
get (request)
[show source]
    # File lib/cloudkit/service.rb, line 56
56:     def get(request)
57:       response = @store.get(
58:         request.uri,
59:         {}.filter_merge!(
60:           :remote_user => request.current_user,
61:           :offset      => request['offset'],
62:           :limit       => request['limit']))
63:       inject_link_headers(request, response)
64:       response.to_rack
65:     end
head (request)
[show source]
     # File lib/cloudkit/service.rb, line 97
 97:     def head(request)
 98:       response = @store.head(
 99:         request.uri,
100:         {}.filter_merge!(
101:           :remote_user => request.current_user,
102:           :offset      => request['offset'],
103:           :limit       => request['limit']))
104:       inject_link_headers(request, response)
105:       response.to_rack
106:     end
index_link_header (request)
[show source]
     # File lib/cloudkit/service.rb, line 130
130:     def index_link_header(request)
131:       index_path = request.path_info.sub(/\/_resolved(\/)*$/, '')
132:       base_url = "#{request.domain_root}#{index_path}"
133:       "<#{base_url}>; rel=\"index\""
134:     end
inject_link_headers (request, response)
[show source]
     # File lib/cloudkit/service.rb, line 112
112:     def inject_link_headers(request, response)
113:       response['Link'] = versions_link_header(request) if request.uri.resource_uri?
114:       response['Link'] = resolved_link_header(request) if request.uri.resource_collection_uri?
115:       response['Link'] = index_link_header(request)    if request.uri.resolved_resource_collection_uri?
116:       response['Link'] = resolved_link_header(request) if request.uri.version_collection_uri?
117:       response['Link'] = index_link_header(request)    if request.uri.resolved_version_collection_uri?
118:     end
not_implemented ()
[show source]
     # File lib/cloudkit/service.rb, line 149
149:     def not_implemented
150:       json_error_response(501, 'not implemented').to_rack
151:     end
options (request)
[show source]
     # File lib/cloudkit/service.rb, line 108
108:     def options(request)
109:       @store.options(request.uri).to_rack
110:     end
post (request)
[show source]
    # File lib/cloudkit/service.rb, line 67
67:     def post(request)
68:       if tunnel_methods.include?(request['_method'].try(:upcase))
69:         return send(request['_method'].downcase, request)
70:       end
71:       response = @store.post(
72:         request.uri,
73:         {:json => request.json}.filter_merge!(
74:           :remote_user => request.current_user))
75:       update_location_header(request, response)
76:       response.to_rack
77:     end
put (request)
[show source]
    # File lib/cloudkit/service.rb, line 79
79:     def put(request)
80:       response = @store.put(
81:         request.uri,
82:         {:json => request.json}.filter_merge!(
83:           :remote_user => request.current_user,
84:           :etag        => request.if_match))
85:       update_location_header(request, response)
86:       response.to_rack
87:     end
resolved_link_header (request)
[show source]
     # File lib/cloudkit/service.rb, line 125
125:     def resolved_link_header(request)
126:       base_url = "#{request.domain_root}#{request.path_info}"
127:       "<#{base_url}/_resolved>; rel=\"http://joncrosby.me/cloudkit/1.0/rel/resolved\""
128:     end
tunnel_methods ()
[show source]
     # File lib/cloudkit/service.rb, line 145
145:     def tunnel_methods
146:       ['PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE']
147:     end
update_location_header (request, response)
[show source]
     # File lib/cloudkit/service.rb, line 136
136:     def update_location_header(request, response)
137:       return unless response['Location']
138:       response['Location'] = "#{request.domain_root}#{response['Location']}"
139:     end
versions_link_header (request)
[show source]
     # File lib/cloudkit/service.rb, line 120
120:     def versions_link_header(request)
121:       base_url = "#{request.domain_root}#{request.path_info}"
122:       "<#{base_url}/versions>; rel=\"http://joncrosby.me/cloudkit/1.0/rel/versions\""
123:     end