Module: Waxx::Http

Extended by:
Http
Included in:
Http
Defined in:
waxx/http.rb

Overview

Waxx Copyright © 2016 ePark labs Inc. & Daniel J. Fitzpatrick <dan@eparklabs.com> All rights reserved. Released under the Apache Version 2 License. See LICENSE.txt.

Constant Summary collapse

Status =
{
  "200"=>"OK",
  "206"=>"Partial Content",
  "300"=>"Multiple Choices",
  "301"=>"Moved Permanently",
  "302"=>"Found",
  "304"=>"Not Modified",
  "400"=>"Bad Request",
  "401"=>"Authorization Required",
  "403"=>"Forbidden",
  "404"=>"Not Found",
  "405"=>"Method Not Allowed",
  "406"=>"Not Acceptable",
  "411"=>"Length Required",
  "412"=>"Precondition Failed",
  "500"=>"Internal Server Error",
  "501"=>"Method Not Implemented",
  "502"=>"Bad Gateway",
  "506"=>"Variant Also Negotiates"
}
ContentTypes =
{
  css:     "text/css; charset=utf-8",
  csv:     "text/csv; charset=utf-8",
  htm:     "text/html; charset=utf-8",
  html:    "text/html; charset=utf-8",
  jpg:     "image/jpeg",
  js:      "application/javascript; charset=utf-8",
  json:    "application/json; charset=utf-8",
  tab:     "text/tab-separated-values; charset=utf-8",
  txt:     "text/plain; charset=utf-8",
  xml:     "text/xml",                              
  gif:     "image/gif",                             
  jpeg:    "image/jpeg",                            
  atom:    "application/atom+xml",                  
  rss:     "application/rss+xml",                   
           
  mml:     "text/mathml",                           
  jad:     "text/vnd.sun.j2me.app-descriptor",      
  wml:     "text/vnd.wap.wml",                      
  htc:     "text/x-component",                      
           
  png:     "image/png",                             
  tif:     "image/tiff",
  tiff:    "image/tiff",                            
  wbmp:    "image/vnd.wap.wbmp",                    
  ico:     "image/x-icon",                          
  jng:     "image/x-jng",                           
  bmp:     "image/x-ms-bmp",                        
  svg:     "image/svg+xml",
  svgz:    "image/svg+xml",                         
  webp:    "image/webp",                            
           
  woff:    "application/font-woff",                 
  jar:     "application/java-archive",
  war:     "application/java-archive",
  ear:     "application/java-archive",              
  hqx:     "application/mac-binhex40",              
  doc:     "application/msword",                    
  pdf:     "application/pdf",                       
  ps:      "application/postscript",
  eps:     "application/postscript",
  ai:      "application/postscript",                
  rtf:     "application/rtf",                       
  m3u8:    "application/vnd.apple.mpegurl",         
  xls:     "application/vnd.ms-excel",              
  eot:     "application/vnd.ms-fontobject",         
  ppt:     "application/vnd.ms-powerpoint",         
  wmlc:    "application/vnd.wap.wmlc",              
  kml:     "application/vnd.google-earth.kml+xml",  
  kmz:     "application/vnd.google-earth.kmz",      
  cco:     "application/x-cocoa",                   
  jardiff: "application/x-java-archive-diff",       
  jnlp:    "application/x-java-jnlp-file",          
  run:     "application/x-makeself",                
  pl:      "application/x-perl",
  pm:      "application/x-perl",                    
  prc:     "application/x-pilot",
  pdb:     "application/x-pilot",                   
  rar:     "application/x-rar-compressed",          
  rpm:     "application/x-redhat-package-manager",  
  sea:     "application/x-sea",                     
  swf:     "application/x-shockwave-flash",         
  sit:     "application/x-stuffit",                 
  tcl:     "application/x-tcl",
  tk:      "application/x-tcl",                     
  der:     "application/x-x509-ca-cert",
  pem:     "application/x-x509-ca-cert",
  crt:     "application/x-x509-ca-cert",            
  xpi:     "application/x-xpinstall",               
  xhtml:   "application/xhtml+xml",                 
  xspf:    "application/xspf+xml",                  
  zip:     "application/zip",                       
           
  bin:     "application/octet-stream",
  exe:     "application/octet-stream",
  dll:     "application/octet-stream",             
  deb:     "application/octet-stream",             
  dmg:     "application/octet-stream",             
  iso:     "application/octet-stream",
  img:     "application/octet-stream",             
  msi:     "application/octet-stream",
  msp:     "application/octet-stream",
  msm:     "application/octet-stream",             
           
  docx:    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",   
  xlsx:    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",          
  pptx:    "application/vnd.openxmlformats-officedocument.presentationml.presentation",  
  
  mid:     "audio/midi",
  midi:    "audio/midi",
  kar:     "audio/midi",                           
  mp3:     "audio/mpeg",                           
  ogg:     "audio/ogg",                            
  m4a:     "audio/x-m4a",                          
  ra:      "audio/x-realaudio",                    
           
  ts:      "video/mp2t",                           
  mp4:     "video/mp4",                            
  mpeg:    "video/mpeg",
  mpg:     "video/mpeg",                           
  mov:     "video/quicktime",                      
  webm:    "video/webm",                           
  flv:     "video/x-flv",                          
  m4v:     "video/x-m4v",                          
  mng:     "video/x-mng",                          
  asx:     "video/x-ms-asf",
  asf:     "video/x-ms-asf",                       
  wmv:     "video/x-ms-wmv",                       
  avi:     "video/x-msvideo",                      

}

