Posted on Leave a comment

How To Redirect Page/Post to Other URL Without Plugin

If you need a quick way to redirect your page, posts to other URL, this is the place.

Simply put the code below to your page/post and you’ll get the redirection.

<script>
setTimeout(function(){
window.location.href = "https://google.com/";

}, 5000);
</script>

There are something you need to know:

  • Replace the number 5000 with the number of milliseconds you want to delay the redirect. If you want 10 seconds, put in 1000.
  • If your code is already inside a <script> block, don’t include the <script> and </script>
  • The code doesn’t appear visually on your site so don’t worry about the appearance of your page/post.
Posted on Leave a comment

Setup MariaDB Galera Cluster in 5 Minutes

mariadb galera cluster setup

Recently, I dived into high availability systems. Among Solr, Redis… MariaDB is a major concern. I followed quite many tutorials on the internet but without luck. I thought to myself, setting up MariaDB Galera cluster must be hard. However, it turned out quite simple. In fact, you don’t need to spend more than 5 minutes to setup a cluster and get it up and running.

Requirements for MariaDB Galera cluster

To run a MariaDB Galera cluster, you must have at least 2 nodes. All nodes must be running the same MariaDB version. In addition, you need to open some specific ports between the nodes to let the cluster to form. Here are the ports:

  • 3306 For MySQL client connections and State Snapshot Transfer that use the mysqldump method
  • 4567 For Galera Cluster replication traffic. Multicast replication uses both UDP transport and TCP on this port.
  • 4568 For Incremental State Transfer.
  • 4444 For all other State Snapshot Transfer.

Setting Up MariaDB Galera Cluster on The First Node

On the first node, edit your mysql configuration file and put the following content to the file /etc/mysql/my.cnf

[mysqld]
user                              = mysql
bind-address                      = 0.0.0.0
wsrep_on                          = on
wsrep_provider                    = /usr/lib/galera/libgalera_smm.so
wsrep_sst_method                  = rsync
wsrep_slave_threads               = 4
default_storage_engine            = innodb
binlog_format                     = row
innodb_autoinc_lock_mode          = 2
innodb_flush_log_at_trx_commit    = 0
sql_mode=NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
open_files_limit=750000
max_connections=30000
default_authentication_plugin=mysql_native_password
#innodb
innodb_lock_wait_timeout = 5
# Galera Cluster Configuration
wsrep_cluster_name="my_cluster"
wsrep_cluster_address="gcomm://"
#172.31.29.119
# Galera Synchronization Configuration
wsrep_sst_method=rsync

# Galera Node Configuration
wsrep_node_address="Node_IP_ADDRESS"
wsrep_node_name="Node_IP_ADDRESS"
mariadb galera cluster setup on the first node

Also, on the first node, you must tell mysql that it is safe to start the new MariaDB Galera cluster from this node. Thus, edit the file /var/lib/mysql/grastate.dat and edit the last line (safe_to_bootstrap) from 0 to 1 (if it is set to 0):

# GALERA saved state
version: 2.1
uuid:    fc43dfacg-c4442-32e4-9e43-tghf6323bn4
seqno:   -1
safe_to_bootstrap: 1

Depends on what user is running mysql service, you need to give it the write permission to grastate.dat file. Otherwise, it cannot start the cluster. If you need a quick fix, just run the following command:

chmod 777 /var/lib/mysql/grastate.dat

Now, you can start the node by issuing this command:

systemctl restart mysql

If everything is ok, you should not see any error message :p.

If you run

systemctl status mysql

You should see something like this:

mariadb galeara cluster started succesfully

Setup MariaDB Glaera cluster on other nodes

Now you have your first node up and running. Setting up other nodes should be simple.

In your /etc/mysql/my.cnf enter the following content:

[mysqld]
user                              = mysql
bind-address                      = 0.0.0.0
wsrep_on                          = on
wsrep_provider                    = /usr/lib/galera/libgalera_smm.so
wsrep_sst_method                  = rsync
wsrep_slave_threads               = 4
default_storage_engine            = innodb
binlog_format                     = row
innodb_autoinc_lock_mode          = 2
innodb_flush_log_at_trx_commit    = 0
sql_mode=NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
open_files_limit=750000
max_connections=30000
default_authentication_plugin=mysql_native_password
#innodb
innodb_lock_wait_timeout = 5
# Galera Cluster Configuration
wsrep_cluster_name="my_cluster"
wsrep_cluster_address="gcomm://IP_OF_THE_FIRST_NODE"

