Background

I spent a few weeks to develop and set up my own website. The registered domain is root domain (i.e. example.com) and the DNS setting on GoDaddy is to redirect the root domain(example.com) to the www subdomain (e.g. www.example.com). The last step before publishing is to add SSL certificates to my root domain and www subdomain. I found a nice tutorial online regarding how to do it Let’s Encrypt on Heroku with DNS Domain Validation. However, it turned out that follow the intructions I could not generate certificate and private key for my www subdomain. I will show the issue and explain how I resolve it in details.

Trulli
Lovely "Lock":)

The Issue

My ultimate goal is to let https://www.example.com work on browsers. I have three custom domain in my Heroku app: *.exmaple.com, exmaple.com, www.example.com.

Following the instructions of Let’s Encrypt on Heroku with DNS Domain Validation, when Let’s Encrypt asked me to provide the domain name (as shown below), no matter I use example.com or www.example.com

1
2
Please enter the domain name(s) you would like on your certificate (comma and/or
space separated) (Enter 'c' to cancel):

later at the stage of applying the certificate to Heroku “sudo heroku certs:add –type=…/certificate …/privatekey”, the heroku will not provide domain name www.example.com as an option for the certificate but only example.com. This leads to the result of www.example.com is not secured.

Resolution

The resolution is easy but took me a lot of time to find it. The trick is using wildcard subdomain. At the stage of providing domain name to Let’s Encrypt, I used *.exmample.com, then later when I apply the generated certificate and private key to Heroku, it offers www.exmample.com as an option.

1
2
=== Almost done! Which of these domains on this application would you like this certificate associated with?
? Select domains www.jingjies-blog.com

Then check on Heroku, I can see the following:

Trulli
The wildcard certificate
Trulli
Secured www.jingjies-blog.com

On GoDaddy, change the redirect from http://www.example.com to https://www.example.com

Trulli
Set up Forwarding

Finally, I can see the “lock” on browser :)

Comment and share

Add View Counter to Hexo in Express

in Series, Building Blog, Technology, Nodejs Sitevisits: -- Pageviews: --

I planned to add a site visit counter and page view counter into my blog (Hexo + Express.js). And by searching online, it seems that there is very limited information can be found on how to add such things on a Hexo Blog where:

  • The Hexo blog is integrated into an existing Express server, i.e. the blog should be visited at express_site/blog
  • The theme I used for the blog does not have such feature added, means I cannot just add something to the _config.yml of the theme and the view counter will work as a charm. I will need to customize it.

There was several options that I had in mind:

  • Only customize Hexo blog and the theme –> I realize it is not feasible. I do not know how to let Hexo or the theme load customised .js file under Hexo + Express structure;
  • Load js from Express side –> I finally use this method. Let Express loading related js file as Express static files, the js file will add the data to the view counter in Hexo pages. Blow is what I got in the end.
    Trulli
    View counter in blog post

Now I will introduce how I achive it in details.

Set up view counter

  • Set up Firebase (There are tons of tutorial out there, so I am not going to repeat it:))

    There is only one thing I would like to emphasize is the database set up. The database should be Realtime Database, and the “rules” is set as below. I will explain in details later why this will not cause security issues.

Trulli
Firebase Realtime Databse Rules
  • After register and setting up the Firebase, add the following code to the hexo_blog_directory/themes/{your theme}/layout/xxx.ejs where you want to show the view counter.
1
2
<span id="site-visits">Sitevisits: <span class="count">--</span></span>
<span id="page-views">Pageviews: <span class="count">--</span></span>
  • Add the following .js code to express_proj/public/javascripts/:

    Note:

    • I used Firebase SDK 9
    • The details of database read/write APIs could be found at Firebase Database APIs
    • You could of course test data read / write sepeartely before using the whole block
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.8.3/firebase-app.js';
import {
getDatabase, ref, get, set, child,
// eslint-disable-next-line import/no-unresolved
} from 'https://www.gstatic.com/firebasejs/9.8.3/firebase-database.js';

const viewCounter = async () => {
// The web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: 'your api key',
authDomain: 'your settings ',
databaseURL: 'xxx',
projectId: 'xxx',
storageBucket: 'xxx',
messagingSenderId: 'xxx',
appId: 'xxx',
measurementId: 'xxx',
};

// Initialize Firebase
const firebase = initializeApp(firebaseConfig);
const db = getDatabase(firebase, firebaseConfig.databaseURL);
const oriUrl = window.location.host;
const curUrl = oriUrl + window.location.pathname;

const readVisits = async (url, selector) => {
const dbKey = decodeURI(url.replace(/\/|\./g, '_'));
let count = 1;
const res = await get(child(ref(db), dbKey));
if (res.exists()) {
count = parseInt(res.val() || 0, 10) + 1;
}
await await set(ref(db, dbKey), count);
if (selector.length > 0) {
// eslint-disable-next-line no-param-reassign
selector[0].innerText = count;
}
};

readVisits(oriUrl, document.querySelectorAll('.post-meta #site-visits .count'));
if (curUrl && curUrl !== '_') {
readVisits(`page/${curUrl}`, document.querySelectorAll('.post-meta #page-views .count'));
}
};

viewCounter();
  • After the above steps, the view counter is ready to go :)

