simple-http 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b4588e9e8c027217ca27a55496429b8c17b1bb49
4
+ data.tar.gz: be034b0620f7358c4e3d806ca4a0ab8b7c16e77d
5
+ SHA512:
6
+ metadata.gz: 25d97c4098cdd837a45c7cf4b6377d943cd29fde1a51db79b7f52f9457658127a411f910b618d23bb42c368f1dc3ef49c47219f929b72ddd96df552a3639ac27
7
+ data.tar.gz: f8044c467a6f30109a21cfa2d86d5b4c9fadeec52f930375502a11a7dfa0f2a74ae932a669417e7c205e7610feb77a01cbf091e7674296dfe6fba64bf8788df9
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # simple-http
2
+
3
+ A really simple HTTP client
4
+
5
+ - GET, POST, PUT, DELETE
6
+
7
+ require "simple/http"
8
+ http_client = Simple::HTTP.new
9
+ http_client.get "http://google.com" # returns a string
10
+
11
+ - Exceptions on errors: because, after all, when you consume a HTTP endpoint and don't
12
+ get a success (20x), then this is an error. Handle it!
13
+
14
+ require "simple/http"
15
+ http_client = Simple::HTTP.new
16
+ begin
17
+ http_client.get "http://google.com" # returns a string
18
+ rescue Simple::HTTP::Error
19
+ STDERR.puts "Ooops! #{$!}"
20
+ end
21
+
22
+ - Caching
23
+
24
+ require "simple/http"
25
+ http_client = Simple::HTTP.new
26
+
27
+ require "active_support/cache"
28
+ require "active_support/cache/file_store"
29
+ http_client.cache = ActiveSupport::Cache::FileStore.new("var/cache")
30
+ http_client.get "http://google.com" # returns a, potentially, cached string
31
+
32
+ - Automatic de/encoding of JSON payloads
33
+
34
+ - Does not requires anything except core ruby classes.
@@ -0,0 +1,33 @@
1
+ # This file is part of the simple-http ruby gem.
2
+ #
3
+ # Copyright (c) 2011 - 2015 @radiospiel
4
+ # Distributed under the terms of the modified BSD license, see LICENSE.BSD
5
+
6
+ module Simple; end
7
+ class Simple::HTTP; end
8
+
9
+ class Simple::HTTP::Error < RuntimeError
10
+ attr :method, :request, :response
11
+
12
+ def initialize(method, request, response)
13
+ @method, @request, @response = method, request, response
14
+ end
15
+
16
+ def code
17
+ response.code.to_i
18
+ end
19
+
20
+ def message
21
+ message = "#{method} #{response.uri} ##{response.code} #{response.message}"
22
+ if response.is_a?(Net::HTTPRedirection)
23
+ message += " To #{response["Location"]}"
24
+ end
25
+ message
26
+ end
27
+ end
28
+
29
+ class Simple::HTTP::TooManyRedirections < Simple::HTTP::Error
30
+ def message
31
+ "Too many redirections; after\n#{super}"
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ # This file is part of the simple-http ruby gem.
2
+ #
3
+ # Copyright (c) 2011 - 2015 @radiospiel
4
+ # Distributed under the terms of the modified BSD license, see LICENSE.BSD
5
+
6
+ require "net/http"
7
+
8
+ class Net::HTTPResponse
9
+ private
10
+
11
+ #
12
+ # The "max-age" value, in seconds, from the Cache-Control header.
13
+ def max_age
14
+ return unless cache_control = header["Cache-Control"]
15
+ cache_control.split(/, /).each do |part|
16
+ next unless part =~ /max-age=(\d+)/
17
+ return Integer($1)
18
+ end
19
+ nil
20
+ end
21
+
22
+ public
23
+
24
+ #
25
+ # returns expiration information, in seconds from now.
26
+ def expires_in
27
+ expires_in = max_age
28
+ if !expires_in && expires = header["Expires"]
29
+ expires_in = Time.parse(expires) - Time.now
30
+ end
31
+
32
+ return expires_in if expires_in && expires_in > 0
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ # This file is part of the simple-http ruby gem.
2
+ #
3
+ # Copyright (c) 2011 - 2015 @radiospiel
4
+ # Distributed under the terms of the modified BSD license, see LICENSE.BSD
5
+
6
+ require "net/http"
7
+
8
+ class Net::HTTPResponse
9
+ #
10
+ # evaluate and potentially parse response
11
+ def result
12
+ case response.content_type
13
+ when "application/json"
14
+ JSON.parse(body) unless body.empty?
15
+ else
16
+ body_string
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ #
23
+ # returns a body. The resulting string is encoded in ASCII-8BIT, if the
24
+ # content type is binary, and encoded in UTF8 otherwise.
25
+ def body_string
26
+ default_encoding = content_is_binary? ? "ASCII-8BIT" : "UTF-8"
27
+
28
+ body = self.body
29
+ if charset = type_params["charset"]
30
+ body = body.force_encoding(charset)
31
+ end
32
+ body.encode(default_encoding)
33
+ end
34
+
35
+ def content_is_binary?
36
+ case content_type
37
+ when /^image/ then true
38
+ else false
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,9 @@
1
+ # This file is part of the simple-http ruby gem.
2
+ #
3
+ # Copyright (c) 2011 - 2015 @radiospiel
4
+ # Distributed under the terms of the modified BSD license, see LICENSE.BSD
5
+
6
+ module Simple; end
7
+ class Simple::HTTP
8
+ VERSION = "0.1.0"
9
+ end
@@ -0,0 +1,166 @@
1
+ # Author:: radiospiel (mailto:eno@radiospiel.org)
2
+ # Copyright:: Copyright (c) 2011-2015 radiospiel
3
+ # License:: Distributes under the terms of the Modified BSD License, see LICENSE.BSD for details.
4
+
5
+ require "net/http"
6
+ require "json"
7
+
8
+ module Simple; end
9
+ class Simple::HTTP; end
10
+
11
+ require_relative "http/version"
12
+ require_relative "http/result"
13
+ require_relative "http/expires_in"
14
+ require_relative "http/errors"
15
+
16
+ #
17
+ # A very simple, Net::HTTP-based HTTP client.
18
+ #
19
+ # Has some support for transferring JSON data: all data in PUT and POST
20
+ # requests are jsonized, and all data in responses are parsed as JSON if
21
+ # the Content-Type header is set to "application/json".
22
+ class Simple::HTTP
23
+
24
+ #
25
+ # The base URL: when set, all requests that do not start with http: or
26
+ # https: are done relative to this base URL.
27
+ attr :base_url, true
28
+
29
+ #
30
+ # When set (default), redirections are followed. Note: When
31
+ # follows_redirections is not set, a HTTP redirection would raise an
32
+ # error - which is probably only useful when testing an interface.
33
+ attr :follows_redirections, true
34
+
35
+ #
36
+ # When set, appends this to all request URLs
37
+ attr :default_params, true
38
+
39
+ def initialize
40
+ self.follows_redirections = true
41
+ end
42
+
43
+ def get(url, headers = {}); http :GET, url, nil, headers; end
44
+ def post(url, body = nil, headers = {}); http :POST, url, body, headers; end
45
+ def put(url, body = nil, headers = {}); http :PUT, url, body, headers; end
46
+ def delete(url, headers = {}); http :DELETE, url, nil, headers; end
47
+
48
+ #
49
+ # -- Caching ----------------------------------------------------------------
50
+
51
+ # When set, and a response is cacheable (as it returns a valid expires_in
52
+ # value), the cache object is used to cache responses.
53
+ attr :cache, true
54
+
55
+ #
56
+ # when does the response expire? By default, calculates expiration based
57
+ # on response headers. Override as needed.
58
+ def expires_in(response)
59
+ response.expires_in
60
+ end
61
+
62
+ private
63
+
64
+ # -- HTTP request -----------------------------------------------------------
65
+
66
+ def http(method, url, body = nil, headers)
67
+ #
68
+ # normalize url; i.e. prepend base_url if the url itself is incomplete.
69
+ unless url =~ /^(http|https):/
70
+ url = File.join(base_url, url)
71
+ end
72
+
73
+ # append default_params, if set
74
+ if default_params
75
+ url.concat(url.include?("?") ? "&" : "?")
76
+ url.concat default_params
77
+ end
78
+
79
+ # "raw" execute request
80
+ http_ method, url, body, headers
81
+ end
82
+
83
+ #
84
+ # do a HTTP request, return its response or, when not successful,
85
+ # raise an error.
86
+ def http_(method, url, body, headers, max_redirections = 10)
87
+ if method == :GET && cache && result = cache.read(url)
88
+ return result
89
+ end
90
+
91
+ uri = URI.parse(url)
92
+ http = Net::HTTP.new(uri.host, uri.port)
93
+
94
+ #
95
+ # build request
96
+ request = build_request method, uri, body, headers
97
+
98
+ #
99
+ # execute request
100
+ response = http.request(request)
101
+
102
+ #
103
+ # Most of the times Net::HTTP#request returns a response with the :uri
104
+ # attribute set, but sometimes not. We make sure that the uri is set
105
+ # everytime.
106
+ response.uri = uri
107
+
108
+ #
109
+ # handle successful responses.
110
+ if response.is_a?(Net::HTTPSuccess)
111
+ result = response.result
112
+ if cache && method == :GET && expires_in = self.expires_in(response)
113
+ cache.write(url, result, expires_in: expires_in)
114
+ end
115
+
116
+ return result
117
+ end
118
+
119
+ #
120
+ # handle redirections.
121
+ if response.is_a?(Net::HTTPRedirection) && self.follows_redirections
122
+ if max_redirections <= 0
123
+ raise TooManyRedirections.new(method, request, respons)
124
+ end
125
+
126
+ return http_(:GET, response["Location"], nil, {}, max_redirections - 1)
127
+ end
128
+
129
+ #
130
+ # raise an error in any other case.
131
+ raise Error.new(method, request, response)
132
+ end
133
+
134
+ private
135
+
136
+ REQUEST_CLASSES = {
137
+ :GET => Net::HTTP::Get,
138
+ :POST => Net::HTTP::Post,
139
+ :PUT => Net::HTTP::Put,
140
+ :DELETE => Net::HTTP::Delete
141
+ }.freeze #:nodoc:
142
+
143
+ #
144
+ # build a HTTP request object.
145
+ def build_request(method, uri, body, headers)
146
+ klass = REQUEST_CLASSES.fetch(method)
147
+ request = klass.new(uri.request_uri)
148
+
149
+ # set request headers
150
+ # unless headers && !headers.empty?
151
+ # # TODO: set headers
152
+ # # set_request_headers request, headers
153
+ # end
154
+
155
+ # set request body
156
+ if request.request_body_permitted? && body
157
+ request.content_type = "application/json"
158
+ if body.is_a?(Hash) || body.is_a?(Array)
159
+ body = JSON.generate(body)
160
+ end
161
+ request.body = body
162
+ end
163
+
164
+ request
165
+ end
166
+ end
@@ -0,0 +1,14 @@
1
+ # Author:: radiospiel (mailto:eno@radiospiel.org)
2
+ # Copyright:: Copyright (c) 2011-2015 radiospiel
3
+ # License:: Distributes under the terms of the Modified BSD License, see LICENSE.BSD for details.
4
+
5
+ require_relative 'test_helper'
6
+
7
+ class SimpleHttpTest < Test::Unit::TestCase
8
+ HTTP = Simple::HTTP.new
9
+
10
+ def test_loaded
11
+ google = HTTP.get "http://google.com"
12
+ assert_match(/doctype/, google)
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ # require 'simplecov'
5
+ require 'test/unit'
6
+
7
+ # SimpleCov.start do
8
+ # add_filter "test/*.rb"
9
+ # end
10
+
11
+ require "simple/http"
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple-http
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - radiospiel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-16 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Simple code for simple HTTP requests
14
+ email: eno@radiospiel.org
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - README.md
20
+ - lib/simple/http.rb
21
+ - lib/simple/http/errors.rb
22
+ - lib/simple/http/expires_in.rb
23
+ - lib/simple/http/result.rb
24
+ - lib/simple/http/version.rb
25
+ - test/simple_http_test.rb
26
+ - test/test_helper.rb
27
+ homepage: http://github.com/radiospiel/simple-http
28
+ licenses: []
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 2.4.6
47
+ signing_key:
48
+ specification_version: 4
49
+ summary: Simple code for simple HTTP requests
50
+ test_files: []