2022年6月24日 星期五

Go開發筆記 - 使用 net/http 處理 URL Redirect 和 Cookie 之 Service Unit Test 需求

最近用 Golang 撰寫 Service Unit Test 時,練了一下 net/http 要如何處理 HTTP Response Header Location 的處理。主要是在使用 net/http 的 http.Client 時,可以加設定 CheckRedirect 的機制來阻擋 URL Redirect 的行為,藉以檢驗 URL Redirect 是否正確。

//httpClient := http.DefaultClient
httpClient := &http.Client{}

httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}

if jar, err := cookiejar.New(nil); err == nil {
httpClient.Jar = jar
}

如此,做 Service Unit Test 時,在發送 HTTP GET request or HTTP HEAD request 時,可以停下來,看看要跳轉到哪裡,以此判斷跳轉機制是否正常。

接著,碰到了另一個問題: 在 follow URL Redirect 後,似乎跳轉過程中產生的 Cookie 都沒有被記錄下來?例如最後的 response.Cookies() 輸出,的確只列出最後的 Response Cookies 資料。這時想要驗證中間的 Cookie 資訊,則需要瀏覽 httpClient.Jar 資料:

for _, c := range(httpClient.Jar.Cookies(res.Request.URL)) {
fmt.Println(c)
}

如此就可以搞定 URL Redirect 驗證,以及全部過程的產生的 Cookie 檢查!當然,若要更細膩地去追蹤每次 URL Redirect 時,產生的 Response Cookies 資料,可以透過 httpClient.CheckRedirect 那處理:

httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
for _, c := range (req.Response.Cookies()) {
fmt.Println(c)
}
}

參考資料:
  • https://pkg.go.dev/net/http#Client
  • https://cs.opensource.google/go/go/+/refs/tags/go1.18.3:src/net/http/client.go
  • https://cs.opensource.google/go/go/+/refs/tags/go1.18.3:src/net/http/client.go;l=493
  • https://cs.opensource.google/go/go/+/refs/tags/go1.18.3:src/net/http/client.go;l=811
  • https://pkg.go.dev/net/http/cookiejar#Jar.Cookies
  • https://cs.opensource.google/go/go/+/refs/tags/go1.18.3:src/net/http/cookiejar/jar.go

2022年6月21日 星期二

VIM 設定檔(vimrc)切換方式 @ macOS 12.4

由於 coding style 的規劃,需要調整 vim editor 的行為:

set tabstop=4
set shiftwidth=4
set expandtab

因此,設計一個 vim_env.sh 來做切換啟用:

% vim --version
...
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
  fall-back for $VIM: "/usr/share/vim"

% cat project_vimrc 
try
    source $VIM/vimrc 
catch
    echo "\$VIM/vimrc not found"
endtry

set tabstop=4
set shiftwidth=4
set expandtab

% cat vim_env.sh
#!/bin/bash

SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )";
alias vim='vim -u $SCRIPT_DIR/project_vimrc'
echo "Update vim environment (using 'type vim' to show raw command) "

% type vim
vim is an alias for vim -u $SCRIPT_DIR/project_vimrc

接著,就靠 alias 來啟用專案 vimrc

2022年6月19日 星期日

隔離險理賠 - 富邦疫苗隔離險理賠郵寄申請 時程約30天才開始審核


四月就被隔離了,恰好 110 年打疫苗前,保了個疫苗險,原本只是單純保個疫苗不良事件,殊不知翻出來看有隔離補償。找了個時間打電話問問看申辦流程,客服要求留完資料後,會有專人聯繫,可惜過了兩個月也沒接到過電話,現在疫情放緩,來把資料郵寄過去試試。

首先,先到 富邦產險 - 防疫險專區 網站,查一下理賠申請方式,內容都是建議,直接攜帶好相關證件直接到現場辦理。先來試試看郵件這招。

致電富邦產險客服(免付費電話,手機可打 0800-009-888 ),確認一下郵寄收件的切確地址跟收件人,於是得知台北地區就直接掛號寄到總公司即可。

地址:台北市中山區遼寧街179號7樓
電話:(02)66367890
富邦壽險 個人理賠部 收

至於文件方面,就下載一份理賠申請單填寫一下,再將身分證影本, 銀行帳戶影本和隔離簡訊列上,有順便把當初衛福部的隔離單印一下(六月下旬,點擊原本的簡訊,已經看不到帶有個人資訊的網頁內容),再看看是不是這樣就搞定。

後續大概寄出 20天後,突然想到查了一下,果真有一些進度,不錯,至少可以信件溝通了:



約30天後,收到簡訊通知,顯示開始審核:


最後,送件滿 3個月後,收到匯款通知。

參考資料:

2022年6月16日 星期四

C開發筆記 - 使用 JS Engine : Duktape 接收與傳遞 Javascript Object

