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.



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

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.



48
49
50
# File 'lib/noms/command/xmlhttprequest.rb', line 48

def headers
  @headers
end

#responseTextObject

Returns the value of attribute responseText.



48
49
50
# File 'lib/noms/command/xmlhttprequest.rb', line 48

def responseText
  @responseText
end

Class Method Details

.originObject



29
30
31
# File 'lib/noms/command/xmlhttprequest.rb', line 29

def self.origin
    @@origin
end

.origin=(origin) ⇒ Object



33
34
35
# File 'lib/noms/command/xmlhttprequest.rb', line 33

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

.useragentObject



37
38
39
# File 'lib/noms/command/xmlhttprequest.rb', line 37

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.



44
45
46
# File 'lib/noms/command/xmlhttprequest.rb', line 44

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”.



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

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.body
    self.readyState = DONE
end

#DONEObject



121
122
123
# File 'lib/noms/command/xmlhttprequest.rb', line 121

def DONE
    DONE
end

#getAllResponseHeadersObject



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

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

#getResponseHeader(header) ⇒ Object



167
168
169
# File 'lib/noms/command/xmlhttprequest.rb', line 167

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

#HEADERS_RECEIVEDObject



113
114
115
# File 'lib/noms/command/xmlhttprequest.rb', line 113

def HEADERS_RECEIVED
    HEADERS_RECEIVED
end

#LOADINGObject



117
118
119
# File 'lib/noms/command/xmlhttprequest.rb', line 117

def LOADING
    LOADING
end

#onreadystatechangeObject



85
86
87
# File 'lib/noms/command/xmlhttprequest.rb', line 85

def onreadystatechange
    @onreadystatechange
end

#onreadystatechange=(callback) ⇒ Object



89
90
91
# File 'lib/noms/command/xmlhttprequest.rb', line 89

def onreadystatechange=(callback)
    @onreadystatechange = callback
end

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



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

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



109
110
111
# File 'lib/noms/command/xmlhttprequest.rb', line 109

def OPENED
    OPENED
end

#readyStateObject



93
94
95
# File 'lib/noms/command/xmlhttprequest.rb', line 93

def readyState
    @readyState
end

#readyState=(value) ⇒ Object



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

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)


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

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.



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

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



105
106
107
# File 'lib/noms/command/xmlhttprequest.rb', line 105

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

#statusObject



159
160
161
# File 'lib/noms/command/xmlhttprequest.rb', line 159

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

#statusTextObject



163
164
165
# File 'lib/noms/command/xmlhttprequest.rb', line 163

def statusText
    @response.statusText unless @response.nil?
end

#useragentObject



57
58
59
# File 'lib/noms/command/xmlhttprequest.rb', line 57

def useragent
    @ua
end