文章加密

;

2019年8月27日 星期二

vuex-class, interface, enum, 各種ts的基礎說明

https://www.jishuwen.com/d/2ACk/zh-tw  vuex-class, 如何使用 vue + typescript 編寫頁面 ( vuex裝飾器部分 )




https://ts.xcatliu.com/basics/type-of-object-interfaces  对象的类型——接口
接口(Interfaces)可以用于对「对象的形状(Shape)」进行描述。

https://ts.xcatliu.com/advanced/class-and-interfaces#%E7%B1%BB%E5%AE%9E%E7%8E%B0%E6%8E%A5%E5%8F%A3 类与接口
实现(implements)是面向对象中的一个重要概念。一般来讲,一个类只能继承自另一个类,有时候不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),用 implements 关键字来实现。这个特性大大提高了面向对象的灵活性。

https://ts.xcatliu.com/basics/type-of-function#%E6%8E%A5%E5%8F%A3%E4%B8%AD%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%9A%E4%B9%89 函数的类型 (ts寫函式)



https://jkchao.github.io/typescript-book-chinese/typings/enums.html#%E6%94%B9%E5%8F%98%E4%B8%8E%E6%95%B0%E5%AD%97%E6%9E%9A%E4%B8%BE%E5%85%B3%E8%81%94%E7%9A%84%E6%95%B0%E5%AD%97   enum



https://medium.com/tkd-giant/typescript%E5%85%A5%E9%96%80-%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-d659bb592810   各種ts的基礎說明, 挺全的

Get Started Writing Class-based Vue.js Apps in TypeScript, vue-property-decorator

https://www.itread01.com/content/1545117490.html  vue-property-decorator使用指南,在Vue中使用TypeScript時,非常好用的一個庫,使用裝飾器來簡化書寫。

https://www.sitepoint.com/class-based-vue-js-typescript/  Get Started Writing Class-based Vue.js Apps in TypeScript


https://qiita.com/ryo2132/items/4d43209ea89ad1297426

2019年8月15日 星期四

token

https://www.bilibili.com/read/cv2356912/

https://juejin.im/post/5b7ea1366fb9a01a0b319612

https://segmentfault.com/a/1190000014527692

https://www.zhihu.com/question/265033797 基于 HTTP 连接下 token 安全问题?

在google搜尋 "token 前端 後端"

在google搜尋 "token 前端 發送"

在google搜尋 "token 前端 安全"

.attr() vs .prop() 初始值與目前狀態是否相符?相符情況下attr() prop()都可使用,不相符時僅prop()可用

初始值與目前狀態是否相符:
相符情況下attr() prop()都可使用
不相符時僅prop()可用

Because "the attribute 'checked' corresponds only to the defaultCheckedproperty, and should only be used to set the initial value of the checkbox".
In fact, both attr() and prop() methods work, but as of jQuery 1.6, are used in different contexts:
— attr() is only used to check out if a checkbox was checked or not at first page load. In other words, it reflects what is written in your HTML source code, that is to say if the attribute 'checked' was initially present or not for a checkbox ( the name 'attr()' of this method can be used as a reminder) ;
— prop() on the other hand is used to check out in real time if a checkbox is currently checked or not — which is of course much more interesting — and to change this state, if needed. Here, we no longer deal with an attribute, but with a property (the name 'prop()' of this method can be used as a reminder).

The same principle applies for the boolean values returned by radio buttons or the <option> elements of a <select> input field for example.


https://cythilya.github.io/2017/09/10/jquery-attr-vs-prop/

2019年8月9日 星期五

request line, status line, HTTP header, content, HTTP狀態碼(status code) ; HTTP Cache 機制 ; PHP下載檔案,簡單四行程式碼!

之所以session可以辨別不同的user,是因為browser與server建立了session_id

http://www.manongjc.com/article/1260.html

PHP下載檔案,簡單四行程式碼!

http://hatsukiakio.blogspot.com/2009/08/php-header.html

header('Content-type:application/force-download'); //告訴瀏覽器 為下載 
header('Content-Transfer-Encoding: Binary'); //編碼方式
header('Content-Disposition:attachment;filename='.$filename); //檔名
@readfile($filename);

