github_api 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
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