bypass our server directly for feed favicons

This commit is contained in:
Athou
2013-04-28 15:15:59 +02:00
parent 06f86a992a
commit c3d826eb74
5 changed files with 146 additions and 224 deletions

View File

@@ -365,7 +365,7 @@
</goals> </goals>
<configuration> <configuration>
<targetGroups>app</targetGroups> <targetGroups>app</targetGroups>
<options>indent,devel,noarg,quotmark</options> <options>indent,devel,noarg,quotmark,laxcomma,laxbreak</options>
</configuration> </configuration>
</execution> </execution>
<execution> <execution>

View File

@@ -39,7 +39,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.commafeed.frontend.pages.DemoLoginPage; import com.commafeed.frontend.pages.DemoLoginPage;
import com.commafeed.frontend.pages.FaviconPage;
import com.commafeed.frontend.pages.GoogleImportCallbackPage; import com.commafeed.frontend.pages.GoogleImportCallbackPage;
import com.commafeed.frontend.pages.GoogleImportRedirectPage; import com.commafeed.frontend.pages.GoogleImportRedirectPage;
import com.commafeed.frontend.pages.HomePage; import com.commafeed.frontend.pages.HomePage;
@@ -69,7 +68,6 @@ public class CommaFeedApplication extends AuthenticatedWebApplication {
mountPage("demo", DemoLoginPage.class); mountPage("demo", DemoLoginPage.class);
mountPage("logout", LogoutPage.class); mountPage("logout", LogoutPage.class);
mountPage("error", DisplayExceptionPage.class); mountPage("error", DisplayExceptionPage.class);
mountPage("favicon", FaviconPage.class);
mountPage("google/import/redirect", GoogleImportRedirectPage.class); mountPage("google/import/redirect", GoogleImportRedirectPage.class);
mountPage(GoogleImportCallbackPage.PAGE_PATH, mountPage(GoogleImportCallbackPage.PAGE_PATH,
GoogleImportCallbackPage.class); GoogleImportCallbackPage.class);

View File

@@ -1,105 +0,0 @@
package com.commafeed.frontend.pages;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.impl.cookie.DateUtils;
import org.apache.wicket.request.IRequestCycle;
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.http.WebResponse;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.time.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.commafeed.backend.HttpGetter;
import com.commafeed.backend.HttpGetter.HttpResult;
import com.commafeed.backend.StartupBean;
import com.commafeed.backend.model.UserRole.Role;
import com.commafeed.frontend.SecurityCheck;
import com.google.common.net.HttpHeaders;
@SuppressWarnings("serial")
@SecurityCheck(Role.USER)
public class FaviconPage extends BasePage {
private static final Logger log = LoggerFactory
.getLogger(FaviconPage.class);
@Inject
HttpGetter getter;
@Inject
StartupBean startupBean;
public FaviconPage(PageParameters params) {
final String url = params.get("url").toString();
getRequestCycle().scheduleRequestHandlerAfterCurrent(
new IRequestHandler() {
@Override
public void respond(IRequestCycle requestCycle) {
WebResponse response = (WebResponse) requestCycle
.getResponse();
response.setLastModifiedTime(Time.millis(startupBean
.getStartupTime()));
response.setContentType("image/x-icon");
long expiresAfter = TimeUnit.DAYS.toMillis(7);
response.setHeader(
HttpHeaders.EXPIRES,
DateUtils.formatDate(new Date(startupBean
.getStartupTime() + expiresAfter)));
response.write(getImage(url));
}
@Override
public void detach(IRequestCycle requestCycle) {
}
});
}
private byte[] getImage(String url) {
byte[] img = null;
try {
if (StringUtils.isNotBlank(url)) {
int index = Math.max(url.length(), url.lastIndexOf("?"));
url = url.substring(0, index);
String iconUrl = "http://g.etfv.co/"
+ URLEncoder.encode(url, "UTF-8") + "?defaulticon=none";
HttpResult result = getter.getBinary(iconUrl);
if (result != null) {
img = result.getContent();
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
if (img == null) {
img = getDefaultIcon();
}
return img;
}
private byte[] getDefaultIcon() {
byte[] bytes = null;
InputStream is = null;
try {
is = getClass().getResourceAsStream("/favicon.gif");
bytes = IOUtils.toByteArray(is);
} catch (IOException e) {
log.error(e.getMessage(), e);
} finally {
IOUtils.closeQuietly(is);
}
return bytes;
}
}

View File

Before

Width:  |  Height:  |  Size: 238 B

After

Width:  |  Height:  |  Size: 238 B

View File

@@ -7,7 +7,25 @@ module.directive('favicon', function() {
url : '=' url : '='
}, },
replace : true, replace : true,
template : '<img ng-src="favicon?url={{url}}" class="favicon"></img>' template : '<img ng-src="{{iconUrl()}}" class="favicon" onError="this.src=\'images/default_favicon.gif\'"></img>',
controller : function($scope) {
$scope.iconUrl = function() {
var url = $scope.url;
var current = window.location.href;
var baseUrl = current.substring(0, current.lastIndexOf('#'));
var defaultIcon = baseUrl + 'images/default_favicon.gif';
if (!url) {
return defaultIcon;
}
var index = Math.max(url.length, url.lastIndexOf('?'));
var iconUrl = 'http://g.etfv.co/';
iconUrl += encodeURIComponent(url.substring(0, index));
iconUrl += '?defaulticon=none';
return iconUrl;
};
}
}; };
}); });
@@ -82,133 +100,144 @@ module.directive('category', [ function() {
restrict : 'E', restrict : 'E',
replace : true, replace : true,
templateUrl : 'directives/category.html', templateUrl : 'directives/category.html',
controller : ['$scope', '$state', '$dialog', 'FeedService', controller : [
'CategoryService', 'SettingsService', function($scope, $state, $dialog, FeedService, '$scope',
CategoryService, SettingsService) { '$state',
$scope.settingsService = SettingsService; '$dialog',
$scope.unsubscribe = function(subscription) { 'FeedService',
var title = 'Unsubscribe'; 'CategoryService',
var msg = 'Unsubscribe from ' + subscription.name + ' ?'; 'SettingsService',
var btns = [ { function($scope, $state, $dialog, FeedService, CategoryService,
result : 'cancel', SettingsService) {
label : 'Cancel' $scope.settingsService = SettingsService;
}, { $scope.unsubscribe = function(subscription) {
result : 'ok', var title = 'Unsubscribe';
label : 'OK', var msg = 'Unsubscribe from ' + subscription.name
cssClass : 'btn-primary' + ' ?';
} ]; var btns = [ {
result : 'cancel',
label : 'Cancel'
}, {
result : 'ok',
label : 'OK',
cssClass : 'btn-primary'
} ];
$dialog.messageBox(title, msg, btns).open().then( $dialog.messageBox(title, msg, btns).open().then(
function(result) { function(result) {
if (result == 'ok') { if (result == 'ok') {
var data = { var data = {
id : subscription.id id : subscription.id
}; };
FeedService.unsubscribe(data, function() { FeedService.unsubscribe(data,
CategoryService.init(); function() {
CategoryService.init();
});
}
}); });
} };
$scope.formatCategoryName = function(category) {
var count = $scope.unreadCount({
category : category
}); });
}; var label = category.name;
if (count > 0) {
label = label + ' (' + count + ')';
}
return label;
};
$scope.formatCategoryName = function(category) { $scope.formatFeedName = function(feed) {
var count = $scope.unreadCount({ var label = feed.name;
category : category if (feed.unread > 0) {
}); label = label + ' (' + feed.unread + ')';
var label = category.name; }
if (count > 0) { return label;
label = label + ' (' + count + ')'; };
}
return label;
};
$scope.formatFeedName = function(feed) { $scope.feedClicked = function(id) {
var label = feed.name; if ($scope.selectedType == 'feed'
if (feed.unread > 0) { && id == $scope.selectedId) {
label = label + ' (' + feed.unread + ')'; $scope.$emit('emitReload');
} } else {
return label; $state.transitionTo('feeds.view', {
}; _type : 'feed',
_id : id
});
}
};
$scope.feedClicked = function(id) { $scope.categoryClicked = function(id) {
if ($scope.selectedType == 'feed' && id == $scope.selectedId) { if ($scope.selectedType == 'category'
$scope.$emit('emitReload'); && id == $scope.selectedId) {
} else { $scope.$emit('emitReload');
$state.transitionTo('feeds.view', { } else {
_type : 'feed', $state.transitionTo('feeds.view', {
_id : id _type : 'category',
}); _id : id
} });
}; }
};
$scope.categoryClicked = function(id) { $scope.renameFeed = function(feed) {
if ($scope.selectedType == 'category' && id == $scope.selectedId) { var name = window.prompt('Rename feed : ', feed.name);
$scope.$emit('emitReload'); if (name && name != feed.name) {
} else { feed.name = name;
$state.transitionTo('feeds.view', { FeedService.rename({
_type : 'category', id : feed.id,
_id : id name : name
}); });
} }
}; };
$scope.renameFeed = function(feed) { $scope.renameCategory = function(category) {
var name = window.prompt('Rename feed : ', feed.name); var name = window.prompt('Rename category: ',
if (name && name != feed.name) { category.name);
feed.name = name; if (name && name != category.name) {
FeedService.rename({ category.name = name;
id : feed.id, CategoryService.rename({
name : name id : category.id,
}); name : name
} });
}; }
};
$scope.renameCategory = function(category) { $scope.deleteCategory = function(category) {
var name = window.prompt('Rename category: ', category.name); var title = 'Delete category';
if (name && name != category.name) { var msg = 'Delete category ' + category.name + ' ?';
category.name = name; var btns = [ {
CategoryService.rename({ result : 'cancel',
id : category.id, label : 'Cancel'
name : name }, {
}); result : 'ok',
} label : 'OK',
}; cssClass : 'btn-primary'
} ];
$scope.deleteCategory = function(category) { $dialog.messageBox(title, msg, btns).open().then(
var title = 'Delete category'; function(result) {
var msg = 'Delete category ' + category.name + ' ?'; if (result == 'ok') {
var btns = [ { CategoryService.remove({
result : 'cancel', id : category.id
label : 'Cancel' }, function() {
}, { CategoryService.init();
result : 'ok', });
label : 'OK', }
cssClass : 'btn-primary'
} ];
$dialog.messageBox(title, msg, btns).open().then(
function(result) {
if (result == 'ok') {
CategoryService.remove({
id : category.id
}, function() {
CategoryService.init();
}); });
} };
});
};
$scope.toggleCategory = function(category) { $scope.toggleCategory = function(category) {
category.expanded = !category.expanded; category.expanded = !category.expanded;
if (category.id == 'all') { if (category.id == 'all') {
return; return;
} }
CategoryService.collapse({ CategoryService.collapse({
id : category.id, id : category.id,
collapse : !category.expanded collapse : !category.expanded
}); });
}; };
}] } ]
}; };
} ]); } ]);