HTTP : HyperText Transfer Protocol  超文本傳輸協議

https://nkongkimo.wordpress.com/2010/04/28/http-header%E5%85%A5%E9%96%80/

整個www都在使用這種協定,幾乎你在流覽器裏看到的大部分內容都是通過http協定來傳輸的
它承載了關於用戶端流覽器,請求頁面,伺服器等相關的資訊

Q:什麼是HTTP?
A:
被設計來讓瀏覽器和伺服器進行溝通的協定,但也可做其他用途。HTTP 遵循標準客戶端—伺服器模式,由客戶端連線以發送請求,然後等待接收回應。HTTP 是一種無狀態協定,意思是伺服器不會保存任兩個請求間的任何資料 (狀態)

示例

當你在流覽器位址欄裏鍵入一個url,你的流覽器會將類似如下的http請求:
GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1 (Request line)
Host: net.tutsplus.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120
Pragma: no-cache
Cache-Control: no-cache
第一行被稱為“Request Line” 它描述的是這個請求的基本資訊,剩下的就是HTTP headers了。


請求完成之後,你的流覽器可能會收到如下的HTTP回應:
HTTP/1.x 200 OK (state line)
Transfer-Encoding: chunked
Date: Sat, 28 Nov 2009 04:36:25 GMT
Server: LiteSpeed
Connection: close
X-Powered-By: W3 Total Cache/0.8
Pragma: public
Expires: Sat, 28 Nov 2009 05:36:25 GMT
Etag: “pub1259380237;gz"
Cache-Control: max-age=3600, public
Content-Type: text/html; charset=UTF-8
Last-Modified: Sat, 28 Nov 2009 03:50:37 GMT
X-Pingback: http://net.tutsplus.com/xmlrpc.php
Content-Encoding: gzip
Vary: Accept-Encoding, Cookie, User-Agent
<!– … rest of the html … –>

第一行被稱為“Status Line”,它之後就是http headers,空行完了就開始輸出內容了(在這個案例中是一些html輸出)。

這個HTTP請求也發出了一些其他資源的接收請求,例如圖片,css檔,js文件等等。


HTTP Request 的結構

6cdc05c8866dc3df9a78880e4756c348.gif (590×247)
被稱作“first line”的第一行包含三個部分:
  • “method” 表明這是何種類型的請求. 最常見的請求類型有 GET, POST 和 HEAD.
  • “path” 體現的是主機之後的路徑. 例如,當你請求 “http://net.tutsplus.com/tutorials/other/top-20-mysql-best-practices/”時 , path 就會是 “/tutorials/other/top-20-mysql-best-practices/”.
  • “protocol” 包含有 “HTTP” 和版本號, 目前流覽器都會使用1.1.
剩下的部分每行都是一個“Name:Value”對。它們包含了各式各樣關於請求和你流覽器的資訊。
例如”User-Agent“就表明了你流覽器版本和你所用的作業系統。
”Accept-Encoding“會告訴伺服器你的流覽可以接受類似gzip的壓縮輸出。
這些headers大部分都是可選的。HTTP 請求甚至可以被精簡成這樣子:
GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1
Host: net.tutsplus.com

並且你仍舊可以從伺服器收到有效的回應。



請求類型


三種最常見的請求類型是:GET,POST 和 HEAD ,從html的編寫過程中你可能已經熟悉了前兩種。
Get
<form action="foo.php" method="GET">
First Name: <input name="first_name" type="text" />
Last Name: <input name="last_name" type="text" />
<input name="action" type="submit" value="Submit" />
</form>
當這個表單被提交時,HTTP request 就會像這樣:
GET /foo.php?first_name=John&last_name=Doe&action=Submit HTTP/1.1

POST
<form action="foo.php" method="POST">
First Name: <input name="first_name" type="text" />
Last Name: <input name="last_name" type="text" />
<input name="action" type="submit" value="Submit" />
</form>
提交這個表單會創建一個如下的HTTP 請求:
POST /foo.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/test.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 43
first_name=John&last_name=Doe&action=Submit
這裏有三個需要注意的地方:
  • 第一行的路徑已經變為簡單的 /foo.php , 已經沒了查詢字串。
  • 新增了 Content-Type 和 Content-Lenght Header,它提供了發送資訊的相關資訊.
  • 所有資料都在headers之後,以查詢字串的形式被發送.