# Galera Synchronization Configuration
wsrep_sst_method=rsync

# Galera Node Configuration
wsrep_node_address="IP_OF_THIS_NODE"
wsrep_node_name="IP_OF_THIS_NODE"

Replace the IP_OF_THE_FIRST_NODE and IP_OF_THIS_NODE with their respective values.

In my case, my second node IP is 192.168.100.5, the configuration looks like this:

Setup MariaDB Galera Cluster in 5 Minutes 1

Save the file and you are ready to start this node:

systemctl restart mysql

Now, if you run:

systemctl status mysql

You should see something similar to this:

node successfully join galera cluster

From the log, you can see the status like joined -> synced. That means the node has successfully joined and synced with the cluster.

Now, if you add data to one of nodes, the other nodes will update automatically.

Now, your cluster has two nodes. If you want to add more nodes, just repeat the setup on other nodes above.

Note on restarting the first node

When your first node of the MariaDB Galera cluster is down, you cannot restart it as with other node. Why? It is because you still have the setting “safe_to_bootstrap” set to 1. When your first node of the cluster is down, simply set this to 0 and restart mysql.

Conclusion

As you can see, setting up MariaDB Galera cluster is quite simple. My setup has two nodes. However, you can add as many new nodes as you prefer. In case one node is down, there are other nodes still running that help you continue to serve your customers.

Posted on Leave a comment

Create SSL Site At Your Localhost With MAMP/NodeJS In 5 Minutes

ssl on localhost

As a software developer, I usually found myself frustrated looking at the browser with the following notice when loading my local site:

Create SSL Site At Your Localhost With MAMP/NodeJS In 5 Minutes 2

Yes, the infamous “Your connection is not private notice”. You can bypass that by typing “THISISUNSAFE” in Chrome/Edge. However, a hack is still a hack. You deserve a good solution.

Today, I’m the solution provider. Let’s walk with me to make https://abc.local load with SSL like a normal secure site.

Here is the environment:

  • OS: MacOS 10.15.3
  • MAMP running Apache 2.4

Your environment may be different, however, the method is applicable to other environments running Apache.

Let’s get started.

How to configure Apache 2.4 on MAMP to enable local secure site

Step 1: Add your site to /etc/hosts

This is the easiest one. To host a site on your localhost, you need to add a record of that site to /etc/hosts file so when you type that site into your browser address bar, the browser know to look for it at your localhost.

In our case, we need to add abc.local to /etc/hosts.

Let’s open /etc/hosts by typing:

sudo vim /etc/hosts

I’m using vim as the text editor, however, you can use any other program you like. The important thing to note is opening it with sudo or you cannot save your changes.

On Windows, the equivalent of /etc/hosts is C:\Windows\System32\drivers\etc\hosts. Just open your notepad with Administrator right and then open the hosts file and you’ll be fine.

Let’s insert:

127.0.0.1 abc.local

at the end of the hosts file and save then close it. Like this:

Create SSL Site At Your Localhost With MAMP/NodeJS In 5 Minutes 3

And you are done with step one!

Step 2: Enable NameVirtualHost, SSL, Vhosts In Apache

In this step, we are going to modify some of Apache’s configurations so it’ll accept SSL, VirtualHost records and Named virtual host. If you have been using MAMP (or XAMPP) for a while, you know how to access the server via http://localhost… However, to access localhost with custom domain name like abc.local, you need to do the following:

First, open the file at /Applications/MAMP/conf/apache/httpd.conf with your favorite text editor. I’ll use Vim as usual.

Now, look for the following lines:

Include /Applications/MAMP/conf/apache/extra/httpd-ssl.conf
 Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf

And remove the # character at the beginning of those lines.

Save the file and quit.

Next, let’s open /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf to enable name based virtual hosting.

Let’s add the following lines if they are not available or commented:

NameVirtualHost *:80
NameVirtualHost *:443

Then save the file and quit.

You are ready for step 3!

Step 3: Generate your self signed SSL certificates

