github_api 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9312a6593c2f32bcc8b408beca9259a0747a70be
4
- data.tar.gz: 9d5e113c5690642ef9fb0d9269ccc42d54421bd1
3
+ metadata.gz: 26afc4d14a19b64a2afdb606f617a8adb4feca39
4
+ data.tar.gz: d8dc7404e573e3795fc614f419161b5a741fca79
5
5
  SHA512:
6
- metadata.gz: 15f1895fc1e726e678f67298e0489c681da59b2e0737c4baba47baa74dfe998ac8d76e0bd02f6f9bdf304fb8043694f70c15e77b670427d1cafa2cb2db4c35cb
7
- data.tar.gz: e4e76f0e15c2ad51905fca1d8072072c689f8a80758e3f86b26bf8004e66fb58bea975393345dc8852d9bcfca495ae2bd195261f075b6cbbd5188087f2124c72
6
+ metadata.gz: e9aee22020a61cb8f71d7ef5906d30a06781e94106ccdc609fc6587114b051f3cbab67d70c3d9ed0bc9b2a7a4d02b63755833aa63305f468f6a081a4378e2b7d
7
+ data.tar.gz: ae1f3c5346bb2f6c231c5a2e950ee5ed966c1a3cff3d9f2ab8d4401a27e746cbc701a0149b8f681d1dca040d905d4db789b3f9610ddb8b33ecde5715f89d7113
data/README.md CHANGED
@@ -719,4 +719,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/piotrm
719
719
 
720
720
  ## Copyright
721
721
 
722
- Copyright (c) 2011-2016 Piotr Murach. See LICENSE.txt for further details.
722
+ Copyright (c) 2011-2017 Piotr Murach. See LICENSE.txt for further details.
@@ -79,6 +79,16 @@ module Github
79
79
  end
80
80
  end
81
81
 
82
+ # Disable following redirects inside a block
83
+ #
84
+ # @api public
85
+ def disable_redirects
86
+ self.follow_redirects = false
87
+ yield
88
+ ensure
89
+ self.follow_redirects = true
90
+ end
91
+
82
92
  # List of before callbacks
83
93
  #
84
94
  # @api public
@@ -235,7 +235,10 @@ module Github
235
235
  archive_format = params.delete('archive_format') || 'tarball'
236
236
  ref = params.delete('ref') || 'master'
237
237
 
238
- get_request("/repos/#{arguments.user}/#{arguments.repo}/#{archive_format}/#{ref}", params)
238
+ disable_redirects do
239
+ response = get_request("/repos/#{arguments.user}/#{arguments.repo}/#{archive_format}/#{ref}", params)
240
+ response.headers.location
241
+ end
239
242
  end
240
243
  end # Client::Repos::Contents
241
244
  end # Github
@@ -12,6 +12,8 @@ module Github
12
12
  # By default, don't traverse the page links
13
13
  property :auto_pagination, default: false
14
14
 
15
+ property :follow_redirects, default: true
16
+
15
17
  # Basic authentication
16
18
  property :basic_auth
17
19
 
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Github
4
+ class Mash < ::Hashie::Mash
5
+ disable_warnings
6
+ end
7
+ end
@@ -6,6 +6,7 @@ require 'github_api/response/jsonize'
6
6
  require 'github_api/response/atom_parser'
7
7
  require 'github_api/response/raise_error'
8
8
  require 'github_api/response/header'
9
+ require 'github_api/response/follow_redirects'
9
10
 
10
11
  module Github
11
12
  class Middleware
@@ -18,6 +19,7 @@ module Github
18
19
  builder.use Github::Request::OAuth2, api.oauth_token if api.oauth_token?
19
20
  builder.use Github::Request::BasicAuth, api.authentication if api.basic_authed?
20
21
 
22
+ builder.use Github::Response::FollowRedirects if api.follow_redirects
21
23
  builder.use Faraday::Response::Logger if ENV['DEBUG']
