OneFeed is Serving HTTPS
Now OneFeed is living on https. Its certificate is signed by Let’s Encrypt, “a free, automated, and open Certificate Authority”. Using Let’s Encrypt’s ACME (Automatic Certificate Management Environment) protocol and a client of the protocol, requesting and renewing site certificate is just done automatically.
ACME protocol defines serveral challenges which a protocol client can use to prove it (the host running the client) owns the domain. Also the protocol defines how to request, renew, and revoke certificates. With clear definition of interaction with ACME server (CA) and client (your site), all process can be automated. Certbot is a recommended ACME client.
To set up https on this site, I use this great post as a reference. Basic steps are:
- use a certbot docker image to get certificate from Let’s Encrypt for the first time.
- update configuration of web server using the certificate.
- set up a cron job to auto-renew the certificate.
Use Docker Images to Get Certificate
Certbot is in active development. Use the certbot docker image (by default latest image), so that we don’t bother ourselves with updating certbot to newest version. And use the nginx docker image to set up a basic web server to fulfill ACME challenges, so that our production web server’s configuration gets untouched when requesting a certificate. (Also plus since OneFeed is already living within docker containers, using docker/docker-compose is an easy decision.) The containers used in this step are discarded/cleaned up as soon as certificate fetched for the first time.
Update Configuration of the Production Web Server
Just google how to set up https on the web server. For OneFeed, https is set up on a nginx server.
Set Up a Cron Job to Renew and Reload/Restart Web Server
The reference post uses docker kill --signal=HUP production-nginx-container
to send signal to nginx container’s nginx process for server reloading.
However, since OneFeed is not using plain nginx container, but a passenger-docker,
therefore using docker-compose restart
to reload certificate instead.
0 23 * * * docker run --rm -it --name certbot-renew \
-v /CERTBOT_VOLUME/etc/letsencrypt:/etc/letsencrypt \
-v /CERTBOT_VOLUME/var/lib/letsencrypt:/var/lib/letsencrypt \
-v /CERTBOT_VOLUME/data/letsencrypt:/data/letsencrypt \
-v /CERTBOT_VOLUME/var/log/letsencrypt:/var/log/letsencrypt \
certbot/certbot renew --webroot -w /data/letsencrypt --quiet \
&& cd YOUR_DOCKER_COMPOSE_WORKING_DIR \
&& docker-compose restart
OneFeed的通知推送功能
实现了push notification功能。 现在当OneFeed上有新评论的时候,我的手机会收到通知。
下面是简单的构架图,
生成新评论的时候,Rails app会触发一个job向RabbitMQ发送消息。 一个sneakers worker会处理RabbitMQ中的消息,然后调用Slack API向Slack发送消息。 Slack会帮忙把消息push到我的手机上。
用到的工具
RabbitMQ的ruby client用的是bunny。 Rails job用bunny来发送消息。 RabbitMQ的consumer用的是Sneakers。 通过Slack bot来向Slack发送消息。Slack的ruby client用的是slack-ruby-client。
Comments and Rate Limit
Now OneFeed supports commenting.
Since post pages are cached for quick access, a tiny modification is needed to accept POST
request initiated from the cached pages.
authenticity_token
s in comment creation form of cached pages are usually out-of-date.
<form action="/posts/post-x-link/comments" method="post">
<input type="hidden" name="authenticity_token" value="zzcjgpp55...+yxjDy4LmydrMVqsAfQ/+igqKDcIAg==">
Rails uses these authenticity_token
s to prevent CSRF attack.
Skip this protection for comment :create
method.
class CommentsController < ApplicationController
protect_from_forgery except: :create
Rate Limit
And a rate limit is set for POST
request of comment creation.
It’s simply implemented on top of Redis.
def exceed_limit?
key = request.remote_ip
if EXISTS key
return true # the ip has been submitted a comment lately
else
INCR key
EXPIRE key, CREATION_RATE_LIMIT
return false
end
end
Tag Cloud, Responsive UI and Performance Tuning
Now OneFeed has a tag cloud, more responsive UI across desktop and phone browsers. Also performance of this site is improved a bit.
Tag Cloud
Both Javascript and CSS can implement tag cloud. A JQuery plugin called jQCloud can produce very beautiful tag cloud. But considering Javascript may be disabled, a CSS implementation is more reliable. My implementation is largely based on this CSS tag cloud.
Responsive UI
First of first to implement a responsive UI,
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Code Highlighting and More
- Add Google Analytics.
- Tag support.
- Code highlighting with help of Rouge.
public void greeting() {
System.out.println("Hello World");
}