To generate a certificate for your site, open terminal and run the following command:

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout abc.local.key -out abc.local.crt -extensions san -config \
  <(echo "[req]"; 
    echo distinguished_name=req; 
    echo "[san]"; 
    echo subjectAltName=DNS:abc.local,DNS:developer.abc.local,DNS:www.abc.local,DNS:api.abc.local,IP:10.0.0.1,IP:127.0.0.1
    ) \
  -subj "/CN=abc.local"

As you can see, in the script, I didn’t just generate certificate for abc.local. I also generate certificate for a bunch of subdomains like www, developer… If you need SSL for subdomain, you can add more DNS record. One caveat though, you cannot add subdomain of subdomain. For example, info.developer.abc.local would not work.

You can also notice that the params -day 3650. That means the certificate is valid for 10 years! How about 100 years? Just replace 3650 with 36500.

generating ssl certificate for the local site

As you can see, I’ve successfully generate the certificate files with the command. You’ll get two files: abc.local.key and abc.local.crt. Let’s put these two files in /Applications/MAMP/conf/apache/ssl. If this folder is not available, you need to create it.

Phew! You’ve done a lot. There is two more steps before you can load your site over SSL. Let’s get to step 4!

Step 4: Create your virtual host record in httpd-ssl.conf

Remember httpd-ssl.conf? You’ve seen this file earlier in the post. Let’s open it and add the following record at the end of the file:

<VirtualHost _default_:443>
	ServerName abc.local
	ServerAlias abc.local
	DocumentRoot "/Applications/MAMP/htdocs/abc/"
	ErrorLog "logs/abc.local-error_log"
	CustomLog "logs/abc.local-access_log" common

	SSLEngine on
	SSLCertificateFile  "/Applications/MAMP/conf/apache/ssl/abc.local.crt"
	SSLCertificateKeyFile  "/Applications/MAMP/conf/apache/ssl/abc.local.key"
</VirtualHost>

Let’s safe the file and quit. Now, it’s time to work on the certificate.

Step 5: Trust your certificate

Since your certificate is self-signed, you need to manually trust it. Let’s open the abc.local.crt file by double clicking on it:

Install the certificate

Now, select System as Keychain and click on Add. The system will ask you to enter password. Do as asked to complete this step.

Now, look for abc.local in the list of certificates and double click on that.

Trust the self-signed certificate

Select Always trust and close the window. You may be asked to enter your password again. Do so as this is the last step you need to work with the certificate!

Final step: Restart MAMP and view your site

Now, go to your browser and type https://abc.local, you should see the site is successfully loaded without any security warning. Clicking on the lock icon, you’ll see the site is trusted:

SSL certificate is working on localhost mac MAMP

You may see a 404 page. That’s expected since our path to the site is not available yet (htdocs/abc). Let me create a very quick index.html in htdocs/abc so you’ll see the content.

Hello from http on localhost MAMP

That’s it! now you have the SSL certificate valid for 10 years!

Bonus tips: How to make SSL works on webpack-dev-server

Now you know how to create secure site on localhost with MAMP. Using the same certificate files, you can make any sites with webpack dev server or other nodejs based app secure on localhost too.

In this example, I’m going to create a new Vue cli project and also create a vue.config.js file at the project root. The content of the file is simple as follow:

var fs = require('fs')
module.exports = {
    devServer: {
        host: 'abc.local',
        port: 8081,
        https: true,
        key: fs.readFileSync("/Applications/MAMP/conf/apache/ssl/abc.local.key"),
        cert: fs.readFileSync("/Applications/MAMP/conf/apache/ssl/abc.local.crt"),
    }

}

As you can see, the key is to set https to true and point key and cert options to the files we have created previously.

When I run the app with npm run serve, you can see that the app is served over https and there is no certificate problem:

Create SSL Site At Your Localhost With MAMP/NodeJS In 5 Minutes 4

Conclusion

I don’t know about you but the day I discovered installing SSL for my local site this easy, my life changed. I no longer have to rely on options like Flywheel’s local just to get the https to work. Hopefully, this tutorial helps you has much it helped me. If you have any suggestions, please let me know in the comment below.

Posted on Leave a comment

List Of All Words In English And More

Recently, during my journey to create a better English dictionary for ESL, I came across a need of getting the pronunciation of all words in English. That means all: single, plural, past tense… are included.

My approach was to get text from books, articles and of course, Wikipedia.

As a result, I extracted over 26 million sentences. These sentences are supposed to be clean (no special characters, no encoding errors).