22
24
  unless options[:raw]
23
25
  builder.use Github::Response::Mashify
@@ -0,0 +1,140 @@
1
+ require 'faraday'
2
+ require 'set'
3
+
4
+ # First saw on octokit, then copied from lostisland/faraday_middleware
5
+ # and adapted for this library.
6
+ #
7
+ # faraday_middleware/lib/faraday_middleware/response/follow_redirects.rb
8
+
9
+ module Github
10
+ # Public: Exception thrown when the maximum amount of requests is exceeded.
11
+ class RedirectLimitReached < Faraday::Error::ClientError
12
+ attr_reader :response
13
+
14
+ def initialize(response)
15
+ super "too many redirects; last one to: #{response['location']}"
16
+ @response = response
17
+ end
18
+ end
19
+
20
+ # Public: Follow HTTP 301, 302, 303, 307, and 308 redirects.
21
+ #
22
+ # For HTTP 301, 302, and 303, the original GET, POST, PUT, DELETE, or PATCH
23
+ # request gets converted into a GET. With `:standards_compliant => true`,
24
+ # however, the HTTP method after 301/302 remains unchanged. This allows you
25
+ # to opt into HTTP/1.1 compliance and act unlike the major web browsers.
26
+ #
27
+ # This middleware currently only works with synchronous requests; i.e. it
28
+ # doesn't support parallelism.
29
+ #
30
+ # If you wish to persist cookies across redirects, you could use
31
+ # the faraday-cookie_jar gem:
32
+ #
33
+ # Faraday.new(:url => url) do |faraday|
34
+ # faraday.use FaradayMiddleware::FollowRedirects
35
+ # faraday.use :cookie_jar
36
+ # faraday.adapter Faraday.default_adapter
37
+ # end
38
+
39
+ class Response::FollowRedirects < Faraday::Middleware
40
+ # HTTP methods for which 30x redirects can be followed
41
+ ALLOWED_METHODS = Set.new [:head, :options, :get, :post, :put, :patch, :delete]
42
+ # HTTP redirect status codes that this middleware implements
43
+ REDIRECT_CODES = Set.new [301, 302, 303, 307, 308]
44
+ # Keys in env hash which will get cleared between requests
45
+ ENV_TO_CLEAR = Set.new [:status, :response, :response_headers]
46
+
47
+ # Default value for max redirects followed
48
+ FOLLOW_LIMIT = 3
49
+
50
+ # Regex that matches characters that need to be escaped in URLs, sans
51
+ # the "%" character which we assume already represents an escaped sequence.
52
+ URI_UNSAFE = /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]%]/
53
+
54
+ # Public: Initialize the middleware.
55
+ #
56
+ # options - An options Hash (default: {}):
57
+ # :limit - A Numeric redirect limit (default: 3)
58
+ # :standards_compliant - A Boolean indicating whether to respect
59
+ # the HTTP spec when following 301/302
60
+ # (default: false)
61
+ # :callback - A callable that will be called on redirects
62
+ # with the old and new envs
63
+ def initialize(app, options = {})
64
+ super(app)
65
+ @options = options
66
+
67
+ @convert_to_get = Set.new [303]
68
+ @convert_to_get << 301 << 302 unless standards_compliant?
69
+ end
70
+
71
+ def call(env)
72
+ perform_with_redirection(env, follow_limit)
73
+ end
74
+
75
+ private
76
+
77
+ def convert_to_get?(response)
78
+ ![:head, :options].include?(response.env[:method]) &&
79
+ @convert_to_get.include?(response.status)
80
+ end
81
+
82
+ def perform_with_redirection(env, follows)
83
+ request_body = env[:body]
84
+ response = @app.call(env)
85
+
86
+ response.on_complete do |response_env|
87
+ if follow_redirect?(response_env, response)
88
+ raise RedirectLimitReached, response if follows.zero?
89
+ new_request_env = update_env(response_env.dup, request_body, response)
90
+ callback.call(response_env, new_request_env) if callback
91
+ response = perform_with_redirection(new_request_env, follows - 1)
92
+ end
93
+ end
94
+ response
95
+ end
96
+
97
+ def update_env(env, request_body, response)
98
+ env[:url] += safe_escape(response['location'])
99
+
100
+ if convert_to_get?(response)
101
+ env[:method] = :get
102
+ env[:body] = nil
103
+ else
104
+ env[:body] = request_body
105
+ end
106
+
107
+ ENV_TO_CLEAR.each {|key| env.delete key }
108
+
109
+ env
110
+ end
111
+
112
+ def follow_redirect?(env, response)
113
+ ALLOWED_METHODS.include? env[:method] and
114
+ REDIRECT_CODES.include? response.status
115
+ end
116
+
117
+ def follow_limit
118
+ @options.fetch(:limit, FOLLOW_LIMIT)
119
+ end
120
+
121
+ def standards_compliant?
122
+ @options.fetch(:standards_compliant, false)
123
+ end
124
+
125
+ def callback
126
+ @options[:callback]
127
+ end
128
+
129
+ # Internal: escapes unsafe characters from an URL which might be a path
130
+ # component only or a fully qualified URI so that it can be joined onto an
131
+ # URI:HTTP using the `+` operator. Doesn't escape "%" characters so to not
132
+ # risk double-escaping.
133
+ def safe_escape(uri)
134
+ uri = uri.split('#')[0] # we want to remove the fragment if present
135
+ uri.to_s.gsub(URI_UNSAFE) { |match|
136
+ '%' + match.unpack('H2' * match.bytesize).join('%').upcase
137
+ }
138
+ end
139
+ end
140
+ end
@@ -13,6 +13,10 @@ module Github
13
13
  !!env