Extra issue: is it okay to expose Firebase apiKey?

When you see that I put apiKey etc. in a static .js file, you must have a question in mind: is that a security issue here? I had the same question. Then I found the following article: Is it safe to expose Firebase apiKey to the public?

The answer is a bit long, so I will sum up here: for a small size and not a critical site, it is okay to do thing like this. The apiKey here in Firebase is not like the traditional api keys we know, it is okay to expose it. All you need to do is to set up whitelist site for Firebase (that is why I mentioend earlier in the article that you could set the Firebase database rules for opening read/write public). Here is how you can do it in details:

  • Go to Firebase Console
  • Check Authentication Menu -> Sign-in method tab
  • Scroll down to Authorized domains
  • Click “Add Domain” button and add your domains (localhost is added as default, and I do not delete as it is needed for local testing)
Trulli
Set up whitelist site

The above should be okay for a small site. I am not going to over-engineering it, but you can always tailor the security rules accoriding to your business requirements :)

Comment and share

I have a Express server and recently I would like to integrate Hexo blog framework into the existing Express.js site, for example, make the blog accessable on express_site/blog. While exploring the feasibility, I realise that it is hardly to find a thorough tutorial of how to achieve it. There are some information can be found on:
Hexo Github Issue 3644 and x-heco-app-connect middleware. However, none of them offer a complete guide of seamlessly integrating Hexo blog into an Express server. For example, following the instruction provided by x-heco-app-connect middleware, the app will generate issues regarding routing. Therefore, I decide to write this blog to offer a tutorial of integrating Hexo into Express, i.e. make a Hexo blog as a route of existing Express server.

Trulli
Hexo under localhost:3000/blog

My way of achieving it is based on x-hexo-app-connect and some of the steps describe blow are based on the instruction provided by x-hexo-app-connect.

Getting Started

1.1 Make a sub-directory under the express project directory. e.g. we make it under experss_proj/blog, use this command under the project directory:

1
$ mkdir blog

1.2 Enter the command to install hexo-cli globally

1
$ sudo npm i hexo-cli -g

1.3 Go to the blog’s directory (created in step 1.1) and enter the following command in terminal to init Hexo:

1
$ hexo init

1.4 In the blog directory, enter the command in terminal to install x-hexo-app-connect package:

1
$ npm i x-hexo-app-connect --save

1.5 Create a index.js file in the blog’s root directory. e.g. if you want to make it using a bash terminal (Mac platform), enter this command below:

1
$ touch index.js

1.6 Fill in the index.js with the following code:

  • for the return part, it is to config the Hexo blog, the route is the most important, that is where you will configure how the Hexo blog should be visited from the original Express server. In my case, the blog will be visited via route express_site/blog
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    const Hexo = require('hexo');

    module.exports = (app) => {
    const blogDirPath = __dirname;
    const hexo = new Hexo(blogDirPath, {});
    // eslint-disable-next-line global-require
    return require('x-hexo-app-connect')(app, hexo, {
    // The Configs/Options
    log: false,
    compress: false,
    header: true,
    serveStatic: false,
    route: "/blog"
    });
    };
    1.7 In the app.js (the home js file of Express), add the following to use the x-hexo-app-connect in Express
    1
    2
    3
    4
    5
    6
    7
    const app = express();
    // Put it after app is initialized, as the app will be used as parameter
    const blogRouter = require('./blog/index')(app);

    ...
    app.use(blogRouter);

    1.8 This step is very important, it is to set “root” parameter in the _config.yml file under the root directory of Hexo. And set the root as /blog. If not set this root, the Hexo blog home page can be visited via express_site/blog, but when click the link of articles, categories, archives etc. the express will report 404 as the routes cannot be found
    1
    2
    3
    4
    # URL
    ## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
    url: http://localhost:3000/
    root: /blog # for locating themes static files (.css etc)
  • If do not set root as /blog, the following url will be generated as localhost:3000/all-categories which will lead to 404 error.
    Trulli
    ./blog/all-categories

1.9 Apply themes. You can just following the set up instruction of each specific theme, then it should be okay.
1.10 After all the above steps, run the Express server, if the terminal showes the following, then it means you are good:)

1
2
3
INFO  Validating config
INFO Start processing
INFO [Hexo-App-Connect] is running on route /blog

Hope this blog helps you in some way :)

Comment and share

My first blog

in Miscellaneous, Life Sitevisits: -- Pageviews: --

First Blog

It is Jingjie here, it is my first blog on my own blogging site.I have always been wanting to have a place where I can write and post my own blogs. instead of writing things here and there.

The reason of writing blog

I am a passionate software engineer and by nature of this area, I learned lots of thing online (i.e. I received help from others) and wrote down a great number of notes (mainly on my own OneNote) regarding the knowledge I acquired: for strengthening my understanding of thing learned and picking them up in the future.

And for all these days working on academia and industry, I have my own understanding of software, technology etc. I would like to share them with others, and hoping they will be kind of helpful in some way (i.e. I would like to return the favor).

For this blog site, I will post my understanding of computer and life as well. Things start :)

Trulli
Suprise of 2022:)

Comment and share

  • page 1 of 1
Author's picture

Jingjie Jiang


Find a place I love the most