Method
HEAD和GET很相似,只不過HEAD不接受HTTP回應的內容部分。當你發送了一個HEAD請求,那就意味著你只對HTTPHeader感興趣,而不是文檔本身。
這個方法可以讓流覽器判斷頁面是否被修改過,從而控制緩存。也可判斷所請求的文檔是否存在。
例如,假如你的網站上有很多鏈結,那麼你就可以簡單的給他們分別發送HEAD請求來判斷是否存在死鏈,這比使用GET要快很多。


HTTP狀態碼

  • 200 用來表示請求成功.
  • 300 來表示重定向.
  • 400 用來表示請求出現問題.
  • 500 用來表示伺服器出現問題.
200 成功 (OK)
前文已經提到,200是用來表示請求成功的。
206 部分內容 (Partial Content)
如果一個應用只請求某範圍之內的檔,那麼就會返回206.
這通常被用來進行下載管理,中斷點續傳或者檔分塊下載。
404 沒有找到 (Not Found)
很容易理解

401 未經授權 (Unauthorized)
受密碼保護的頁面會返回這個狀態。如果你沒有輸入正確的密碼,那麼你就會在流覽器中看到如下的資訊:
注意這只是受密碼保護頁面,請求輸入密碼的彈出框是下面這個樣子的:

403 被禁止(Forbidden)
如果你沒有許可權訪問某個頁面,那麼就會返回403狀態。這種情況通常會發生在你試圖打開一個沒有index頁面的檔夾。如果伺服器設置不允許查看目錄內容,那麼你就會看到403錯誤。
其他一些方式也會發送許可權限制,例如你可以通過IP位址進行阻止,這需要一些htaccess的協助。
order allow,deny
deny from 192.168.44.201
deny from 224.39.163.12
deny from 172.16.7.92
allow from all
302(或307)臨時移動(Moved Temporarily) 和 301 永久移動(Moved Permanently)
這兩個狀態會出現在流覽器重定向時。例如,你使用了類似 bit.ly 的網址縮短服務。這也是它們如何獲知誰點擊了他們鏈結的方法。
302和301對於流覽器來說是非常相似的,但對於搜索引擎爬蟲就有一些差別。打個比方,如果你的網站正在維護,那麼你就會將用戶端流覽器用302重定向到另外一個位址。搜索引擎爬蟲就會在將來重新索引你的頁面。但是如果你使用了301重定向,這就等於你告訴了搜索引擎爬蟲:你的網站已經永久的移動到了新的位址。
500 伺服器錯誤(Internal Server Error)

這個代碼通常會在頁面腳本崩潰時出現。大部分CGI腳本都不會像PHP那樣輸出錯誤資訊給流覽器。如果出現了致命的錯誤,它們只會發送一個500的狀態碼。這時需要查看伺服器錯誤日誌來排錯。



HTTP Cache 機制

  1. Expires跟max-age都可以決定一個 Response 是否過期,但max-age會蓋過(override
    )Expires
    。在過期之前,瀏覽器「不會」發送出任何 Request。
    -max-age:status code 200 (from memory cache)
    -Expires:status code 200 (from disk cache)
  2. Last-Modified 與 If-Modified-Since:有一種期況,cache已經過期了,但是檔案也沒有修改過,故檔案使否被修改過成為是否更新快取的條件。
  3. Etag 與 If-None-Match:若是你打開檔案什麼都不做,然後存檔,這個編輯時間也會被更新。所以就產生了用「檔案內容更動與否」來當作是否要更新快取的條件,可以把 Etag 想成是這份檔案內容的 hash 值(但其實不是,但原理類似就是了,總之就是一樣的內容會產生一樣的 hash,不一樣的會產生不一樣的 hash)
※以上,list 1是第一個判斷是否更新快取的條件,list2和lsit3都是次要條件,不過list3則是比list2更好的第二個判斷條件。當快取過期之後,可以用If-Modified-Since或是If-None-Match詢問 Server 有沒有新的資源,如果有的話就回傳新的,沒有的話就回傳 Status code 304,代表快取裡面的資源還能繼續沿用。