14
14
  end
15
15
 
16
+ def [](property)
17
+ loaded? ? env[:response_headers][property] : nil
18
+ end
19
+
16
20
  def oauth_scopes
17
21
  loaded? ? env[:response_headers][OAUTH_SCOPES] : nil
18
22
  end
@@ -76,7 +80,6 @@ module Github
76
80
  def body
77
81
  loaded? ? env[:body] : nil
78
82
  end
79
-
80
83
  end # Header
81
84
  end # Response
82
85
  end # Github
@@ -2,13 +2,12 @@
2
2
 
3
3
  require 'faraday'
4
4
  require 'hashie'
5
+ require 'github_api/mash'
5
6
 
6
7
  module Github
7
8
  class Response::Mashify < Response
8
- dependency 'hashie/mash'
9
-
10
9
  define_parser do |body|
11
- ::Hashie::Mash.new body
10
+ ::Github::Mash.new body
12
11
  end
13
12
 
14
13
  def parse(body)
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Github
4
- VERSION = "0.15.0"
4
+ VERSION = "0.16.0"
5
5
  end # Github
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: github_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Murach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-25 00:00:00.000000000 Z
11
+ date: 2017-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -228,6 +228,7 @@ files:
228
228
  - lib/github_api/error/client_error.rb
229
229
  - lib/github_api/error/service_error.rb
230
230
  - lib/github_api/ext/faraday.rb
231
+ - lib/github_api/mash.rb
231
232
  - lib/github_api/middleware.rb
232
233
  - lib/github_api/mime_type.rb
233
234
  - lib/github_api/normalizer.rb
@@ -248,6 +249,7 @@ files:
248
249
  - lib/github_api/resource.rb
249
250
  - lib/github_api/response.rb
250
251
  - lib/github_api/response/atom_parser.rb
252
+ - lib/github_api/response/follow_redirects.rb
251
253
  - lib/github_api/response/header.rb
252
254
  - lib/github_api/response/jsonize.rb
253
255
  - lib/github_api/response/mashify.rb