Class: Hyperloop::HTTP

Inherits:
Object
  • Object
show all
Defined in:
lib/hyper-operation/http.rb

Overview

HTTP is used to perform a `XMLHttpRequest` in ruby. It is a simple wrapper around `XMLHttpRequest`

# Making requests

To create a simple request, HTTP exposes class level methods to specify the HTTP action you wish to perform. Each action accepts the url for the request, as well as optional arguments passed as a hash:

HTTP.get("/users/1.json")
HTTP.post("/users", payload: data)

The supported `HTTP` actions are:

# Handling responses

Responses can be handled using either a simple block callback, or using a Promise returned by the request.

## Using a block

All HTTP action methods accept a block which can be used as a simple handler for the request. The block will be called for both successful as well as unsuccessful requests.

HTTP.get("/users/1") do |request|
  puts "the request has completed!"
end

This `request` object will simply be the instance of the HTTP class which wraps the native `XMLHttpRequest`. #ok? can be used to quickly determine if the request was successful.

HTTP.get("/users/1") do |request|
  if request.ok?
    puts "request was success"
  else
    puts "something went wrong with request"
  end
end

The HTTP instance will always be the only object passed to the block.

## Using a Promise

If no block is given to one of the action methods, then a Promise is returned instead. See the standard library for more information on Promises.

HTTP.get("/users/1").then do |req|
  puts "response ok!"
end.fail do |req|
  puts "response was not ok"
end

When using a Promise, both success and failure handlers will be passed the HTTP instance.

# Accessing Response Data

All data returned from an HTTP request can be accessed via the HTTP object passed into the block or promise handlers.

  • #ok? - returns `true` or `false`, if request was a success (or not).

  • #body - returns the raw text response of the request

  • #status_code - returns the raw HTTP status code as integer

  • #json - tries to convert the body response into a JSON object

Constant Summary collapse

ACTIONS =

All valid Hyperloop::HTTP action methods this class accepts.

See Also:

%w[get post put delete patch head]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeHTTP

Returns a new instance of HTTP.


136
137
138
# File 'lib/hyper-operation/http.rb', line 136

def initialize
  @ok = true
end

Instance Attribute Details

#bodyObject (readonly)

Returns the value of attribute body


134
135
136
# File 'lib/hyper-operation/http.rb', line 134

def body
  @body
end

#error_messageObject (readonly)

Returns the value of attribute error_message


134
135
136
# File 'lib/hyper-operation/http.rb', line 134

def error_message
  @error_message
end

#methodObject (readonly)

Returns the value of attribute method


134
135
136
# File 'lib/hyper-operation/http.rb', line 134

def method
  @method
end

#status_codeObject (readonly)

Returns the value of attribute status_code


134
135
136
# File 'lib/hyper-operation/http.rb', line 134

def status_code
  @status_code
end

#urlObject (readonly)

Returns the value of attribute url


134
135
136
# File 'lib/hyper-operation/http.rb', line 134

def url
  @url
end

#xhrObject (readonly)

Returns the value of attribute xhr


134
135
136
# File 'lib/hyper-operation/http.rb', line 134

def xhr
  @xhr
end

Class Method Details

.active?Boolean

Returns:

  • (Boolean)

140
141
142
143
144
145
146
147
148
# File 'lib/hyper-operation/http.rb', line 140

def self.active?
  jquery_active_requests = 0
  %x{
    if (typeof jQuery !== "undefined" && typeof jQuery.active !== "undefined" && jQuery.active !== null) {
      jquery_active_requests = jQuery.active;
    }
  }
  (jquery_active_requests + @active_requests) > 0
end

.active_requestsObject


150
151
152
153
# File 'lib/hyper-operation/http.rb', line 150

def self.active_requests
  @active_requests ||= 0
  @active_requests
end

.decr_active_requestsObject


160
161
162
163
164
165
166
167
# File 'lib/hyper-operation/http.rb', line 160

def self.decr_active_requests
  @active_requests ||= 0
  @active_requests -= 1
  if @active_requests < 0
    `console.log("Ooops, Hyperloop::HTTP active_requests out of sync!")`
    @active_requests = 0
  end
end

.delete(url, options = {}, &block) ⇒ Object


# File 'lib/hyper-operation/http.rb', line 118

.get(url, options = {}) {|self| ... } ⇒ Promise?

Create a Hyperloop::HTTP `get` request.

Examples:

HTTP.get("/foo") do |req|
  puts "got data: #{req.data}"
end

Parameters:

  • url (String)

    url for request

  • options (Hash) (defaults to: {})

    any request options

