remove surf code, clean up purge cache and better define purge cache tests for expected behavior

This commit is contained in:
Kyle Drake 2024-02-21 13:51:41 -06:00
parent b4caf44af4
commit 29619d51ee
12 changed files with 106 additions and 395 deletions

View file

@ -1,6 +1,4 @@
get '/browse/?' do
@surfmode = false
@page = params[:page]
@page = 1 if @page.not_an_integer?

View file

@ -1,22 +0,0 @@
get '/surf/?' do
not_found # 404 for now
@page = params[:page]
@page = 1 if @page.not_an_integer?
params.delete 'tag' if params[:tag].nil? || params[:tag].strip.empty?
site_dataset = browse_sites_dataset
site_dataset = site_dataset.paginate @page.to_i, 1
@page_count = site_dataset.page_count || 1
@site = site_dataset.first
redirect "/browse?#{Rack::Utils.build_query params}" if @site.nil?
@title = "Surf Mode - #{@site.title}"
erb :'surf', layout: false
end
get '/surf/:username' do |username|
not_found # 404 for now
@site = Site.select(:id, :username, :title, :domain, :views, :stripe_customer_id).where(username: username).first
not_found if @site.nil?
@title = @site.title
not_found if @site.nil?
erb :'surf', layout: false
end

View file

@ -766,20 +766,26 @@ class Site < Sequel::Model
def purge_cache(path)
relative_path = path.gsub base_files_path, ''
# We gotta flush the dirname too if it's an index file.
if relative_path != '' && relative_path.match(/\/$|index\.html?$/i)
PurgeCacheWorker.perform_async username, relative_path
if relative_path[0] != '/'
relative_path = '/' + relative_path
end
# We gotta flush the dirname too if it's an index file.
if relative_path != '' && relative_path.match(/\/$|\/index\.html?$/i)
purge_file_path = Pathname(relative_path).dirname.to_s
purge_file_path = '' if purge_file_path == '.'
purge_file_path += '/' if purge_file_path != '/'
PurgeCacheWorker.perform_async username, '/?surf=1' if purge_file_path == '/'
PurgeCacheWorker.perform_async username, purge_file_path
else
html = relative_path.match(/(.*)\.html?$/)
if html
PurgeCacheWorker.perform_async username, html.captures.first
else
PurgeCacheWorker.perform_async username, relative_path
end
end
end
def purge_all_cache
site_files.each do |site_file|

View file