Instance Method Summary collapse

Instance Method Details

#content_type(t, default = "application/octet-stream") ⇒ Object Also known as: ctype



11
12
13
# File 'waxx/http.rb', line 11

def content_type(t, default="application/octet-stream")
  ContentTypes[t.to_sym] || default
end

#content_typesObject



7
8
9
# File 'waxx/http.rb', line 7

def content_types
  ContentTypes
end

#escape(str) ⇒ Object Also known as: qs



20
21
22
23
24
# File 'waxx/http.rb', line 20

def escape(str)
  str.to_s.gsub(/([^a-zA-Z0-9_.-]+)/) do |m|
    '%' + m.unpack('H2' * m.bytesize).join('%').upcase
  end
end


90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'waxx/http.rb', line 90

def parse_cookie(str)
  Waxx.debug "parse_cookie"
  re = {}
  return re if str.nil? or str == ""
  str.split(/[;,]\s?/).each do |pairs|
    name, values = pairs.split('=',2)
    next unless name and values
    name = unescape(name)
    vals = values.split('&').collect{|v| unescape(v) }
    if re.has_key?(name)
      Waxx.debug "re has key"
      if Array === re[name]
        re[name].push vals
      else
        re[name] = [re[name], vals]
      end
    else
      re[name] = vals
    end
    re[name].flatten!
  end
  re.freeze
  re
end

#parse_data(env, meth, io, head) ⇒ Object



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
# File 'waxx/http.rb', line 115

def parse_data(env, meth, io, head)
  Waxx.debug "parse_data"
  if %w(PUT POST PATCH).include? meth
    data = io.read(env['Content-Length'].to_i)
    Waxx.debug "data.size: #{data.size} #{env['Content-Type']}"
    if env['Content-Length'].to_i == 0
      post = {}.freeze
      data = nil
    else
      case (env['Content-Type'] || env['content-type'] || env['Content-type'])
        when /x-www-form-urlencoded/
          post = query_string_to_hash(data).freeze
        when /multipart/
          post = parse_multipart(env, data).freeze
        when /json/
          post = (JSON.parse(data)).freeze
        else
          post = data.freeze
      end
    end
  else
    post = {}.freeze
    data = nil
  end
  [post, data]
end

#parse_head(io) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'waxx/http.rb', line 33

def parse_head(io)
  Waxx.debug("parse_head: #{io.class}", 9)
  env = {}
  head = ""
  while(e = io.gets)
    break if e.strip == ""
    head << e
    n, v = e.split(":", 2)
    env[n] = v.strip
  end
  Waxx.debug "env.size: #{env.size}", 9
  [env, head]
end

#parse_multipart(env, data) ⇒ Object



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
# File 'waxx/http.rb', line 62

def parse_multipart(env, data)
  boundary = env['Content-Type'].match(/boundary=(.*)$/)[1]
  parts = data.split("--"+boundary+"\r\n")
  post = {}
  parts.each{|part|
    next if part.strip == ""
    begin
      head, body = part.split("\r\n\r\n",2)
      headers = Hash[*(head.split("\r\n").map{|hp| hp.split(":",2).map{|i| i.strip}}.flatten)]
      cd = Hash[*("_=#{headers['Content-Disposition']}".split(";").map{|da| da.strip.gsub('"',"").split("=",2)}.flatten)]
      if cd['filename']
        post[cd['name']] = {
          filename: cd['filename'],
          data: body.sub(/\r\n--#{boundary}--\r\n$/,"").sub(/\r\n$/,""),
          content_type: headers['Content-Type'],
          headers: headers
        }
      else
        post[cd['name']] = body.sub(/\r\n--#{boundary}--\r\n$/,"").sub(/\r\n$/,"")
      end
    rescue => e
      Waxx.debug "Error parse_multipart: #{e}"
      post["Error in parse_multipart (uid-#{rand})"] = e
    end
  }
  post
end

#query_string_to_hash(str, base = {}) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'waxx/http.rb', line 47

def query_string_to_hash(str, base={})
  return base if str.nil? or str.strip == ""
  str.strip.split(/[;&]/).each{|nv|
    n, v = nv.split("=",2).map{|s| unescape(s)}
    if n =~ /\[\]$/
      n = n.sub(/\[\]$/,"")
      base[n] ||= []
      base[n] << v
    else
      base[n] = v
    end
  }
  base
end

#time(t = Time.new.utc) ⇒ Object



16
17
18
# File 'waxx/http.rb', line 16

def time(t=Time.new.utc)
  t.strftime('%a, %d %b %Y %H:%M:%S UTC')
end

#unescape(str) ⇒ Object



27
28
29
30
31
# File 'waxx/http.rb', line 27

def unescape(str)
  str.to_s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do |m|
    [m.delete('%')].pack('H*')
  end
end