From these sentences, I ran a job to get all the unique words. The method is quite simple, I split the sentences into single word with space delimiter. Spaces, punctuation are removed, of course.

The result is over 1.9 million unique words. As a went through the list, a portion is not words. Most of these ones have two letters. They could be abbreviations, ordinal number…

However, all English words should be in this list.

My next step would be creating recordings for these words so learners know how to speak them correctly.

If you are interested, you can download the database here. It is a PostgreSQL backup. You can import with pgAdmin.

Posted on Leave a comment

Passing Data Back And Forth Between Child and Parent in Vue

If you are developing in Vue long enough, you will meet a scenario when you need to pass data from child to parent or parent to child. That’s what I’m going to show you in this post. I’ll make it short and to the point so you can continue working on your great project fast.

Passing data from parent to child in Vue

Passing literal value

To pass data from parent to child, you need to use props. Let’s take the following example:

I have a child component called Cow like this:

<template>
    <div >
        <h3>{{ parentMessage }}</h3>
    </div>
</template>


<script>
export default {
    name: 'Cow',
    props: {
        parentMessage: String
    }
}
</script>

As you can see, the Cow component has a prop called parentMessage. In the parent component, we can pass data to Cow using this prop.

<template>
  <div id="app">
    <Cow parentMessage="I am a cow" />
  </div>
</template>

Then, you see the message appears as expected:

Vue passing literal props

It’s easy, isn’t it?

Updating props

What if you want to change the prop to something else? It’s quite simple, fortunately.

First, let’s create a data property in the parent component called newParentMessage. We are going to bind this property to the Cow’s prop.

In the parent component, it looks like this:

<Cow :parentMessage="newParentMessage" />

You can see that we put the colon at the beginning of the prop. This signifies we are binding the prop to a variable, not literal value as before.

Let’s create a new button in the parent component so when we click on that, the message to Cow component changes.

<button>Change parent message</button>

We need to create a click handler for this button in the parent component. Let’s call it changeParentMethod. Let’s change the message to “I’m just a poor cow”:

changeParentMessage() {
      this.newParentMessage = "I'm just a poor cow"
    }

We also need to bind the click handler to the button. So, this is the final code of the button:

<button @click="changeParentMessage">Change parent message</button>

Here is what the page look like:

Passing Data Back And Forth Between Child and Parent in Vue 5

If I click the button now, you’ll see that the message is changed.

Vue send data from parent to child

We have successfully pass data from parent to child. Let’s tackle the next challenge: passing data from child component to parent.

When you need to pass data from child to parent in Vue, use $emit. What $emit does it to send a event and in the parent component, you need to have a event handler to catch that event.

Sounds confusing? Let’s see a graph:

Sending data from child to parent component with event

Still confusing? Let’s code!

So currently, the cow message is “I’m just a poor cow”. What if since the start of this post, the cow has been working insanely and got rich? It feels the need to update the status to parent saying: “I’m not poor anymore”.

Let’s help the cow do that. He’s a cool cow.

In the Cow component, let’s create a button so we can send the update. On this button click we will emit an event called update_cow_status along with the data it wants to send.

<button @click="updateFinancialStatus">Update cow status</button>

Next, we need to create the function updateFinancialStatus in Cow component to actually emit the event update_cow_status.

updateFinancialStatus() {
            this.$emit('update_cow_status', {
                message: "I'm not poor anymore",
                netWorth: "$400Bn, with a B!!!"
            })
        }

As you can see, we emit the event along with a data object. The next task is to get the data in parent.

In the parent component, let’s register a handler for update_cow_status event. This is how you do it:

<Cow @update_cow_status="getCowMessage" :parentMessage="newParentMessage" />

As you can see, you need to put the event name in the Cow component. Let’s create the getCowMessage in parent’s methods. I’ll keep it simple to just log the message from Cow.

getCowMessage(message) {
        console.log(message)
    }

Now, let’s see our page:

Passing Data Back And Forth Between Child and Parent in Vue 6

When I click on Update cow status button, I’ll get the following data in the console:

Passing data from child component to parent in Vue

As you can see, we have successfully passed the data from child component to parent with $emit.

Source code

If you need the full source code, you can download it here:

Conclusion

Passing data from child to parent and parent to child is very useful when working on small projects. In larger projects, you might want to use Vuex to store and update data and share such data between components.