Class: NOMS::Command::XMLHttpRequest

Inherits:
Object
  • Object
show all
Defined in:
lib/noms/command/xmlhttprequest.rb

Overview

Implements a subset of the XMLHttpRequest interface. This class is exposed as a constructor function in the Javascript VM. It uses NOMS::Command::UserAgent for HTTP conversations, adding checks for the same-origin policy.

Constant Summary collapse

OPENED =
1
HEADERS_RECEIVED =
2
LOADING =
3
DONE =
4
@@origin =
nil
@@ua =
nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeXMLHttpRequest

Returns a new instance of XMLHttpRequest.



52
53
54
55
56
57
# File 'lib/noms/command/xmlhttprequest.rb', line 52

def initialize()
    @origin = @@origin
    @ua = @@ua || NOMS::Command::UserAgent.new(@origin)
    @headers = { }
    @readyState = 0
end

Instance Attribute Details

#headersObject

Returns the value of attribute headers.



50
51
52
# File 'lib/noms/command/xmlhttprequest.rb', line 50

def headers
  @headers
end

#responseTextObject

Returns the value of attribute responseText.



50
51
52
# File 'lib/noms/command/xmlhttprequest.rb', line 50

def responseText
  @responseText
end

Class Method Details

.originObject



31
32
33
# File 'lib/noms/command/xmlhttprequest.rb', line 31

def self.origin
    @@origin
end

.origin=(origin) ⇒ Object



35
36
37
# File 'lib/noms/command/xmlhttprequest.rb', line 35

def self.origin=(origin)
    @@origin = NOMS::Command::URInion.parse(origin)
end

.useragentObject



39
40
41
# File 'lib/noms/command/xmlhttprequest.rb', line 39

def self.useragent
    @@ua
end

.useragent=(ua) ⇒ Object

Set the class attribute for the UserAgent; ideally this is shared among everything in one noms invocation.



46
47
48
# File 'lib/noms/command/xmlhttprequest.rb', line 46

def self.useragent=(ua)
    @@ua = ua
end

Instance Method Details

#abortObject



177
178
179
# File 'lib/noms/command/xmlhttprequest.rb', line 177

def abort()
    lambda { || @readyState = 0 }
end

#do_send(data = nil) ⇒ Object

NOMS::Command::UserAgent doesn’t do async calls (yet) since httpclient doesn’t do anything special with them and you can only busy-wait on them. So they’re “simulated”, and by “simulated” I mean “performed synchronously”.



146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/noms/command/xmlhttprequest.rb', line 146

def do_send(data=nil)
    # @async ignored
    @ua.add_redirect_check do |url|
        self.same_origin? url
    end
    @response, landing_url = @ua.request(@method, @url, data, @headers)
    # We don't need the 'landing' URL
    @ua.pop_redirect_check
    self.readyState = OPENED
    self.readyState = HEADERS_RECEIVED
    self.readyState = LOADING
    @responseText = @response.content
    self.readyState = DONE
end

#DONEObject



123
124
125
# File 'lib/noms/command/xmlhttprequest.rb', line 123

def DONE
    DONE
end

#getAllResponseHeadersObject



173
174
175
# File 'lib/noms/command/xmlhttprequest.rb', line 173

def getAllResponseHeaders
    lambda { || @response.headers.map { |h, v| "#{h}: #{v}" }.join("\n") + "\n" }
end

#getResponseHeader(header) ⇒ Object



169
170
171
# File 'lib/noms/command/xmlhttprequest.rb', line 169

def getResponseHeader(header)
    @response.header[header.downcase] unless @response.nil?
end

#HEADERS_RECEIVEDObject



115
116
117
# File 'lib/noms/command/xmlhttprequest.rb', line 115

def HEADERS_RECEIVED
   HEADERS_RECEIVED
end

#LOADINGObject



119
120
121
# File 'lib/noms/command/xmlhttprequest.rb', line 119

def LOADING
    LOADING
end

#onreadystatechangeObject



87
88
89
# File 'lib/noms/command/xmlhttprequest.rb', line 87

def onreadystatechange
    @onreadystatechange
end

#onreadystatechange=(callback) ⇒ Object



91
92
93
# File 'lib/noms/command/xmlhttprequest.rb', line 91

def onreadystatechange=(callback)
    @onreadystatechange = callback
end

#open(method, url, async = true, user = nil, password = nil) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/noms/command/xmlhttprequest.rb', line 73

def open(method, url, async=true, user=nil, password=nil)
    raise NOMS::Command::Error.new "origin of #{url} doesn't match application origin (#{@origin})" unless
        same_origin? @ua.absolute_url(url)
    # Should we run onreadystatechange when resetting this? Not doing it for now.
    @readyState = 0
    @responseText = ''
    @response = nil
    @method = method
    @url = url
    @async = async
    @user = user
    @password = password
end

#OPENEDObject



111
112
113
# File 'lib/noms/command/xmlhttprequest.rb', line 111

def OPENED
    OPENED
end

#readyStateObject



95
96
97
# File 'lib/noms/command/xmlhttprequest.rb', line 95

def readyState
    @readyState
end

#readyState=(value) ⇒ Object



99
100
101
102
103
104
105
# File 'lib/noms/command/xmlhttprequest.rb', line 99

def readyState=(value)
    @readyState = value
    unless @onreadystatechange.nil?
        @onreadystatechange.methodcall self
    end
    @readyState
end

#same_origin?(other) ⇒ Boolean

Checks whether the URL has the same origin as the “origin” URL

Returns:

  • (Boolean)


65
66
67
68
69
70
71
# File 'lib/noms/command/xmlhttprequest.rb', line 65

def same_origin?(other)
    other = NOMS::Command::URInion.parse(other)
    return false unless @origin.scheme == other.scheme
    return false unless @origin.host == other.host
    return false unless @origin.port == other.port
    return true
end

#send(*vary) ⇒ Object

This problematic implementations attempts to “guess” when Object#send is intended, and when the Javascript- style xhr.send() is desired. The one ambiguous situation it can’t recover from is when there is one string argument, this is a valid invocation of XMLHttpRequest#send as well as Object#send, and we settle on XMLHttpRequest#send.



133
134
135
136
137
138
139
# File 'lib/noms/command/xmlhttprequest.rb', line 133

def send(*vary)
    if vary.size == 0 or (vary.size == 1 and ! vary[0].is_a? Symbol)
        do_send(*vary)
    else
        super
    end
end

#setRequestHeader(header, value) ⇒ Object



107
108
109
# File 'lib/noms/command/xmlhttprequest.rb', line 107

def setRequestHeader(header, value)
    @headers[header] = value
end

#statusObject



161
162
163
# File 'lib/noms/command/xmlhttprequest.rb', line 161

def status
    @response.status.to_i unless @response.nil?
end

#statusTextObject



165
166
167
# File 'lib/noms/command/xmlhttprequest.rb', line 165

def statusText
    @response.status + ' ' + @response.reason unless @response.nil?
end

#useragentObject



59
60
61
# File 'lib/noms/command/xmlhttprequest.rb', line 59

def useragent
    @ua
end