Module: AdhdRESTServer

Defined in:
lib/adhd/adhd_rest_server.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#proxy_connObject

Returns the value of attribute proxy_conn.



34
35
36
# File 'lib/adhd/adhd_rest_server.rb', line 34

def proxy_conn
  @proxy_conn
end

Instance Method Details

#handle_getObject



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/adhd/adhd_rest_server.rb', line 175

def handle_get  
  resume
  # We need to connect to the right server and build a header
  server_uri = URI.parse(@our_doc[:db].server.uri)
  server_addr = server_uri.host
  server_port = server_uri.port
  
  docid = @our_doc[:doc]._id
  dbname = @our_doc[:db].name
  request = "GET /#{dbname}/#{docid}/#{@our_doc[:doc].filename} HTTP/1.0\r\n\r\n"
  #send_data request
  #close_connection_after_writing
  puts "Connect to #{server_addr} port #{server_port}"
  conn = EM::connect server_addr, server_port, ProxyToServer, self, request
  EM::enable_proxy proxy_conn, self, 1024    
end

#handle_putObject



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/adhd/adhd_rest_server.rb', line 203

def handle_put
  resume
  
  # We need to connect to the right server and build a header
  server_uri = URI.parse(@our_doc[:db].server.uri)
  server_addr = server_uri.host
  server_port = server_uri.port
  
  docid = @our_doc[:doc]._id
  dbname = @our_doc[:db].name
  request = "PUT /#{dbname}/#{docid}/#{@our_doc[:doc].filename}?rev=#{@our_doc[:doc]["_rev"]} HTTP/1.0\r\n"
  request += "Content-Type: #{@our_doc[:doc].mime_type}\r\n"
  request += "Content-Length: #{@our_doc[:doc].size_bytes}\r\n"
  request += "\r\n"
  request += @buffer
  #send_data request
  #close_connection_after_writing
  puts "Connect to #{server_addr} port #{server_port}"
  conn = EM::connect server_addr, server_port, ProxyToServer, self, request
  EM::enable_proxy self, proxy_conn, 1024  
end

#initialize(node_manager) ⇒ Object



36
37
38
39
40
# File 'lib/adhd/adhd_rest_server.rb', line 36

def initialize node_manager
  @node_manager = node_manager
  @buffer = ""
  @status = :header
end

#proxy_receive_data(data) ⇒ Object



197
198
199
200
# File 'lib/adhd/adhd_rest_server.rb', line 197

def proxy_receive_data data
  # Response to a PUT request only
  send_data data
end

#proxy_unbindObject



192
193
194
195
# File 'lib/adhd/adhd_rest_server.rb', line 192

def proxy_unbind
  # Our cpnnection to the CouchDB has just been torn down
  close_connection_after_writing
end

#receive_data(data) ⇒ Object

The format we are expecting:

PUT somedatabase/document/attachment?rev=123 HTTP/1.0 Content-Length: 245 Content-Type: image/jpeg

<JPEG data>



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/adhd/adhd_rest_server.rb', line 54

def receive_data data

  # First we get all the headers in to find out which resource 
  # we are looking for.
  
  if @status == :header
    @buffer += data
           
    if data =~ /\r\n\r\n/

     # Detected end of headers
     header_data = @buffer[0...($~.begin(0))]
    
     # Try the webrick parser
     @req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)

     StringIO.open(header_data, 'rb') do |socket|
       @req.parse(socket)
     end
     
     # The rest of the incomming connection        
     @buffer = @buffer[($~.end(0))..-1]
     
     # Compute the ID of the sought resource
     if @req.path =~ /\/adhd\/(.*)/
       @req.header["Filename"] = $1
       @req.header["ID"] = MD5.new($1).to_s
     else
       # Throw an error          
     end
    
     # Change the status once headers are found
     @status = :find_node 
    else
     # Avoid DoS via buffer filling
     close_connection if @buffer.length > 1000
    end
    
  end
  
  # Now we have the headers, but maybe not the full body, and we are looking
  # for the right node in our network to handle the call.
  if @status == :find_node
     pause # We want to tell the remote host to wait a bit
           # This would allow us to defer the execution of the calls to find 
           # the right nodes, and extract the doc.
     
     # TODO: We need to push all the chit-chat with the remote servers to 
     #       A deferable object, or some other connection, not to block.
     #       Right now we are blocking and it sucks.  
           
     # Now get or write the document associated with this file
     if @req.request_method == "GET"
       
       @our_doc = @node_manager.srdb.get_doc_directly(@req.header["ID"])
       
       # TODO: handle erros if file does not exist
       if @our_doc[:ok]
         @status == :get
         handle_get
       else
         send_data "Problem"
       end          
     end
     
     if @req.request_method == "PUT"
       # Define a Doc with the data so far
       @our_doc = ContentDoc.new
       
       @our_doc._id = @req.header["ID"]
       @our_doc.internal_id = @req.header["ID"]
       @our_doc.size_bytes = @req.content_length
       @our_doc.filename = @req.header["Filename"]
       @our_doc.mime_type = @req.content_type
       
       # Write to the right node
       @our_doc = @node_manager.srdb.write_doc_directly(@our_doc)
       
       # TODO: if an error is returned here, we cannot execute the query
       if @our_doc[:ok]
         @status = :put
         handle_put
       else          
         send_data "Problem"
       end
     end
   
     # Now send the reply as an HTTP1.0 reponse
   
     # HTTP/1.0 200 OK
     # Date: Fri, 08 Aug 2003 08:12:31 GMT
     # Server: Apache/1.3.27 (Unix)
     # MIME-version: 1.0
     # Last-Modified: Fri, 01 Aug 2003 12:45:26 GMT
     # Content-Type: text/html
     # Content-Length: 2345
     # ** a blank line *
     # <HTML> ...
   
   
   
   # response = @our_doc.to_s
   # 
   # send_data "HTTP/1.0 200 OK\r\n"
   # send_data "Content-Type: text/plain\r\n"
   # send_data "Content-Length: #{response.length}\r\n"
   # send_data "\r\n"
   # send_data response
   #
   # # Close the connection
   # close_connection_after_writing      

  end
  
  # We have the header and the node, and now we execute the request
  if @status == :execute_request
  
  end
  
end

#unbindObject



225
226
227
# File 'lib/adhd/adhd_rest_server.rb', line 225

def unbind
  puts "-- someone disconnected from the echo server!"
end