Q:想要即時更新,但如果一周都沒改變,不希望每次user都還來要資料。
A:第一招,你可以用Cache-Control: max-age=0,這就代表說這個 Response 0 秒之後就會過期,意思是瀏覽器一接收到,就會標示為過期。這樣當使用者再次造訪頁面,就會去 Server 詢問有沒有新的資料,再搭配上Etag來使用,就可以保證只會下載到最新的 Response。
第二招,有一個已經規範好的策略叫做:Cache-Control: no-cacheno-cache並不是「完全不使用快取的意思」,而是跟我們上面的行為一樣。每次都會發送 Request 去確認是否有新的檔案。
如果要「完全不使用快取」,是Cache-Control: no-store。這邊不要搞混了。


來個實例:
假設 A 網站是使用Cache-Control: no-store,B 網站是使用Cache-Control: no-cache
當每一次重新造訪同樣一個頁面的時候,無論 A 網站有沒有更新,A 網站都會傳來「整份新的檔案」,假設index.html有 100 kb 好了,造訪了十次,累積的流量就是 1000kb。
B 網站的話,我們假設前九次網站都沒有更新,一直到第十次才更新。所以前九次 Server 只會回傳 Status code 304,這個封包大小我們姑且算作 1kb 好了。第十次因為有新的檔案,會是 100kb。那十次加起來的流量就是 9 + 100 = 109 kb
可以發現 A 跟 B 達成的效果一樣,那就是「只要網站更新,使用者就能立即看到結果」,但是 B 的流量遠低於 A,因為有善用快取策略。只要每一次 Request 都先確認網站有沒有更新即可,不用每一次都抓完整的檔案下來。
這就是no-storeno-cache的差異,永遠不用快取跟永遠檢查快取。



最後一個問題

現在 Web App 當道,許多網站都是採用 SPA 的架構搭配 Webpack 打包。前端只需要引入一個 JavaScript 的檔案,Render 就交給 JavaScript 來做就好。
這類型的網站,HTML 可能長得像這樣:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
  <link rel='stylesheet' href='style.css'></link>
  <script src='script.js'></script>
</head>
<body>
 <!-- body 為空,所有內容都交給 js 去 render -->
</body>
</html>

當 JavaScript 載入之後,利用 JavaScript 把頁面渲染出來。
面對這種情境,我們就會希望這個檔案能夠跟上面的首頁檔案一樣,「只要檔案更新,使用者能夠立即看到新的結果」,因此我們可以用Cache-Control: no-cache來達成這個目標。
可是呢,還記得剛說過no-cache其實就是每一次訪問頁面,都去 Server 問說有沒有新的結果。意思就是無論如何,都會發出 Request。
有沒有可能,連 Request 都不發呢?
意思就是:「只要檔案不更新,瀏覽器就不會發 Request,直接沿用快取裡的即可。只要檔案一更新,瀏覽器就要立即抓取新的檔案」
前者其實就是我們一開始講的max-age在做的事,但max-age沒辦法做到判斷「檔案不更新」這件事情。
所以其實這個目標,沒辦法單靠上面我們介紹的這些瀏覽器的快取機制來達成,需要 Server 那邊一起配合才行。其實說穿了,就是把 Etag 的機制自己實作在檔案裡面。
什麼意思呢?我們直接來看一個範例,我們把index.html改成這樣:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
  <link rel='stylesheet' href='style.css'></link>
  <script src='script-qd3j2orjoa.js'></script>
</head>
<body>
 <!-- body 為空,所有內容都交給 js 去 render -->
</body>
</html>

注意到 JavaScript 的檔名變成:script-qd3j2orjoa.js,後面其實就跟 Etag 一樣,都是代表這個檔案的 hash 值。然後我們把這個檔案的快取策略設成:Cache-Control: max-age=31536000
這樣子這個檔案就會被快取住一年。一年之內都不會對這個 URL 發送新的 Request。
那如果我們要更新的話怎麼辦呢?我們不要更新這個檔案,直接更新index.html,換一個 JavaScript 檔案:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
  <link rel='stylesheet' href='style.css'></link>
  <script src='script-8953jief32.js'></script>
