Skip to content

Commit

Permalink
Maintain methods across redirects
Browse files Browse the repository at this point in the history
If HTTPS is enabled on a server, but the client uses plain HTTP
Gitlab generates HTTP 301 redirect. By default HTTParty will
follow with GET request regardless of the original method and
any PUT/POST will silently fail to update the target. Fix by
enabling HTTParty::maintain_method_across_redirects.
  • Loading branch information
ikravets committed Oct 19, 2021
1 parent 1e8c635 commit d83f809
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/gitlab/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module Gitlab
class Request
include HTTParty
format :json
maintain_method_across_redirects true
headers 'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'
parser(proc { |body, _| parse(body) })

Expand Down
69 changes: 69 additions & 0 deletions spec/gitlab/request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,73 @@
}.merge(described_class.headers))).to have_been_made.times(3)
end
end

describe 'redirection' do
it 'redirect GET' do
http_endpoint = 'http://example.com/api/v4'
https_endpoint = 'https://example.com:443/api/v4'
http_path = "#{http_endpoint}/version"
https_path = "#{https_endpoint}/version"
token = 'token'
@request.private_token = token
@request.endpoint = http_endpoint

allow(@request).to receive(:httparty)

stub_request(:get, http_path)
.to_return(
status: [301, 'Moved Permanently'],
headers: { location: https_path }
)
stub_request(:get, https_path)
.to_return(status: 200)
@request.get('/version')
expect(a_request(:get, http_path).with(headers: {
'PRIVATE_TOKEN' => token
}.merge(described_class.headers))).to have_been_made
expect(a_request(:get, https_path).with(headers: {
'PRIVATE_TOKEN' => token
}.merge(described_class.headers))).to have_been_made
end

it 'redirect PUT' do
http_endpoint = 'http://example.com/api/v4'
https_endpoint = 'https://example.com:443/api/v4'
http_path = "#{http_endpoint}/application/settings"
https_path = "#{https_endpoint}/application/settings"
token = 'token'
body = 'signup_enabled=true'
@request.private_token = token
@request.endpoint = http_endpoint

allow(@request).to receive(:httparty)

stub_request(:put, http_path)
.with(body: body)
.to_return(
status: [301, 'Moved Permanently'],
headers: { location: https_path },
)
stub_request(:put, https_path)
.with(body: body)
.to_return(
status: 200,
body: '{}'
)

# simulate Gitlab.edit_application_settings(signup_enabled: true)
@request.put('/application/settings', :body => body)

expect(a_request(:put, http_path).with(
body: body,
headers: {
'PRIVATE_TOKEN' => token
}.merge(described_class.headers))).to have_been_made
expect(a_request(:put, https_path).with(
body: body,
headers: {
'PRIVATE_TOKEN' => token
}.merge(described_class.headers))).to have_been_made
end
end
end

0 comments on commit d83f809

Please sign in to comment.