Class: RubyRest::RESTServlet

Inherits:
WEBrick::HTTPServlet::AbstractServlet
  • Object
show all
Includes:
Atom, Tools
Defined in:
lib/rubyrest/servlets.rb

Overview

This is the servlet that actually exposes a REST API by translating HTTP requests into ‘generic’ or ‘custom’ service methods.

Direct Known Subclasses

CRUDServlet

Constant Summary collapse

ANONYMOUS_ACCESS =
"POST/credentials"

Constants included from Atom

Atom::ATOMSERV_TYPE, Atom::ATOM_TYPE, Atom::HTML_TYPE, Atom::MODULEID, Atom::NAMESPACES, Atom::WORKSPACE_METHOD

Constants included from Tools

Tools::ATOM_DATE_FORMAT, Tools::ERRORS

Instance Method Summary collapse

Methods included from Atom

#build_entry, #build_feed, #build_service_document, #format_response

Methods included from Tools

#error, #format_atom_date, #nvl, #parse_atom_date, #to_class, #to_gem_name, #to_module_name

Constructor Details

#initialize(server, *options) ⇒ RESTServlet

Injects some RubyRest configuration options from the server to the servlet



20
21
22
23
24
25
26
27
# File 'lib/rubyrest/servlets.rb', line 20

def initialize( server, *options )
  super( server, options )
  @servicemodule = server.rubyrest[ :servicemodule ]
  
  if server.rubyrest.has( :authmodel )
    @authmodel = server.rubyrest[ :authmodel ]
  end
end

Instance Method Details

#anonymous_accessObject

Defines whether the request is allowed to be processed without the need of a security token



145
146
147
# File 'lib/rubyrest/servlets.rb', line 145

def anonymous_access
  "#{@http_method}/#{@model}" == ANONYMOUS_ACCESS
end

#check_security(request) ⇒ Object

Checks that a token is present in the request exception if doing a POST on a credentials property



151
152
153
154
155
156
157
158
159
160
# File 'lib/rubyrest/servlets.rb', line 151

def check_security( request )
  auth_class = to_class( @servicemodule , @authmodel )
  if @token == nil and !anonymous_access
    raise WEBrick::HTTPStatus::Unauthorized
  end
  if @token != nil
    @principal = auth_class.validate( @token )
    raise WEBrick::HTTPStatus::Unauthorized if @principal == nil
  end
end

#credentials_create(request) ⇒ Object

Custom service method that authenticates a username/password pair found in the request body. The authentication is left to the class defined by the :authmodel configuration option.

Developpers can provide their own implementation, however it is recommended to subclass the class Credentials

Raises:

  • (WEBrick::HTTPStatus::Unauthorized)


131
132
133
134
135
136
137
138
# File 'lib/rubyrest/servlets.rb', line 131

def credentials_create( request )
  auth_class = to_class( @servicemodule, @authmodel )
  auth = auth_class.new
  auth_class.rest_bind( auth, @body )
  auth = auth_class.authenticate( auth )
  raise WEBrick::HTTPStatus::Unauthorized if auth == nil
  return auth  
end

#dashboard(request) ⇒ Object

Returns the model defined by the configuration option :dashboard



164
165
166
167
# File 'lib/rubyrest/servlets.rb', line 164

def dashboard( request ) 
  clazz = to_class( @servicemodule, "dashboard" )
  clazz.rest_retrieve( @principal )
end

#dispatch(request, response) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/rubyrest/servlets.rb', line 63

def dispatch( request, response )

  @service_method = resolve_service_method
  check_security( request ) if @authmodel != nil
  @result = self.method( @service_method ).call( request )

  if @result.respond_to? "unauthorized" and @result.unauthorized == true
    raise WEBrick::HTTPStatus::Unauthorized
  else
    response.status = @success_code
    format_response( request, response )
  end
end

#do_DELETE(request, response) ⇒ Object



111
112
113
114
115
116
117
# File 'lib/rubyrest/servlets.rb', line 111

def do_DELETE( request, response )
  resolve_params( request )
  incompatible_path( request ) if @id == nil
  @generic_method = :delete
  @success_code = 410
  dispatch( request, response )
end

#do_GET(request, response) ⇒ Object



88
89
90
91
92
93
# File 'lib/rubyrest/servlets.rb', line 88

def do_GET( request, response )
  resolve_params( request )
  @success_code = 200
  resolve_get_method
  dispatch( request, response )
end

#do_POST(request, response) ⇒ Object



95
96
97
98
99
100
101
# File 'lib/rubyrest/servlets.rb', line 95

def do_POST( request, response )
  resolve_params( request )
  incompatible_path( request ) if @id != nil
  @generic_method = :create
  @success_code = 201
  dispatch( request, response )
end

#do_PUT(request, response) ⇒ Object



103
104
105
106
107
108
109
# File 'lib/rubyrest/servlets.rb', line 103

def do_PUT( request, response )
  resolve_params( request )
  incompatible_path( request ) if @id == nil
  @generic_method = :update
  @success_code = 200
  dispatch( request, response )
end

#incompatible_path(request) ⇒ Object

Raises an error stating that the current http method is not compatible with the requested path.



121
122
123
# File 'lib/rubyrest/servlets.rb', line 121

def incompatible_path( request )
  error( 100, @http_method, request.path )
end

#resolve_custom_methodObject



48
49
50
51
52
53
54
55
# File 'lib/rubyrest/servlets.rb', line 48

def resolve_custom_method
  if @property != nil
    @custom_method = "#{@model}_#{@property}"
  else 
    @custom_method = WORKSPACE_METHOD
    @custom_method = "#{@model}_#{@generic_method}" if @model != nil
  end
end

#resolve_get_methodObject



78
79
80
81
82
83
84
85
86
# File 'lib/rubyrest/servlets.rb', line 78

def resolve_get_method
  if @property != nil
      @generic_method = :retrieve_related
  else 
    if @id != nil 
      @generic_method = :show
    else @generic_method = :retrieve end 
  end
end

#resolve_params(request) ⇒ Object

Inspects the request, and resolve the parameters The format of a request is the following:

/:model/:id/:property



34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/rubyrest/servlets.rb', line 34

def resolve_params( request )
  params = request.path.split( "/" )
  @http_method = request.request_method
  @token = request[ 'token']
  @model = params[1]
  @id = params[2]
  @property = params[3]
  begin
    @body = REXML::Document.new( request.body ) if request.body != nil
  rescue => e
    puts "unable to parse request body: #{request.body}"
  end
end

#resolve_service_methodObject



57
58
59
60
61
# File 'lib/rubyrest/servlets.rb', line 57

def resolve_service_method
  resolve_custom_method
  return @custom_method if self.respond_to? @custom_method
  return @generic_method
end