Localhost or Heroku?讓程式判別是否在heroku上運行的辦法!(Alpha camp core final)

這標題我相信看到的人會有些黑人問號,但卻是我在做AC學期三期末考時碰到的一個小問題,還請容我緩緩道來。 如果只想看要怎麼讓node判別是否在Heroku上運行的解法可以拉到最後。

緣起

其中一個題目是短網址產生器,撰寫程式碼的過程沒什麼問題,基本的程式邏輯會是這個樣子。
使用者輸入網址->若在資料庫內已有資料->回應對應的短網址
使用者輸入網址->若在資料庫內沒有資料->將本地的位置+產生的urlCode存入資料庫->導向對應的endpoint->回傳給使用者。

舉個例子來說,當使用者輸入 https://www.youtube.com 時,會回傳類似
http://127.0.0.1/Y5ms8 的結果,這看起來沒什麼問題,但題目要求要同時部署到heroku上就會產生一個小麻煩了。原因很簡單,從上面這簡單的例子可以看出短網址的組成只有兩個部分
本地伺服器位置+產生的urlCode,也就是說今天搬到heroku上運行後,雖然不會報錯,但產出的網址還是會類似 http://127.0.0.1/Y5ms8 而非像是 https://arcane-tor-34628.herokuapp.com/Y5ms8 的東西,這下可就尷尬了。

問題解析

問題其實相當的單純,我們先看一下原始的程式碼是怎麼寫的

//將產生的urlCOde與baseUrl結合,此時的baseUrl為 "http://127.0.0.1:3000" 
const shortUrl = baseUrl + '/' + urlCode;

//將產生的短網址等資訊存進資料庫
let url = new Url({
          longUrl,
          shortUrl,
          urlCode,
          date: new Date()
        });
await url.save(); 

也就是說,當前的程式碼並沒有顧及到程式是在那裡運行的!它總是會回傳baseUrl + urlCode的組合,於是這就產生了兩種不同的思考方向去解決題目的要求。

方法一,暴力解法:直接做兩種版本,本地版本&Heroku版本

我知道方法一聽起來很~~~蠢,不過倒不失為一個最終手段,寫程式的前輩常常告訴我們先求有再求好,現在既然已經有個保險方案便可以放在心裡最為不得已的備案,英文有句話是這麼說的
“It’s like your fat pants,you are not gonna wear them,but you’re glad to know where they are."
用來形容這情況再合適不過了。

方法:讓程式判別所使用的伺服器並產生對應的短網址

這種想法就合理得多了,基本上一模一樣的東西做兩份根本是討打嘛!
此解法中虛擬碼的邏輯大概會像以下這樣

if 我在heroku上運行
  { const shortUrl = herokuUrl + '/' + urlCode  }
else
  { const shortUrl = baseUrl + '/' + urlCode }

那剩下的部分就只是要找出讓node知道怎麼判別運行環境這點即可!

解法:設置Heroku環境變數

過程中我嘗試了幾種不同的方式,最終覺得這個做法最為單純直觀。
如果是AC的學生,應該對設置環境變數不陌生,也就是利用process.env.變數名稱 來隱藏一些敏感資訊,heroku上自然也有類似的設定,你可以透過下方的指令設定環境變數在heroku上使用

heroku config:set 變數名稱 = 變數值

i.e
heroku config:set IsHeroku = true
console.log(process.env.IsHeroku) //true   

藉由這樣的環境變數設置,由於僅在heroku上有用,本地端使用時將會辨識為undefined,了解到這些後便可以修改我們的程式碼囉!

//首先設定環境變數,在終端機輸入以下指令
heroku config:set HEROKU = true 

//修改對應的程式碼
let shortUrl; 
if (process.env.HEROKU) {
          shortUrl = herokuUrl + '/' + urlCode;
 } else {
          shortUrl = baseUrl + '/' + urlCode;
        } 

結語

如何? 完全運用課程所學就解決了這個小問題~!比起做兩個版本的解法來說專業多了吧!
整個解題過程會再次發現虛擬碼確實有它的用處在,Stackoverflow中也不乏用虛擬碼進行提問的網友。重點還是在於徹底釐清自己的問題,理解自己目前的癥結點是程式邏輯還是語法工具的不足,這樣關鍵字也會比較好下,比方說當我知道我目前的癥結點後,我採用的關鍵字便是"node localhost heroku",很快的便找到與我有相同問題的網友並開啟了一連串的解法試驗,最終找到自己最滿意的做法。 很多時候你手中掌握的工具其實已經足夠了,你只是需要換個角度去看問題,網友提供的意見則能幫助你快速的從不同角度看待同一個問題,這也是寫程式的醍醐味~!
若你是AC的學生,相信這個做法能幫助你在期末作業時省下一些功夫:P 祝學習愉快!

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s