</head>
<body>
 <!-- body 為空,所有內容都交給 js 去 render -->
</body>
</html>

因為index.html的快取策略是no-cache,所以每一次訪問這個頁面,都會去index.html是否更新
以現在這個例子來說,它的確更新了,因此新的這份就會傳回給瀏覽器。而瀏覽器發現有新的 JavaScript 檔案就會去下載並且快取起來(不會render到一樣的js檔,因為被快取了)
藉由把 Etag 的機制實作在index.html裡面,我們就達成了我們的目標:「只要檔案不更新,瀏覽器就不會發 Request,直接沿用快取裡的即可。只要檔案一更新,瀏覽器就要立即抓取新的檔案」
原理就是針對不同的檔案採用不同的快取策略,並且直接用「更換 JavaScript 檔案」的方式強制瀏覽器重新下載。


2019年8月7日 星期三

Postman - 後端工程師用來測試 API的神器, runner iteration

https://dotblogs.com.tw/kinanson/2015/11/07/153838     →得出這是後端工程師在測試使用的,前端不需要他

https://ithelp.ithome.com.tw/articles/10201503


runner iteration 操作說明:
  1. + New Collection 
  2. Add Request 
  3. 編輯該request,如url, 測試環境
  4. 寫遞迴時的測試
    const FIRST_ON_LINE_REGION = ["global", "de", "pl", "se", "dk", "cz", "it", "hu", "fi", "pt", "es", "fr", "nl", "be-fr", "be-nl"];
    const OTHER_REGION = ["bt", "me-en", "lk", "in", "tr", "tw", "bd", "cn", "hk", "vn", "kr", "jp", "ru", "th", "sg", "nz", "ph", "id", "au", "my", "br", "latin", "no", "uk", "sk", "ch-fr", "ch-it", "ch-de", "ro", "rs", "ua", "gr", "za", "ca-fr", "ca-en", "us", "me-ar", "mx", "bg", "ie", "il", "ea", "middleeast-fa", "eg", "ua-ua", "nafr-ar", "africa-fr", "np", "wa", "middleeast-fa", "lt", "lv", "ee", "kz", "mm", "eg-en", "hk-en", "co", "cl", "ar", "pe", "ea-sw", "ch-en", "bn", "gr-el", ""];
    const REGION_LIST = FIRST_ON_LINE_REGION.concat(OTHER_REGION);
    pm.environment.set("countryname", REGION_LIST[pm.info.iteration]);
    // pm.info.iteration
    pm.test("Successful GET request - "+ REGION_LIST[pm.info.iteration -1] || "NO", function () {
    pm.expect(pm.response.code).to.be.oneOf([200,201,202]);
    });
  5. 用runner跑遞迴

活動大廳與vip,接收資料一個包在res.data,一個直接用res就可以用,甚至於用getIp.php,也是這樣

觀察了一下,如果不是vue造成的,應該就是response headers的設定造成的(可以從browser的nerwork去看見)

vip
X-Powered-By: PHP/7.1.28


活動大廳
Access-Control-Allow-Origin: * Access-Control-Allow-Headers: * X-Frame-Options: SAMEORIGIN

2019年8月4日 星期日

英文自我介紹

hi, everybody. my name is shih-ting ni,i'm very honored to be here for an interview. i am a frontend engineer.i have worked in taiwinner company for one year, and i participated in developing a vip system project,which consist of forestage and backstage. game players can search their account information,such as vip level, reward, and they can still borrow money, return money at the forestage. then admins can login into the backstage, and set the account's relational rules.they can also restrict the access ip to the backstage.

besides, i took over a angular project and changed it into vue's code, because the employee left the company. it's a project  a little bit like a blog, admins can login into the backstage and change the words and images about the forestage.

in my free time, i learn php, git, vue, scss. and i think it's a good time to change to a more challenging job.  That’s all.Thank you for giving me the chance. it's a pleasure to meet you, and i hope i'll have a chance to get to know you better in the future.