Class: Rackful::Server
- Inherits:
-
Object
- Object
- Rackful::Server
- Defined in:
- gems/rackful-0.1.1/lib/rackful_server.rb,
gems/rackful-0.1.1.orig/lib/rackful_server.rb
Overview
Rack compliant server class for implementing RESTful web services.
Instance Attribute Summary (collapse)
-
- (#[]) resource_factory
readonly
An object responding thread safely to method `#[]`.
Instance Method Summary (collapse)
-
- (Array<(status_code, response_headers, response_body)>) call(p_env)
As required by the Rack specification.
- - (Array<(status_code, response_headers, response_body)>) call!(p_env)
-
- (Server) initialize(resource_factory)
constructor
An object responding thread safely to method `#[]`.
A Server has no knowledge, and makes no presumptions, about your URI namespace. It requires a _Resource Factory_ which produces Resources given a certain absolute path.
The Resource Factory you provide need only implement one method, with signature `Resource #[]( String path )`. This method will be called with a URI-encoded path string, and must return a Resource, or `nil` if there’s no resource at the given path.
For example, if a Rackful client tries to access a resource with URI http://example.com/some/resource, then your Resource Factory can expect to be called like this:
resource = resource_factory[ '/your/resource' ]
If there’s no resource at the given path, but you’d still like to respond to `POST` or `PUT` requests to this path, you must return an empty resource.
.
Constructor Details
- (Server) initialize(resource_factory)
An object responding thread safely to method `#[]`.
A Rackful::Server has no knowledge, and makes no presumptions, about your URI namespace. It requires a _Resource Factory_ which produces Resources given a certain absolute path.
The Resource Factory you provide need only implement one method, with signature `Resource #[]( String path )`. This method will be called with a URI-encoded path string, and must return a Resource, or `nil` if there’s no resource at the given path.
For example, if a Rackful client tries to access a resource with URI http://example.com/some/resource, then your Resource Factory can expect to be called like this:
resource = resource_factory[ '/your/resource' ]
If there’s no resource at the given path, but you’d still like to respond to `POST` or `PUT` requests to this path, you must return an empty resource.
47 48 49 50 |
# File 'gems/rackful-0.1.1/lib/rackful_server.rb', line 47 def initialize(resource_factory) super() @resource_factory = resource_factory end |
Instance Attribute Details
- (#[]) resource_factory (readonly)
An object responding thread safely to method `#[]`.
A Rackful::Server has no knowledge, and makes no presumptions, about your URI namespace. It requires a _Resource Factory_ which produces Resources given a certain absolute path.
The Resource Factory you provide need only implement one method, with signature `Resource #[]( String path )`. This method will be called with a URI-encoded path string, and must return a Resource, or `nil` if there’s no resource at the given path.
For example, if a Rackful client tries to access a resource with URI http://example.com/some/resource, then your Resource Factory can expect to be called like this:
resource = resource_factory[ '/your/resource' ]
If there’s no resource at the given path, but you’d still like to respond to `POST` or `PUT` requests to this path, you must return an empty resource.
40 41 42 |
# File 'gems/rackful-0.1.1/lib/rackful_server.rb', line 40 def resource_factory @resource_factory end |
Instance Method Details
- (Array<(status_code, response_headers, response_body)>) call(p_env)
As required by the Rack specification.
For thread safety, this method clones `self`, which handles the request in #call!. A similar approach is taken by the Sinatra library.
61 62 63 64 65 66 |
# File 'gems/rackful-0.1.1/lib/rackful_server.rb', line 61 def call(p_env) start = Time.now retval = dup.call! p_env #$stderr.puts( 'Duration: ' + ( Time.now - start ).to_s ) retval end |
- (Array<(status_code, response_headers, response_body)>) call!(p_env)
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'gems/rackful-0.1.1/lib/rackful_server.rb', line 73 def call!(p_env) request = Request.new( self.resource_factory, p_env ) # See also Request::current(): Thread.current[:rackful_request] = request response = Rack::Response.new begin raise HTTP404NotFound \ unless resource = self.resource_factory[Path.new(request.path)] unless resource.path == request.path response.header['Content-Location'] = resource.path request.content_path = resource.path end request.assert_if_headers resource if %w{HEAD GET OPTIONS PUT DELETE}.include?( request.request_method ) resource.__send__( :http_#{request.request_method}", request, response ) else resource.http_method request, response end rescue HTTPStatus => e # Already handled by HTTPStatus#initialize: #raise if $DEBUG && 500 <= e.status bct = e.class.best_content_type request.accept, false serializer = e.serializer(bct) response = Rack::Response.new serializer, e.status, e.headers ensure # The next line fixes a small peculiarity in RFC2616: the response body of # a `HEAD` request _must_ be empty, even for responses outside 2xx. if request.head? response.body = [] end end if 201 == response.status && ( location = response['Location'] ) && ( new_resource = request.resource_factory[location] ) && ! new_resource.empty? \ or ( (200...300) === response.status || 304 == response.status ) && ! response['Location'] && ( new_resource = request.resource_factory[request.path] ) && ! new_resource.empty? response.headers.merge! new_resource.default_headers end r = response.finish #~ $stderr.puts r.inspect r end |