摘要:接下來我們開始編寫自己的配置文件,實現指向的代理,并在請求中添加進行鑒權,同時在響應中添加跨域頭,以滿足跨域需求。在上面的配置文件中,用我們從創建的代替,用需要實現訂閱的郵件列表的代替,而則是的后綴數字。
tl;dr
nginx 既靈活方便,又功能豐富,可以幫助我們實現添加跨域頭、URL 重寫以及隱藏敏感信息等功能。本文介紹在使用 MailChimp
進行郵件營銷中遇到的一個普遍問題,分析了瀏覽器發起跨域請求時,在瀏覽器和服務器之間的交互過程,在此基礎上提供了一個使用 nginx
反向代理實現的、靈活經濟的解決方案。
MailChimp是最大的郵件營銷解決方案提供商,官方網站 https://mailchimp.com。
通過 MailChimp 可以定制郵件模板、創建自己的郵件列表、發起各種營銷活動,并支持統計有多少人打開了郵件以及其他一些 SNS 功能,客戶可以隨時訂閱或取消訂閱郵件。
MailChimp 提供了多種訂閱表單,如普通表單、嵌入表單、彈窗表單以及由第三方集成的表單……用于收集用戶郵箱及其他一些個人信息,然而這些表單都存在一些問題,如普通表單必須進行 captcha 校驗,嵌入表單及彈窗表單不支持注冊后自動跳轉到自己的頁面,并且所有這些表單還需要用戶在收件箱里收取確認郵件并確認訂閱,對于一家迫切需要更多訂閱用戶實現郵件營銷的公司來說,為了盡可能多地獲取訂閱用戶,這些校驗和確認能省則省。而第三方集成的表單則需要按月收費,每月十幾到上百美元不等,好鋼要用在刀刃上,這也是一筆能省則省的開支。
MailChimp 還提供了 API 接口,其中 與列表成員相關的 API 接口 包含列表成員的創建、讀取、編輯以及刪除功能,因此,可以通過 AJAX 方式進行郵件訂閱,訂閱流程中是否加入 captcha 校驗完全自主,用戶訂閱之后也不需要進行郵箱確認,并且完全免費。
但這些 API 也存在兩個問題,一是不支持跨域,二是 MailChimp 提供的 API key 是全權限的,意味著一旦泄露,搗蛋分子就可以利用 MailChimp 的 API 接口對你的 MailChimp 賬號為所欲為。
因此,我們如果希望使用 MailChimp 的 API 實現用戶訂閱,就需要解決上述兩個問題,兼具靈活性和功能性的 nginx 是個不錯的選擇。
首先我們需要一個 nginx,在本地試驗的話用 docker 就可以了,在命令行終端執行 docker pull nginx,稍等片刻就可把 nginx 最新版的 docker 鏡像拉取下來了。如果網絡狀況不佳,還可以配置 daocloud 的 Docker 加速器。
打開終端窗口運行 docker run --name temp-nginx nginx,再打開一個終端窗口,然后使用 docker cp temp-nginx:/etc/nginx/nginx.conf. 和 docker cp temp-nginx:/etc/nginx/conf.d/default.conf. 這兩個命令從容器中將 nginx 相關的配置拷貝出來,拷貝出來的配置文件主要作為我們自己編寫配置文件的參考,即使之前沒有配置過 nginx,也可以依葫蘆畫瓢完成基本的配置。
nginx.conf 文件中通過 include 指令包含了 default.conf 文件的內容,我們首先把兩個文件簡化合并成一個文件,并刪除不必要的注釋,命名為 mailChimp.conf。
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { server { listen 80; location / { root /usr/share/nginx/html; index index.html index.htm; } } }
目的達到,我們可以“卸磨殺驢”,隨后運行 docker stop temp-nginx && docker rm temp-nginx 將前面創建的容器停止并刪除。
為了方便調試,我們同時編寫一個 shell 腳本,用于隨時使用創建的 mailChimp.conf 配置文件啟動 docker 容器,并將 localhost 的 8080 端口綁定到容器的 80 端口上,這樣我們就可以向 http://localhost:8080/ 發起請求,并在命令行終端查看日志,一旦配置出現問題可以隨時使用 ctrl+c 停止 docker 容器,修改配置后重新運行該腳本即可。
#!/usr/bin/env bash docker rm mailChimp-nginx docker run --name mailChimp-nginx -v /path/to/mailChimp.conf:/etc/nginx/nginx.conf:ro -it -p 8080:80 nginx
接下來我們開始編寫自己的配置文件,實現指向 MailChimp 的代理,并在請求中添加 API key 進行鑒權,同時在響應中添加跨域頭,以滿足跨域需求。
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { server { listen 80; location / { root /usr/share/nginx/html; index index.html index.htm; } location /maillist/subscribe { if ($request_method = GET) { return 403; } add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods PUT,OPTIONS; add_header Access-Control-Allow-Headers Content-Type; if ($request_method = OPTIONS) { return 204; } proxy_set_header Authorization "apikey {apiKey}"; rewrite /maillist/subscribe/(.*)$ /3.0/lists/{listId}/members/$1 break; proxy_pass https://us{siteNumber}.api.mailchimp.com; } } }
在上面的配置文件中,{apiKey} 用我們從 MailChimp 創建的 API key 代替,{listId} 用需要實現訂閱的郵件列表的 ID 代替,而 {siteNumber} 則是 API key 的后綴數字。
我們仍然使用 docker 鏡像中 /usr/share/nginx/html 目錄的內容作為網站首頁,同時添加一個 /maillist/subscribe 路徑。
由于 MailChimp 的 API key 是全權限的,為避免用戶直接通過瀏覽器訪問 /maillist/subscribe/ 獲取 MailChimp 的 /3.0/lists/{listId}/members/ 的內容,首先需要對 HTTP Method 為 GET 的請求返回 403 Forbidden,在配置文件中通過 if 指令進行 Method 判斷,并通過 return 指令返回 403 代碼。
基于我們瀏覽器進行跨域請求的了解,瀏覽器在正式發起跨域請求之前,先要發起一個 Method 為 OPTIONS 的請求(Preflighted Requests,預檢請求),通過該請求獲取服務端的響應以了解服務端是否支持跨域、支持哪些 Method、以及支持哪些 Header 等信息,簡言之,獲取服務器支持的 HTTP 請求特性,這些響應頭在 OPTIONS 請求的響應以及正式請求響應中必須一致。
因此我們接著進行 HTTP 響應頭的設置,由于后面我們對請求及響應進行了代理轉發,而轉發的 MailChimp 響應中不包含 Access-Control-Allow-Origin 跨域響應頭,因此這里使用 add_header 添加 Access-Control-Allow-Origin 時,需要在后面加上 always,表示始終加上 Access-Control-Allow-Origin。
此外還需要添加 Access-Control-Allow-Methods 和 Access-Control-Allow-Headers 響應頭。
經試驗,如果采用 MailChimp 列表成員添加的 API,使用 POST Method,實現訂閱郵件的添加,則當用戶通過其他途徑退訂了列表之后,無法重新訂閱,因此改為采用 MailChimp 列表成員編輯的 API,這是一個 PUT Method,請求 URL 路徑中包含用戶郵箱地址的 MD5 值,當請求的用戶在列表中不存在時為添加,當用戶存在時則為修改。因此這里的 Access-Control-Allow-Methods 設置為 PUT,OPTIONS。
MailChimp API 僅支持 JSON 格式的數據,這需要在請求中設置 Content-Type 為 application/json; charset=utf-8,同時還需要在 nginx 的響應中設置 Access-Control-Allow-Headers 為 Content-Type。
設置完畢,對于 Method 為 OPTIONS 的請求,我們不需要返回 body,因此再次使用 if 指令進行 Method 判斷,并返回 204 代碼表示無正文。
最后,就是代理轉發的設置了,首先使用 proxy_set_header 指令設置鑒權請求頭,然后使用 rewrite 指令進行 URL 重寫,使用正則表達式獲取 /maillist/subscribe/ 之后的 E-Mail 的 MD5,拼接成 MailChimp API 請求的 URL,最后,通過 proxy_pass 指令實現代理轉發。
使用 Fetch 從前端發起請求,相關代碼如下,API key、list ID 等敏感信息已被隱藏:
var headers = new Headers() headers.append("Content-Type", "application/json; charset=utf-8") var body = "{"email_address":"test@te.st","status":"subscribed"}" fetch("http://localhost:8080/maillist/subscribe/f1c49ab3e7dd54b1daee1f4bdc0a1f78", { method: "PUT", headers, body }).then(res => res.json()).then(json => { console.log(json) }).catch(err => { console.log(err) })
從控制臺上看到結果如下:
實際項目中,body 使用 JSON.stringify 進行序列化,請求路徑中的參數還需要使用 MD5 庫進行 MD5 值計算。
最終的配置可以在 nginx 的 docker 鏡像基礎上創建一個包含了上述配置的 docker 鏡像,然后部署到 DaoCloud 或其他提供 docker 容器服務的站點上去。下面是一個部署在 DaoCloud 的代理,http://mario-studio.daoapp.io/,使用 Vue 創建了一個超級簡單的 訂閱表單,歡迎大家訂閱我的郵件列表,雖然還不知道我會發些什么(手動比心
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/39491.html
摘要:接下來我們開始編寫自己的配置文件,實現指向的代理,并在請求中添加進行鑒權,同時在響應中添加跨域頭,以滿足跨域需求。在上面的配置文件中,用我們從創建的代替,用需要實現訂閱的郵件列表的代替,而則是的后綴數字。 tl;dr nginx 既靈活方便,又功能豐富,可以幫助我們實現添加跨域頭、URL 重寫以及隱藏敏感信息等功能。本文介紹在使用 MailChimp進行郵件營銷中遇到的一個普遍問題,分...
摘要:跨域總結跨域思路跨域解決方案一般分為兩種前端解決,后端解決前端解決方案通過前端解決的思想就是,通過設置中間件把跨域的請求轉發一下,其實就是反向代理,比如想要訪問豆瓣的接口很會有跨域問題,但是如果請求的是就不存在跨域反向代理就是截取之后的請求 跨域總結 1.跨域思路 跨域解決方案一般分為兩種:前端解決,后端解決 1.1 前端解決方案 通過前端解決的思想就是,通過設置中間件把跨域的請求轉發...
閱讀 1992·2021-08-11 11:13
閱讀 1014·2021-07-25 21:37
閱讀 2576·2019-08-29 18:42
閱讀 2508·2019-08-26 12:18
閱讀 913·2019-08-26 11:29
閱讀 1683·2019-08-23 17:17
閱讀 2662·2019-08-23 15:55
閱讀 2597·2019-08-23 14:34