Module: AppEngine::URLFetch

Defined in:
lib/appengine-apis/urlfetch.rb

Overview

The URLFetch Service provides a way for user code to execute HTTP requests to external URLs.

Chunked and hanging requests are not supported, and all content will be returned in a single block.

URLFetch::HTTP also provides a drop-in replacement for Net::HTTP. To replace the standard implementation throughout your app you can do:

require 'appengine-apis/urlfetch'
Net::HTTP = AppEngine::URLFetch::HTTP

Defined Under Namespace

Classes: DownloadError, InvalidURLError, ResponseTooLargeError

Constant Summary collapse

HTTP =

Deprecated alias for Net::HTTP, for backwards compatibility.

Net::HTTP

Class Method Summary collapse

Class Method Details

.build_urlfetch_request(url, options) ⇒ Object

:nodoc:



101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/appengine-apis/urlfetch.rb', line 101

def build_urlfetch_request(url, options)  # :nodoc:
  method = options.delete(:method) || 'GET'
  payload = options.delete(:payload)
  headers = options.delete(:headers) || {}
  truncate = options.delete(:allow_truncated)
  follow_redirects = options.delete(:follow_redirects)
  deadline = options.delete(:deadline)
  
  follow_redirects = true if follow_redirects.nil?
  
  unless options.empty?
    raise ArgumentError, "Unsupported options #{options.inspect}."
  end
  
  begin
    method = HTTPMethod.value_of(method.to_s.upcase)
  rescue java.lang.IllegalArgumentException
    raise ArgumentError, "Invalid method #{method.inspect}."
  end
  
  if truncate
    options = FetchOptions::Builder.allow_truncate
  else
    options = FetchOptions::Builder.disallow_truncate
  end
  if follow_redirects
    options.follow_redirects
  else
    options.do_not_follow_redirects
  end
  
  options.set_deadline(deadline) if deadline
  
  url = java.net.URL.new(url) unless url.java_kind_of? java.net.URL
  request = HTTPRequest.new(url, method, options)
  
  iterator = if headers.respond_to?(:canonical_each)
    :canonical_each
  else
    :each
  end

  if payload
    if headers["Content-Length"].to_i != payload.size
      headers["Content-Length"] = payload.size.to_s
    end
  end
  
  headers.send(iterator) do |name, value|
    request.set_header(HTTPHeader.new(name, value))
  end
  
  if payload
    request.set_payload(payload.to_java_bytes)
  end
  
  return request
end

.convert_urlfetch_body(java_response) ⇒ Object

:nodoc:



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/appengine-apis/urlfetch.rb', line 160

def convert_urlfetch_body(java_response)  # :nodoc:
  status = java_response.response_code.to_s
  klass = Net::HTTPResponse.send(:response_class, status)
  mesg = klass.name
  mesg = mesg[4, mesg.size]
  response = klass.new(nil, status, mesg)
  java_response.headers.each do |header|
    response.add_field(header.name, header.value)
  end
  body = if java_response.content
    String.from_java_bytes(java_response.content)
  else
    nil
  end
  response.urlfetch_body = body
  return response
end

.fetch(url, options = {}) ⇒ Object

Fetches the given HTTP URL, blocking until the result is returned.

Supported options:

:method

GET, POST, HEAD, PUT, or DELETE

:payload

POST or PUT payload (implies method is not GET, HEAD, or DELETE)

:headers

HTTP headers to send with the request. May be a Hash or Net::HTTPHeaders.

:allow_truncated

if true, truncate large responses and return them without error. otherwise, ResponseTooLargeError will be thrown when a response is truncated.

:follow_redirects

if true (the default), redirects are transparently followed and the response (if less than 5 redirects) contains the final destination’s payload and the response status is 200. You lose, however, the redirect chaininformation. If false, you see the HTTP response yourself, including the ‘Location’ header, and redirects are not followed.

:deadline

Deadline, in seconds, for the request.

Returns a Net::HTTPResponse.

Throws:

  • InvalidURLError if the provided url is malformed.

  • DownloadError if the remote service could not be contacted or the URL could not be fetched.

  • ResponseTooLargeError if response truncation has been disabled and the response is too large. Some responses are too large to even retrieve from the remote server, and in these cases the exception is thrown even if response truncation is enabled.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/appengine-apis/urlfetch.rb', line 85

def fetch(url, options={})
  request = build_urlfetch_request(url, options)
  begin
    java_response = urlfetch_service.fetch(request)
    return convert_urlfetch_body(java_response)
  rescue java.lang.IllegalArgumentException => ex
    raise ArgumentError, ex.message
  rescue java.net.MalformedURLException => ex
    raise InvalidURLError, ex.message
  rescue java.io.IOException => ex
    raise DownloadError, ex.message
  rescue ResponseTooLargeException => ex
    raise ResponseTooLargeError, ex.message
  end
end

.urlfetch_serviceObject

:nodoc:



178
179
180
# File 'lib/appengine-apis/urlfetch.rb', line 178

def urlfetch_service  # :nodoc:
  @service ||= URLFetchServiceFactory.getURLFetchService
end

.urlfetch_service=(service) ⇒ Object

:nodoc:



182
183
184
# File 'lib/appengine-apis/urlfetch.rb', line 182

def urlfetch_service=(service)  # :nodoc:
  @service = service
end