對嵌入式設備來說,如果資源夠大的話,直接用 Node.js 絕對是個不錯方案,受限於硬體資源限制,採用了 Duktape JS Engine。

寫 C Code 操作 Duktape JS Engine 時,呼叫的方式還滿像以前學生時代寫組語的感覺,要先一步步把參數先配置好,接著在呼叫函示去運算。這次就筆記一下,如何從 JS Code 傳遞 Object 到 C Code,以及 C Code 要怎樣傳遞 Object 回 JS Code。

從 JS Code 傳遞 Object 到 C Code:

//
// _js_helper_fetch_url_more 是從 C Code 植入 function,並且接送一個 JS Object,有 url 跟 request_header 兩個屬性
//
if (typeof _js_helper_fetch_url_more !== "undefined") {
    var ret = _js_helper_fetch_url_more({
        url: 'https://ipinfo.io/country',
        request_header: [
            'Content-Type: HelloWorld',
            'X-MAN: HelloWorld',
        ],  
    }); 
    console.log(JSON.stringify(ret));
}

在 C Code 要取得傳進來的 JS Object,並存取 url 跟 request_header 兩個屬性:

if (duk_is_object(ctx, -1) && duk_has_prop_string(ctx, -1, "url")) {
    duk_get_prop_string(ctx, -1, "url");
    const char *url = duk_to_string(ctx, -1);
    duk_pop(ctx);
}

if (duk_has_prop_string(ctx, -1, "request_header")) {
    duk_get_prop_string(ctx, -1, "request_header");
    if (duk_is_object(ctx, -1) && duk_has_prop_string(ctx, -1, "length")) {
        duk_get_prop_string(ctx, -1, "length");
        int header_length = duk_get_int(ctx, -1);
        printf("#JS_Helper_Fetch_Url_More> access input_object.request_header.length: %d\n", header_length);
        duk_pop(ctx);

        for (int i=0 ; i<header_length ; ++i) {
            duk_get_prop_index(ctx, -1, i);
            const char *header_value = duk_get_string(ctx, -1);
            printf("#JS_Helper_Fetch_Url_More> access input_object.request_header[%d] = [%s]\n", i, header_value);
            duk_pop(ctx);
        }
    }
    duk_pop(ctx);
}

最後,想要從 C Code 傳遞一個 JS Object 回去的方式:

//
// 傳回 {"status": true, "errorCode": 0}
//

duk_idx_t obj_idx;
obj_idx = duk_push_object(ctx);

int errorCode = 0;
duk_push_int(ctx, errorCode);
duk_put_prop_string(ctx, obj_idx, "error_code");

if (errorCode == 0) {
    duk_push_true(ctx);
} else {
    duk_push_false(ctx);
}
duk_put_prop_string(ctx, obj_idx, "status");

更多完整資訊,請參考:github.com/changyy/study-duktape

2022年6月12日 星期日

PHP開發筆記 - 書:現代PHP, 新的特點及良好習慣(Modern PHP: New Features and Good Practices)

書:現代PHP, 新的特點及良好習慣(Modern PHP: New Features and Good Practices)

幾週前,找資料時看到了這本書,且幾年前也有人在 IT 鐵人賽 提到。這是一本 2015 年 02 月歐萊禮出的書。只是近幾年已經有許多熱門的語言跟誇架,如 Python, Ruby(RoR), Javascript(Node.js), Golang,似乎誰也沒在記得 PHP、Facebook 出的 HHVM?我也是翻了書才知道還有個 Hack 語言。
沒想到自己已經寫了超過15年PHP了吧?工作上真的還滿夠用,偶爾寫寫 python 跟 php 工具做事。但看了這本 Modern PHP 後,反而補充一段遺失的知識,算是滿值得的。書中的內容對我來說大概有50%以上是已知的,很快就看完了,屬於工作上或學生時代就知道的事,也代表持續使用 PHP 多少都會有所成長,但實在不如讀書吸收的知識效率高,翻出看個小時就就獲得幾年功力。

另外一提,書中有些工具教學的範例套件不見得是現在熱門的工具,建議使用上時還先找一下網路上資源,例如當紅的 PHP Mail 套件就是 PHPMailer ,我也在 2015 年用 PHPMailer 幫公司開發一套可發送百萬 EDM 的小服務,近年則是被同事擴充成可自動化排程架構了。

總之,我還是買了一本來收藏,也詢問 碁峰圖書 得知沒有電子書服務(早年 O'Reilly 有可以下的電子書,並靠 Social DRM,現在則改成訂閱制)。往後則是使用PHP語言時,要時時提醒自己多用 composer 管理做事,包括工具開發等。如果持續朝向如何規範更加的產出程式碼品質時,那真的有源源不絕的目標可以邁進的。

2022年6月10日 星期五

PHP 開發筆記 - 使用 PHP-CS-FIXER 維護團隊的 Coding Style

使用 PHP 語言開發網站服務時,採用各類框架後,其撰寫風格已定下八九成了,那為何還需要呢?主要用來提升產出品質。就像程式碼都能動,QA也驗證過,也上線服務百人千人了,這時有測試涵蓋率資訊,可以讓未來增減功能時,更加大膽。

稍微研究後,在 PHP 語言上,可以直接使用 PHP Coding Standards Fixer 工具,整體上還滿舒適的,裡頭有提到非常多編碼風格檢驗,基本上用預設的即可。備忘一下:

首先故意把 php-cs-fixer 安裝在程式碼上一層名為 tools 目錄,且 tools 內有 composer.phar 工具可用:

% mkdir -p tools/php-cs-fixer
% php tools/composer.phar require --working-dir=tools/php-cs-fixer friendsofphp/php-cs-fixer

先列出當前目錄中,有哪些要修改的項目:

% cd src
% ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff .

對當前目錄進行修正的用法:

% cd src
% ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix .

接著,可以把上面兩個指令包在 composer.json 中,靠 run-script 處理:

% cd src
% cat composer.json | jq '.scripts'
{
  "test": "phpunit",
  "cs-diff": "../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff .",
  "cs": "../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix ."
}

使用方式:

% ../tools/composer.phar run-script cs-diff
> ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff .
Loaded config default.
Using cache file ".php-cs-fixer.cache".

Checked all files in 0.032 seconds, 12.000 MB memory used

% ../tools/composer.phar run-script cs     
> ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix .
Loaded config default.
Using cache file ".php-cs-fixer.cache".

Fixed all files in 0.006 seconds, 12.000 MB memory used

接著,可以評估一下自己打算用哪些規範,從 PHP Framework Interop Group (簡稱PHP-FIG) 常見的推薦用法,就是要來個 PSR-12 就對了:

% cat test.php 
<?php

    $x                = "hello world";

     $y =            "123";

% ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --using-cache=no --rules=@PSR12  -vvv test.php
PHP CS Fixer 3.8.0 BerSzcz against war! by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 7.4.29
Loaded config default.
.                                                                                                                           1 / 1 (100%)
Legend: ?-unknown, I-invalid file syntax (file ignored), S-skipped (cached or empty file), .-no changes, F-fixed, E-error

Checked all files in 0.005 seconds, 12.000 MB memory used

規則嚴一點,使用 Symfony framework 語法:

% ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff --using-cache=no --rules=@PSR12,@Symfony -vvv test.php 
PHP CS Fixer 3.8.0 BerSzcz against war! by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 7.4.29
Loaded config default.
F                                                                                                                           1 / 1 (100%)
Legend: ?-unknown, I-invalid file syntax (file ignored), S-skipped (cached or empty file), .-no changes, F-fixed, E-error
   1) web/test.php (single_quote, binary_operator_spaces)
      ---------- begin diff ----------
--- /Volumes/Data/project/src/test.php
+++ /Volumes/Data/project/src/test.php
@@ -1,5 +1,5 @@
 <?php
 
-    $x                = "hello world";
+    $x = 'hello world';
 
-     $y =            "123";
+     $y = '123';

      ----------- end diff -----------


Checked all files in 0.011 seconds, 12.000 MB memory used

進行修正:

% ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --using-cache=no --rules=@PSR12,@Symfony test.php
Loaded config default.
   1) web/test.php

Fixed all files in 0.011 seconds, 12.000 MB memory used

% cat test.php 
<?php

    $x = 'hello world';

     $y = '123';

更多語法修正可以參考 github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/doc/rules/index.rst 解說,例如變數運算時的空白規劃,就可以參考 binary_operator_spaces 的設計。

2022年6月8日 星期三

樊登說書

圖:樊登說書 實體勳章 非同凡響

約莫 2021 春天起入坑,接著靠運動時期清書,應該沒八個月規律地刷完一遍,不到四百本書,正在進行複習第二遍,未來就進入每週聽一本書,然後沒啥 podcast 想聽時,繼續挑有興趣的來複習。

從樊登說書的熱門書籍清起,可以很清楚地看到 TA 已經是親子學習為主、商業工具書為輔,但無論如何,都仍是人性議題,帶團隊跟養小孩都還是相互呼應的,稱不上衝突。例如如何鼓勵員工往前邁進,等同於鼓勵小孩如何進步一樣。

我以前也覺得網路上有很多文料,舉凡工作技術文、親子、科普等,認為不需要翻書了,直到被大學室友提醒:片段的文章,跟從頭到尾的書籍,還是有很大的不一樣。現代人的習性也慢慢被切割成只能閱讀零碎的片段。

樊登說書其實厲害的就樊登一人,自己打通任督二脈,以論語中庸當內力,在吸取中內外的書籍,的確如他所言,這個事業搞起來後,自己受益最大,也開始慢跑健身少吃麵食,也持續享受著看書、講書的興趣,推掉不必要聚會,並精實的呼應著讓人一年讀 52本書,另外,也朝向不吃光用戶眼光跟時間,吸收完知識後,關掉 app 去做正經事。其實看一個人功力強不強,就像看廚師炒飯一樣,一本經典書籍內容那麼充沛,有幾位網紅可以好好用 30 分鐘介紹一本書?又有幾位網紅可以串起各類書籍,並且前後呼應而不是自相矛盾?

回顧起 2021 年接觸的 app ,應當就這 app 受益最大。從商務工具書,提醒自己溝通時要著重事實的呈述而非情緒,親子相處時,要多留點時間給小孩,不只陪伴,還包括等待小孩成長。我想,我還是會繼續複習完成二刷吧


樊登說書 熱門書籍 Top 100 清單(說書時間、書名):

2017-03-18 正面管教

2016-07-30 非暴力沟通

2017-04-08 亲密关系

2018-04-28 终身成长

2019-03-30 逆商

2018-12-15 父母的语言

2016-11-19 刻意练习

2015-10-24 关键对话

2017-12-09 可复制的领导力

2017-10-07 高效能人士的七个习惯

2017-01-07 如何让你爱的人爱上你

2018-06-09 即兴演讲

2017-05-20 自卑与超越

2016-01-01 如何培养孩子的社会能力

2019-03-02 应对焦虑

2018-10-27 活好

2013-12-03 你就是孩子最好的玩具

2019-06-01 不管教的勇气

2019-07-20 掌控习惯

2016-12-10 不吼不叫

2016-07-16 如何说孩子才会听,怎么听孩子才肯说

2019-01-12 感受爱

2015-09-18 幸福的婚姻

2018-11-03 认知天性

2020-04-18 陪孩子终身成长

2016-10-15 销售就是要玩转情商

2019-10-12 不妥协的谈判

2019-03-16 列奥纳多·达·芬奇传

2020-01-04 我们都曾受过伤,却有了更好的人生

2019-04-06 能力陷阱

2021-07-10 人生只有一件事

2019-06-15 自尊

2019-08-03 事实

2019-11-09 被忽视的孩子

2018-03-03 他人的力量

2019-04-27 低风险创业

2019-06-08 高效休息法

2020-02-29 思维的囚徒

2019-02-16 用事实说话

2019-05-04 坚毅

2020-09-19 自驱型成长

2020-09-26 活出心花怒放的人生

2018-12-08 思辨与立场

2013-11-25 幸福的方法

2016-02-04 我的情绪为何总被他人左右

2020-09-12 洞见

2018-01-06 反脆弱

2019-05-11 原生家庭

2018-07-07 活法

2019-08-31 解码青春期

2014-01-04 第3选择

2020-02-08 爱、金钱和孩子

2020-04-11 意志力

2018-10-13 掌控谈话

2018-10-06 运动改造大脑

2019-08-17 顾客为什么购买

2021-09-11 心态

2019-11-23 孔子传

2017-11-18 思考,快与慢

2019-04-20 世界观

2020-05-23 斯坦福高效睡眠法

2016-03-26 干法

2016-06-25 你要如何衡量你的人生

2018-08-11 热锅上的家庭

2015-07-03 次第花开

2021-05-22 解惑:心智模式决定你的一生

2018-09-22 一平方米的静心

2020-08-08 陌生人效应

2019-07-13 学会吃饭

2020-09-05 曾国藩的正面与侧面

2019-08-10 身为职场女性

2020-06-20 与内心的恐惧对话

2017-08-05 少有人走的路

2019-12-14 幸福的陷阱

2019-03-23 欲罢不能

2016-12-03 销售洗脑

2019-07-27 道德经说什么

2018-12-01 苏东坡传

2019-03-09 你要的是幸福,还是对错

2019-04-13 掌控

2021-04-17 你好,小孩

2020-11-28 内在动机:自主掌控人生的力量

2018-11-10 扫除道

2015-02-06 叛逆不是孩子的错

2021-05-15 考试脑科学

2018-01-27 深度工作

2018-03-24 心流

2021-04-24 如何克服社交焦虑

2019-02-23 高能量姿势

2019-09-07 分手后,成为更好的自己

2014-03-14 管理十诫

2021-03-20 幸福关系的7段旅程

2016-05-06 养育女孩

2020-07-25 学习的格局

2015-12-12 瞬变

2019-11-16 你为什么不道歉

2017-12-02 恰如其分的自尊

2017-01-21 王阳明哲学

2020-03-28 弹性

2019-05-18 有限与无限的游戏