Class: Store::Digest::HTTP

Inherits:
Object
  • Object
show all
Defined in:
lib/store/digest/http/version.rb,
lib/store/digest/http.rb

Constant Summary collapse

VERSION =
"0.1.0"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(store, base: nil, post_raw: nil, post_form: nil, param_map: nil) ⇒ HTTP

Returns a new instance of HTTP.



285
286
287
288
289
290
# File 'lib/store/digest/http.rb', line 285

def initialize store, base: nil, post_raw: nil, post_form: nil, param_map: nil
  @store     = store
  @base      = base      || BASE
  @post_raw  = post_raw  || POST_RAW
  @post_form = post_form || POST_FORM
end

Instance Attribute Details

#post_formObject (readonly)

Returns the value of attribute post_form.



283
284
285
# File 'lib/store/digest/http.rb', line 283

def post_form
  @post_form
end

#post_rawObject (readonly)

Returns the value of attribute post_raw.



283
284
285
# File 'lib/store/digest/http.rb', line 283

def post_raw
  @post_raw
end

#storeObject (readonly)

Returns the value of attribute store.



283
284
285
# File 'lib/store/digest/http.rb', line 283

def store
  @store
end

Instance Method Details

#call(env) ⇒ Object



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
# File 'lib/store/digest/http.rb', line 292

def call env
  # warn env.inspect
  # do surgery to request scheme
  env['HTTPS'] = 'on' if
    env['REQUEST_SCHEME'] and env['REQUEST_SCHEME'].downcase == 'https'

  req   = Rack::Request.new env
  uri   = URI(req.base_url) + env['REQUEST_URI']
  path  = uri.path.gsub(/^\/+\.well-known\/+ni\/+/, '').split(/\/+/, -1)
  query = uri_query uri # XXX req.GET is worthless
  body  = req.body

  # dispatch type
  disp = nil
  if path.empty?
    disp = :stats
  elsif store.algorithms.include?(algo = path.first.to_sym)
    if slug = path[1]
      if slug.empty?
        disp = :collection
      elsif !/^[0-9A-Za-z_-]+$/.match?(slug)
        return [404, [], []]
      else
        # determine if we have a whole digest or just part of one
        algo = query[:algorithm] = path.first.to_sym

        query[:digest] = slug

        if /^[0-9A-Za-z_-]+$/.match?(slug) and
            slug.length == (DIGESTS[algo] * 4/3.0).ceil
          disp = :object
        elsif /^[0-9A-Fa-f]+$/.match?(slug) and
            slug.length == DIGESTS[algo] * 2
          query[:radix] = 16

          disp = :object
        else
          disp = :partial
        end
      end
    else
      # redirect 307
      newuri = req.base_url + "/.well-known/ni/#{algo}/"
      return [307, [['Location', newuri.to_s]], []]
    end
  elsif path.first == post_raw
    disp = :raw
  elsif path.first == post_form
    # 415 unsupported media type
    # XXX EXPLAIN THIS
    return [415, [], []] unless
      req.get_header('Content-Type') == 'multipart/form-data'

    # 409 conflict
    # XXX EXPLAIN THIS
    return Rack::Response[409, [], []] unless
      req.POST.values.any? { |f|
      f.is_a? Rack::Multipart::UploadedFile }

    # XXX here is where we would set the date from the
    # multipart header but rack doesn't have a way of doing this

    disp = :raw
  else
    # 404 again  
    return [404, [], []]
  end

  if methods = DISPATCH[disp]
    m = (req.request_method == 'HEAD' ? 'GET' : req.request_method).to_sym
    if func = methods[m]
      begin
        resp = instance_exec uri.dup, query, req.env.dup, body, &func
        resp = Rack::Response[*resp] if resp.is_a? Array
      rescue Exception => e
        warn "wah #{e}"
        return [500, [], []]
      end

      resp.body = [] if req.request_method == 'HEAD'

      return resp.to_a
    else
      return [405, [], []]
    end
  else
    return [404, [], []]
  end
end