@ -104,8 +104,6 @@ class SiteFile < Sequel::Model
DB.transaction do
self.path = new_path
self.save_changes
site.purge_cache current_path
site.purge_cache new_path
if is_directory
site_files_in_dir = site.site_files.select {|sf| sf.path =~ /^#{current_path}\//}

View file

@ -1,8 +0,0 @@
function _nc_surf_page_overload() {
var ele = document.getElementsByTagName('a')
for(var i=0; i<ele.length; i++) {
if(ele[i].href.match(/^\w+:\/\//i)) // && !ele[i].href.match(/^.+\.neocities\.org/i))
ele[i].setAttribute('target', '_blank')
}
}
_nc_surf_page_overload()

View file

@ -87,8 +87,7 @@ describe 'site_files' do
_(dasharezone).wont_equal nil
_(dasharezone.is_directory).must_equal true
_(PurgeCacheWorker.jobs.first['args'].last).must_equal 'dirone'
_(PurgeCacheWorker.jobs.last['args'].last).must_equal 'dasharezone'
# No purge cache is executed because the directory is empty
end
it 'wont set an empty directory' do
@ -112,12 +111,14 @@ describe 'site_files' do
'files[]' => Rack::Test::UploadedFile.new('./tests/files/index.html', 'image/jpeg')
)
PurgeCacheWorker.jobs.clear
@site.site_files.select {|s| s.path == 'test'}.first.rename('test2')
_(@site.site_files.select {|sf| sf.path =~ /test2\/index.html/}.length).must_equal 1
_(@site.site_files.select {|sf| sf.path =~ /test2\/test.jpg/}.length).must_equal 1
_(@site.site_files.select {|sf| sf.path =~ /test\/test.jpg/}.length).must_equal 0
_(PurgeCacheWorker.jobs.collect {|p| p['args'].last}.sort).must_equal ["/test/test.jpg", "/test/index.html", "/test/", "test", "test2", "test/test.jpg", "test2/test.jpg", "test/index.html", "test/", "test2/index.html", "test2/"].sort
_(PurgeCacheWorker.jobs.collect {|p| p['args'].last}.sort).must_equal ["/test/", "/test/test.jpg", "/test2/", "/test2/test.jpg",].sort
end
it 'doesnt wipe out existing file' do
@ -309,8 +310,7 @@ describe 'site_files' do
it 'purges cache for html file with extension removed' do
upload 'files[]' => Rack::Test::UploadedFile.new('./tests/files/notindex.html', 'text/html')
_(PurgeCacheWorker.jobs.first['args'].last).must_equal '/notindex.html'
PurgeCacheWorker.jobs.clear
_(PurgeCacheWorker.jobs.length).must_equal 1
PurgeCacheWorker.new.perform @site.username, '/notindex.html'
_(PurgeCacheWorker.jobs.first['args'].last).must_equal '/notindex'
end
@ -329,25 +329,14 @@ describe 'site_files' do
_(@site.site_changed).must_equal true
_(@site.title).must_equal 'Hello?'
# Purge cache needs to flush / and index.html for either scenario.
_(PurgeCacheWorker.jobs.length).must_equal 3
_(PurgeCacheWorker.jobs.length).must_equal 1
first_purge = PurgeCacheWorker.jobs.first
surf_purge = PurgeCacheWorker.jobs[1]
dirname_purge = PurgeCacheWorker.jobs.last
username, pathname = first_purge['args']
_(username).must_equal @site.username
_(pathname).must_equal '/index.html'
_(surf_purge['args'].last).must_equal '/?surf=1'
username, pathame = nil
username, pathname = dirname_purge['args']
_(username).must_equal @site.username
_(pathname).must_equal '/'
_(@site.space_used).must_equal @site.actual_space_used
_((@site.space_used > 0)).must_equal true
end

View file

@ -128,4 +128,91 @@ describe Site do
_(site.suggestions.length).must_equal(Site::SUGGESTIONS_LIMIT - 5)
end
end
describe 'purge_cache' do
before do
@site = Fabricate :site
PurgeCacheWorker.jobs.clear
end
it 'works for /index.html' do
@site.purge_cache '/index.html'
_(PurgeCacheWorker.jobs.length).must_equal 1
args = PurgeCacheWorker.jobs.first['args']
_(args.first).must_equal @site.username
_(args.last).must_equal '/'
end
it 'works for /dir/index.html' do
@site.purge_cache '/dir/index.html'
_(PurgeCacheWorker.jobs.length).must_equal 1
args = PurgeCacheWorker.jobs.first['args']
_(args.first).must_equal @site.username
_(args.last).must_equal '/dir/'
end
it 'works for /test.html' do
@site.purge_cache '/test.html'
_(PurgeCacheWorker.jobs.length).must_equal 1
args = PurgeCacheWorker.jobs.first['args']
_(args.first).must_equal @site.username
_(args.last).must_equal '/test'
end
it 'works for /newdir/index.html' do
@site.purge_cache '/newdir/test.html'
_(PurgeCacheWorker.jobs.length).must_equal 1
args = PurgeCacheWorker.jobs.first['args']
_(args.first).must_equal @site.username
_(args.last).must_equal '/newdir/test'
end
it 'works for /file.png' do
@site.purge_cache '/file.png'
_(PurgeCacheWorker.jobs.length).must_equal 1
args = PurgeCacheWorker.jobs.first['args']
_(args.first).must_equal @site.username
_(args.last).must_equal '/file.png'
end
it 'works for /testdir/file.png' do
@site.purge_cache '/testdir/file.png'
_(PurgeCacheWorker.jobs.length).must_equal 1
args = PurgeCacheWorker.jobs.first['args']
_(args.first).must_equal @site.username
_(args.last).must_equal '/testdir/file.png'
end
it 'works for /notindex.html' do
@site.purge_cache '/notindex.html'
_(PurgeCacheWorker.jobs.length).must_equal 1
args = PurgeCacheWorker.jobs.first['args']
_(args.first).must_equal @site.username
_(args.last).must_equal '/notindex'
end
it 'works for index.html missing forward slash' do
@site.purge_cache 'index.html'
_(PurgeCacheWorker.jobs.length).must_equal 1
args = PurgeCacheWorker.jobs.first['args']
_(args.first).must_equal @site.username
_(args.last).must_equal '/'
end
it 'works for photo.png missing forward slash' do
@site.purge_cache 'photo.png'
_(PurgeCacheWorker.jobs.length).must_equal 1
args = PurgeCacheWorker.jobs.first['args']
_(args.first).must_equal @site.username
_(args.last).must_equal '/photo.png'
end
it 'works for testdir/photo.png missing forward slash' do
@site.purge_cache 'testdir/photo.png'
_(PurgeCacheWorker.jobs.length).must_equal 1
args = PurgeCacheWorker.jobs.first['args']
_(args.first).must_equal @site.username
binding.pry
_(args.last).must_equal '/testdir/photo.png'
end
end
end

View file

@ -2,10 +2,6 @@
function getPage(page) {
document.location.href = '/browse?page='+page+'&'+$('#search_criteria').serialize();
}
function surf(page) {
document.location.href = '/surf?page='+page+'&'+$('#search_criteria').serialize();
}
</script>
<div class="header-Outro with-columns browse-page">
@ -80,9 +76,6 @@
<a href="<%= site.uri %>"
class="neo-Screen-Shot"
title="<%= site.title %>"
<% if @surfmode %>
onclick="surf(<%= ((@page-1)*Site::BROWSE_PAGINATION_LENGTH)+i+1 %>); return false"
<% end %>
>
<span class="img-Holder" style="background:url(<%= site.screenshot_url('index.html', '540x405') %>) no-repeat;">
<img src="/img/placeholder.png" alt="<%= site.title %>" />
@ -91,9 +84,6 @@
<div class="title">
<a href="<%= site.uri %>"
title="<%= site.title %>"
<% if @surfmode %>
onclick="surf(<%= ((@page-1)*Site::BROWSE_PAGINATION_LENGTH)+i+1 %>); return false"
<% end %>
><%= site.title.shorten(30) %></a>
</div>
<div class="site-info">

View file

@ -194,7 +194,7 @@
<div class="col col-50"><div class="screenshot" style="background-image:url(/img/front-browse-screenshot.jpg);"></div></div>
<div class="col col-50 text">
<h3><i class="fa fa-globe"></i> Welcome back, web surfing</h3>
<p>All Neocities sites are viewable in our <a href="/browse">website gallery</a>. And it's easy to browse sites with our optional surf bar.</p>
<p>All Neocities sites are viewable and easily surfable in our <a href="/browse">website gallery</a>.</p>
<p>Using tags (our version of Web Rings) you can easily discover new sites related to your interests.</p>
</div>
</div>

View file

@ -1,285 +0,0 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><%= title %></title>
<link href="/css/font-awesome.css" rel="stylesheet">
<link href="/css/bootstrap.min.css" rel="stylesheet">
<style>
*, form {
margin: 0;
padding: 0;
}
html {
height: 100%;
}
body {
height: 100%;
width: 100%;
font-family: "Lucida Grande", helvetica, verdana, sans-serif;
font-size: 12px;
overflow: hidden;
}
#logo {
background: url(/img/topbar-cat.png) no-repeat 1px 0px;
width: 30px;
height: 26px;
background-size: 29px;
position: absolute;
display: block;
}
#website-frame {
width: 100%;
height: 100%;
height: calc(100% - 2.2em);
}
#top-bar {
background: #3B3B3B;
color: #cecece;
float: left;
width: 100%;
padding: 6px 0;
}
#top-bar ul {
list-style: none;
margin: 0;
}
#top-bar li {
float: left;
margin-left: 20px;
line-height: normal;
}
#top-bar a {
color: #cecece;
text-decoration: none;
}
#top-bar a:hover {
color: #fff;
}
#top-bar input {
border: 0;
background: #555;
color: white;
width: 13em;
padding: 1px 5px;
font-size: inherit;
margin: 0;
height: 1.1em;
line-height: normal;
border-radius: 3px;
}
::-webkit-input-placeholder { font-style: italic; color: #aaa!important; }
:-moz-placeholder { font-style: italic; color: #ccc; }
::-moz-placeholder { font-style: italic; color: #ccc; }
:-ms-input-placeholder { font-style: italic; color: #ccc; }
#top-bar .twitter-typeahead {
color: #000;
}
#top-bar .tt-dropdown-menu {
background: #FFFFFF;
cursor: pointer;
border: 1px solid #ddd;
top: 106%!important;
width: 98.5%!important;
}
#top-bar .tt-suggestion {
margin:0;
padding: 0px 8px 0px 8px;
height: 2em;
line-height: 2em;
}
#top-bar .tt-cursor {
background: #DAF3EF;
}
#top-bar .browse-actions {
margin-left: 20px;
}
#top-bar .site-actions {
float: right;
margin-right: 9px;
}
.popover {
background-color: #555;
}
.popover.bottom .arrow:after {
border-bottom-color: #555;
}
.popover a {
color: #cecece;
}
#top-bar .close {
background: url(/img/topbar-close.png) no-repeat;
width: 13px;
height: 13px;
background-size: 13px;
margin-top: 1px;
float: left;
opacity: 1; /*overriding boostrap*/
}
#top-bar .invisible a {
color: #3B3B3B;
}
#top-bar .fa-heart {
font-size: 0.7em;
color: #e93250;
vertical-align: .45em;
margin-left: -.15em;
}
#top-bar .fa-user {
display: inline;
font-size: 11px;
}
.hidden {
display:none!important;
visibility:hidden
}
#followLink .follow {
display: inline;
}
#followLink .following {
display: none;
}
#followLink .unfollow {
display: none;
}
#followLink.is-following {
width: 6em;
display: block;
}
#followLink.is-following .follow {
display: none;
}
#followLink.is-following .following {
display: inline;
}
#followLink.is-following .unfollow {
display: none;
}
#followLink.is-following.unfollow .follow {
display: none;
}
#followLink.is-following.unfollow .following {
display: none;
}
#followLink.is-following.unfollow .unfollow {
display: inline;
}
</style>
</head>
<body>
<script type="text/javascript">
function getPage(page) {
document.location.href = '/surf?page='+page+'&'+$('#search_criteria').serialize()
}
function backToBrowse() {
document.location.href = '/browse?'+$('#search_criteria').serialize()
}
</script>
<a href="/" id="logo"></a>
<div id="top-bar">
<ul class="browse-actions">
<li>
<a href="/browse" onclick="backToBrowse(<%= @page %>); return false">Neocities</a>
</li>
<% if @page %>
<li>
<form id="search_criteria" onsubmit="getPage(1); return false">
<input type="hidden" name="sort_by" value="<%= params[:sort_by] %>">
<input class="typeahead" name="tag" type="text" placeholder="Browse by tag..." value="<%= params[:tag] %>" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" />
<input class="hidden" type="submit" tabindex="-1"/>
</form>
</li>
<li>
<% if @page > 1 %>
<a href="" onclick="getPage(<%= @page - 1 %>); return false">
<i class="fa fa-caret-left"></i> Prev
</a>
<% end %>
</li>
<li>
<% if @page != @page_count %>
<a href="" onclick="getPage(<%= @page + 1 %>); return false">Next <i class="fa fa-caret-right"></i></a>
<% end %>
</li>
<% end %>
</ul>
<ul class="site-actions">
<li><a href="/site/<%= @site.username %>"><i class="fa fa-user"><% if @site.supporter? %><i class="fa fa-heart"></i><% end %></i> <strong><%= @site.username %></strong></a></li>
<% if current_site && current_site != @site %>
<li>
<a id="followLink" href="#" onclick="toggleFollow(<%= @site.id %>); return false" class="<% if current_site.is_following? @site %>is-following<% end %>">
<span class="unfollow"><i class="fa fa-times"></i> Unfollow</span>
<span class="following"><i class="fa fa-check"></i> Following</span>
<span class="follow"><i class="fa fa-plus"></i> Follow</span>
</a>
</li>
<% end %>
<li>
<a href="" id="shareButton" data-container="body" data-toggle="popover" data-placement="bottom" data-content='<%== erb :'_share', layout: false, locals: {site: @site} %>' onclick="return false">
<i class="fa fa-share-alt"></i> Share
</a>
</li>
<% unless signed_in? %>
<li>
<a href="/">Create your own free web site</a>
</li>
<% end %>
<li>
<a class="close" href="//<%= @site.host %>" alt="close" title="close"></a>
</li>
</ul>
</div>
<iframe src="https://<%= @site.username %>.neocities.org?surf=1" frameborder="0" scrolling="yes" marginheight="0" marginwidth="0" id="website-frame" name="website-frame"></iframe>
<script src="/js/jquery-1.11.0.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
<script src="/js/typeahead.bundle.js"></script>
<script>
$(function() {
$('#shareButton').popover({html: true})
})
$('.typeahead').typeahead({
minLength: 2,
highlight: true
}, {
name: 'tags',
source: function(query, callback) {
$.get('/tags/autocomplete/'+query+'.json', function(data) {
var suggestions = JSON.parse(data)
var suggestionObjects = []
for(var i=0; i<suggestions.length; i++)
suggestionObjects.push({value: suggestions[i]})
callback(suggestionObjects)
})
}
}).on('typeahead:selected', function(e) {
e.target.form.submit()
})
var link = $('a#followLink');
function toggleFollow(id) {
$.post('/site/'+id+'/toggle_follow', {csrf_token: '<%= csrf_token %>'}, function(res) {
if(res.result == 'followed')
link.addClass('is-following')
if(res.result == 'unfollowed')
link.removeClass('is-following')
})
}
link.hover(function() {
if (link.hasClass('is-following')) {
link.addClass('unfollow');
}
}, function() {
link.removeClass('unfollow');
});
</script>
</body>
</html>

