-
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(auto_source): add specs and re-structure files
- Loading branch information
1 parent
574ed4b
commit 31a7b4e
Showing
9 changed files
with
289 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'addressable' | ||
require 'base64' | ||
require 'html2rss' | ||
require 'ssrf_filter' | ||
|
||
module Html2rss | ||
module Web | ||
## | ||
# Helper methods for handling auto source feature. | ||
class AutoSource | ||
def self.enabled? = ENV['AUTO_SOURCE_ENABLED'].to_s == 'true' | ||
def self.username = ENV.fetch('AUTO_SOURCE_USERNAME') | ||
def self.password = ENV.fetch('AUTO_SOURCE_PASSWORD') | ||
def self.allowed_origins = ENV.fetch('AUTO_SOURCE_ALLOWED_ORIGINS', '').split(',').to_set | ||
|
||
def self.build_auto_source_from_encoded_url(encoded_url) | ||
url = Addressable::URI.parse Base64.urlsafe_decode64(encoded_url) | ||
request = SsrfFilter.get(url) | ||
headers = request.to_hash.transform_values(&:first) | ||
|
||
auto_source = Html2rss::AutoSource.new(url, body: request.body, headers:) | ||
|
||
auto_source.channel.stylesheets << Html2rss::RssBuilder::Stylesheet.new(href: '/rss.xsl', type: 'text/xsl') | ||
|
||
auto_source.build | ||
end | ||
|
||
def self.ttl_in_seconds(rss, default_in_minutes: 60) | ||
(rss.channel.ttl || default_in_minutes) * 60 | ||
end | ||
|
||
def self.check_request_origin!(request, response, allowed_origins = AutoSource.allowed_origins) | ||
if allowed_origins.empty? | ||
response.write 'No allowed origins are configured. Please set AUTO_SOURCE_ALLOWED_ORIGINS.' | ||
else | ||
origin = Set[request.env['HTTP_HOST'], request.env['HTTP_X_FORWARDED_HOST']].delete(nil) | ||
return if allowed_origins.intersect?(origin) | ||
|
||
response.write "Origin '#{origin}' is not allowed." | ||
end | ||
|
||
response.status = 403 | ||
request.halt | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
spec/fixtures/vcr_cassettes/auto_source-github-h2r-web.yml
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
require_relative '../../app' | ||
|
||
describe Html2rss::Web::App do # rubocop:disable RSpec/SpecFilePathFormat | ||
include Rack::Test::Methods | ||
def app = described_class | ||
|
||
let(:request_headers) do | ||
{ 'HTTP_HOST' => 'localhost' } | ||
end | ||
|
||
let(:username) { 'username' } | ||
let(:password) { 'password' } | ||
|
||
before do | ||
allow(Html2rss::Web::AutoSource).to receive_messages(enabled?: true, | ||
username:, | ||
password:, | ||
allowed_origins: Set['localhost']) | ||
end | ||
|
||
describe "GET '/auto_source/'" do | ||
context 'without provided basic auth' do | ||
it 'sets header "www-authenticate" in response', :aggregate_failures do | ||
get '/auto_source/', {}, request_headers | ||
|
||
expect(last_response.has_header?('www-authenticate')).to be true | ||
expect(last_response).to be_unauthorized | ||
end | ||
end | ||
|
||
context 'with provided basic auth' do | ||
it 'responds successfully to /auto_source/', :aggregate_failures do | ||
get '/auto_source/', {}, | ||
request_headers.merge('HTTP_AUTHORIZATION' => basic_authorize(username, password)) | ||
|
||
expect(last_response).to be_ok | ||
expect(last_response.body).to include('Automatically sources') & | ||
include('<iframe loading="lazy"></iframe>') | ||
end | ||
end | ||
end | ||
|
||
describe "GET '/auto_source/:encoded_url'" do | ||
context 'with provided basic auth' do | ||
subject(:response) do | ||
VCR.use_cassette('auto_source-github-h2r-web') do | ||
get "/auto_source/#{Base64.urlsafe_encode64('https://github.com/html2rss/html2rss-web')}", | ||
{}, | ||
request_headers.merge('HTTP_AUTHORIZATION' => basic_authorize(username, password)) | ||
end | ||
end | ||
|
||
it 'responds successfully', :aggregate_failures do | ||
expect(response).to be_ok | ||
end | ||
|
||
it do | ||
expect(response.body).to start_with '<?xml version="1.0" encoding="UTF-8"?>' | ||
end | ||
|
||
it do | ||
expect(response.get_header('cache-control')).to eq 'must-revalidate, private, max-age=0' | ||
end | ||
|
||
it 'sets content type' do | ||
expect(response.get_header('content-type')).to eq described_class::CONTENT_TYPE_RSS | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters