close

有支有陣子沒怎麼用到的程式忽然無法完整跑完,一開始看到 Apache 上的錯誤訊息寫這樣:

[Tue Jun 02 12:35:38.163897 2020] [proxy_fcgi:error] [pid 000000:tid 999912345678900] (70007)The timeout specified has expired: [client 127.0.0.1:12345] AH01075: Error dispatching request to : (polling)

大部分的文章說是需要把逾時的時間拉大一點,讓程式有機會可以慢慢跑完,譬如去修改 Apache 的 config 裡的以下值:

  • Timeout 
  • ProxyTimeout 
  • FcgidIdleTimeout
  • FcgidProcessLifeTime
  • FcgidConnectTimeout
  • FcgidIOTimeout

(可能會在 httpd.conf 或 fcgid.conf 裡,視之前設定的位置而定)

 

但是因為這是一個小~小~的程式,我覺得應該不至於需要那麼多的資源與時間,所以轉而檢查了一下程式。後來發現是卡在 Google reCAPTCHA 要向 Google 驗證時,會跑個大約 60 秒後才吐 Exception。(視 Web Server 與 PHP 可接受的逾時時間而定)

看了一下同事的寫法和我的寫法,我在兩年前是這樣寫的:

<?php
$gRecaptchaResponse = $_POST["g-recaptcha-response"]; // 從前端送來的 Google reCAPTCHA 表單驗證值 
$reCaptchaUrl = "https://www.google.com/recaptcha/api/siteverify"; // Google Verify URL
$secret = "(Google reCaptcha Key)"; // Your Key
$curl = curl_init();
// 我原本的寫法

curl_setopt($curl, CURLOPT_URL, $reCaptchaUrl."?secret=".$secret."&response=".$gRecaptchaResponse); // Using GET method
// --------------------
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
$result = curl_exec($curl);
?>

而我同事的寫法是這樣,我們的差別在於我用了 GET、他用了 POST 向 Google 進行驗證:

<?php
$gRecaptchaResponse = $_POST["g-recaptcha-response"]; // Google
$reCaptchaUrl = "https://www.google.com/recaptcha/api/siteverify"; // Google Verify URL
$secret = "(Google reCaptcha Key)"; // Your Key
$curl = curl_init();
// 從這裡開始不一樣

curl_setopt($curl, CURLOPT_URL, $reCaptchaUrl);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT , 5); //to connection Google Recaptcha server in 5 seconds.
curl_setopt($curl, CURLOPT_TIMEOUT, 10); // to get response from Google Recaptcha server in 10 seconds.
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query(array("secret"=>$secret, "response"=>$gRecaptchaResponse)));
// --------------------

curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
$result = curl_exec($curl);
?>

上網查一下,在 stackoverflow 看到也有人一年多前在問 "Recaptcha v2 verification",回答者說對 server 要驗證那段一定要用 POST。

在 Google reCAPTCHA 的 developer guides 上面沒有看到特別說什麼時候起要改成用 POST,不過 "Verifying the user's response" 這段是直接指定一定要用 POST 進行驗證。

修改後就好了~感謝世上有 Google 大神與強者我同事。

 

 

(2020/12/22 update!) 發現在 IE 裡,前端的 JavaScript 無法正確初始化 Google reCaptcha,會出現錯誤訊息:「物件沒有支援這個屬性或方法 'querySelector'」(Object doesn't support property or method 'querySelector')

因為這個錯誤訊息是來自於 Google reCaptcha 的核心 api.js 被中斷了,所以要初始化 Google reCaptcha 的前端語法根本執行不了:

grecaptcha.ready(function() {
    grecaptcha.execute('replace_to_your_recaptcha_token', {action: 'form_submit_button'}).then(function(token) {
        $("#g-recaptcha-response").val(token);
    });
});

按 F12 打開 IE 的開發者工具 (developer tool),發現 IE 的模式預設被設定為 IE 5,這個預設模式是來自於 DOCTYPE 宣告,不過把它改成最簡化的 DOCTYPE,預設也還是會是 IE7 模式:

<!DOCTYPE html>

最後加入一行 META,強制以 IE edge 模式執行,結束這回合:

<meta http-equiv="X-UA-Compatible" content="IE=edge" />
arrow
arrow
    創作者介紹
    創作者 小攻城師 的頭像
    小攻城師

    小攻城師的戰場筆記

    小攻城師 發表在 痞客邦 留言(0) 人氣()