View file

@ -1,10 +0,0 @@
<script>
function _nc_surf_page_overload() {
var ele = document.getElementsByTagName('a')
for(var i=0; i<ele.length; i++) {
if(ele[i].href.match(/^\w+:\/\//i) && !ele[i].href.match(/^.+\.neocities\.org/i))
ele[i].setAttribute('target', '_blank')
}
}
_nc_surf_page_overload()
</script>

View file

@ -11,38 +11,6 @@ class PurgeCacheWorker
end
def perform(username, path)
# Must always have a forward slash
path = '/' + path if path[0] != '/'
# Add removed html ext if present
html = path.match(/(.*)\.html?$/)
if html
PurgeCacheWorker.perform_async username, html.captures.first
end
$redis_proxy.publish 'proxy', {cmd: 'purge', path: "#{username}#{path}"}.to_msgpack
=begin
url = Addressable::URI.encode_component(
"https://#{proxy_ip}#{path}",
Addressable::URI::CharacterClasses::QUERY
)
retry_encoded = false
begin
#cmd = %{timeout 5 curl -k -I -H "Host: #{URI::encode("#{username}.neocities.org")}" -H "Cache-Purge: 1" "#{url}"}
#`#{cmd}`
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
HTTP.follow.timeout(read: 10, write: 10, connect: 5).
headers(host: URI::encode("#{username}.neocities.org"), cache_purge: '1').
head(url, ssl_context: ctx)
rescue URI::InvalidURIError
raise if retry_encoded == true
url = URI.encode url
retry_encoded = true
retry
end
=end
end
end