Yields:

  • (self)

    optional block to handle response

Returns:

  • (Promise, nil)

    optionally returns a promise


# File 'lib/hyper-operation/http.rb', line 86

.head(url, options = {}, &block) ⇒ Object


124
125
126
127
128
129
130
131
132
# File 'lib/hyper-operation/http.rb', line 124

ACTIONS.each do |action|
  define_singleton_method(action) do |url, options = {}, &block|
    new.send(action, url, options, block)
  end

  define_method(action) do |url, options = {}, &block|
    send(action, url, options, block)
  end
end

.incr_active_requestsObject


155
156
157
158
# File 'lib/hyper-operation/http.rb', line 155

def self.incr_active_requests
  @active_requests ||= 0
  @active_requests += 1
end

.patch(url, options = {}, &block) ⇒ Object


# File 'lib/hyper-operation/http.rb', line 120

.post(url, options = {}) {|self| ... } ⇒ Promise?

Create a Hyperloop::HTTP `post` request. Post data can be supplied using the `payload` options. Usually this will be a hash which will get serialized into a native javascript object.

Examples:

HTTP.post("/bar", payload: data) do |req|
  puts "got response"
end

Parameters:

  • url (String)

    url for request

  • options (Hash) (defaults to: {})

    optional request options

Yields:

  • (self)

    optional block to yield for response

Returns:


# File 'lib/hyper-operation/http.rb', line 100

.put(url, options = {}, &block) ⇒ Object


# File 'lib/hyper-operation/http.rb', line 116

Instance Method Details

#get_header(key) ⇒ String?

Returns the value of the specified response header.

Parameters:

  • key (String)

    name of the header to get

Returns:

  • (String)

    value of the header

  • (nil)

    if the header key was not in the response


256
257
258
259
260
261
# File 'lib/hyper-operation/http.rb', line 256

def get_header(key)
  %x{
    var value = #@xhr.getResponseHeader(#{key});
    return (value === null) ? nil : value;
  }
end

#inspectObject


263
264
265
# File 'lib/hyper-operation/http.rb', line 263

def inspect
  "#<HTTP @url=#{@url} @method=#{@method}>"
end

#jsonHash, Array

Parses the http response body through json. If the response is not valid JSON then an error will very likely be thrown.

Examples:

Getting JSON content

HTTP.get("api.json") do |response|
  puts response.json
end

# => {"key" => 1, "bar" => 2, ... }

Returns:

  • (Hash, Array)

    returns the parsed json


232
233
234
# File 'lib/hyper-operation/http.rb', line 232

def json
  @json ||= JSON.parse(@body)
end

#ok?true, false

Returns true if the request succeeded, false otherwise.

Examples:

HTTP.get("/some/url") do |response|
  if response.ok?
    alert "Yay!"
  else
    alert "Aww :("
  end

Returns:

  • (true, false)

    true if request was successful


247
248
249
# File 'lib/hyper-operation/http.rb', line 247

def ok?
  @ok
end

#send(method, url, options, block) ⇒ Object


169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/hyper-operation/http.rb', line 169

def send(method, url, options, block)
  @method   = method
  @url      = url
  @payload  = options.delete :payload
  @handler  = block
  %x{
    var payload_to_send = null;
    var content_type = null;
    if (typeof(this.payload) === 'string') {
      payload_to_send = this.payload;
    }
    else if (this.payload != nil) {
      payload_to_send = this.payload.$to_json();
      content_type = 'application/json';
    }

    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function() {
      if(xhr.readyState === XMLHttpRequest.DONE) {
        self.$class().$decr_active_requests();
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
          return #{succeed(`xhr.responseText`, `xhr.status`, `xhr`)};
        } else {
          return #{fail(`xhr`, `xhr.status`, `xhr.statusText`)};
        }
      }
    }
    xhr.open(this.method.toUpperCase(), this.url);
    if (payload_to_send !== null && content_type !== null) {
      xhr.setRequestHeader("Content-Type", content_type);
    }
    if (options["$has_key?"]("headers")) {
      var headers = options['$[]']("headers");
      var keys = headers.$keys();
      var keys_length = keys.length;
      for (var i=0; i < keys_length; i++) {
        xhr.setRequestHeader( keys[i], headers['$[]'](keys[i]) );
      }
    }
    if (payload_to_send !== null) {
      self.$class().$incr_active_requests();
      xhr.send(payload_to_send);
    } else {
      self.$class().$incr_active_requests();
      xhr.send();
    }
  }

  @handler ? self : promise
end