Serverless 架構(gòu)應(yīng)用開發(fā)指南:創(chuàng)建自己的 Serverless 短鏈服務(wù)

在想用 Serverless 可以做點(diǎn)什么簡單的在線應(yīng)用后,我想到了一個(gè)是在線短鏈生成服務(wù)。最后的結(jié)果見:http://x.pho.im/,一個(gè)非常簡單的在線應(yīng)用。

這里的代碼基于:https://github.com/vannio/serverless-shrink

因?yàn)樯厦娴拇a中,不能自動創(chuàng)建域名。然后,再針對數(shù)據(jù)庫進(jìn)行了一些優(yōu)化。

代碼邏輯

這里的代碼邏輯比如簡單:

  • 創(chuàng)建短鏈時(shí),使用生成一個(gè)四位的字符串
  • 將原有的 URL 和生成的 URL 存儲到 DynamoDB 中
  • 在返回的 HTML 中,輸出對應(yīng)的 URL
  • 重定向時(shí),從 DynamoDB 讀取對應(yīng)的短鏈
  • 如果短鏈存在,則執(zhí)行 302 重定向;如果不存在,則返回一個(gè) 404。

創(chuàng)建首頁

首頁只是一個(gè)簡單的 HTML 表單:

const base_page = `<html>
<h1>Hi!</h1>
  <form method="POST" action="">
    <label for="uri">Link:</label>
    <input type="text" id="link" name="link" size="40" autofocus />
    <br/>
    <br/>
    <input type="submit" value="Shorten it!" />
  </form>
</html>`

module.exports.handler = (event, context, callback) => {
  console.log(JSON.stringify(event));

  callback(
    null,
    {
      statusCode: 200,
      body: base_page,
      headers: {'Content-Type': 'text/html'},
    }
  );
}

當(dāng)我們提交的時(shí)候,就會觸發(fā)對應(yīng)的 POST 請求。

生成短鏈

如上所述,對于個(gè)短鏈請求,我們要做這么幾件事:

  1. 解析出提交表單中的鏈接
  2. 根據(jù) URL 生成對應(yīng)的短鏈
  3. 將對應(yīng)的 URL 和短鏈的對應(yīng)關(guān)系存儲到 DynamoDB 中
  4. 如果成功,則返回生成的短鏈;失敗則,返回一個(gè) 400

事實(shí)上,在存儲 URL 和短鏈的 map 之前,我們應(yīng)該先判斷一下數(shù)據(jù)中是否已經(jīng)有相應(yīng)的短鏈。不過,對于這種只針對于我一個(gè)用戶的短鏈服務(wù)來說,這個(gè)步驟有點(diǎn)浪費(fèi)錢——畢竟要去掃描一遍數(shù)據(jù)庫。所以,我也不想去添加這樣的擴(kuò)展功能。

接下來,讓我們回到代碼中去,代碼的主要邏輯都是在 Promise 里,按順序往下執(zhí)行。

解析出提交表單中的鏈接

首先,我們通過 querystring 庫來解決中表單中的鏈接。

const submitted = querystring.parse(event.body).link;

根據(jù) URL 生成對應(yīng)的短鏈

接著,使用 Node.js 中的 crypto.randomBytes 方法來生成八位的偽隨機(jī)碼。

crypto.randomBytes(8)
  .toString('base64')
  .replace(/[=+/]/g, '')
  .substring(0, 4)

由于生成的偽隨機(jī)碼是 Buffer 類型,因此需要轉(zhuǎn)換為字符串。同時(shí),因?yàn)樯傻亩替溨胁粦?yīng)該有 "=+/",它會導(dǎo)致生成的 URL 有異常。于是,我們便替換掉偽隨機(jī)碼中的這些特殊字體。最后,截取生成的字符串的前 4 位。

現(xiàn)在,我們就可以將其存儲到數(shù)據(jù)中了。

存儲到 Dynamo 數(shù)據(jù)庫中。

對應(yīng)的存儲邏輯如下所示,我們 new 了一個(gè) DocumentClient 對象,然后直接存儲到數(shù)據(jù)庫中。put 函數(shù)中的對象,即是對應(yīng)的參數(shù)。

return docClient.put({
  TableName: tableName,
  Item: {
    slug: slug,
    url: submitted
  },
  Expected: {
    url: {Exists: false}
  }
}).promise().then(() => { return slug; });

最后,我們返回了 slug,用于接下來的處理。

返回短鏈給用戶

一切處理正常的話,我們將向用戶返回最后的內(nèi)容:

return callback(
  null,
  {
    statusCode: 200,
    body: RenderPage(path.join(prefix, slug).replace(':/', '://'), prefix),
    headers: {'Content-Type': 'text/html'}
  }
);

其中的 HTML 部分的渲染邏輯如下所示:

function RenderPage (link, submitted) {
  return `
<html>
<body>
<h3>
  <a href="${link}">${link}</a>
</h3>
<p>URL ${submitted} was shortened to:
  <a href="${link}">${link}</a>
</p>
</body>
</html>`
};

是的,只是返回短鏈和原有的鏈接了。

好了,現(xiàn)在我們已經(jīng)擁有這個(gè)短鏈了。接下來,就是點(diǎn)擊這個(gè)短鏈,看看背后會發(fā)生些什么?

重定向短鏈

首先,我們先在我們的 serverless.yml 中,將短鏈的路徑配置為參數(shù):

functions :
  ...
  redirect:
    handler: redirect/index.handler
    events:
      - http:
          path: /{slug}
          method: get

然后,從數(shù)據(jù)庫中按短鏈的 slug 查找對應(yīng)的 URL:

const slug = event.pathParameters.slug;

docClient.get({
  TableName: tableName,
  Key: {
    slug: slug
  }
}, (err, data) => {

})

如果存在對應(yīng)的短鏈,則 302 重定向?qū)υ械?URL:

const item = data.Item;

if (item && item.url) {
  callback(
    null,
    {
      statusCode: 302,
      body: item.url,
      headers: {
        'Location': item.url,
        'Content-Type': 'text/plain'
      }
    }
  )
}

如果沒有,則返回一個(gè) 404。

我們的代碼就是這么的簡單,現(xiàn)在讓我們來部署測試一下。

部署及測試短鏈服務(wù)

如果你還沒有 clone 代碼的話,執(zhí)行下面的命令來安裝:

serverless install -u https://github.com/phodal/serverless-guide/tree/master/url-shorter -n url-shorter

然后執(zhí)行 yarn install 來安裝對應(yīng)的依賴。

如果你在 Route53 上注冊有相應(yīng)的域名,修改一下 serverless.yml 文件中的域名,我們就可以使用 serverless create_domain 來創(chuàng)建域名的路由。

緊接著,執(zhí)行 serverless deploy 來部署。

api keys:
  None
endpoints:
  GET - https://4rr5ndhaw3.execute-api.us-east-1.amazonaws.com/dev/
  POST - https://4rr5ndhaw3.execute-api.us-east-1.amazonaws.com/dev/
  GET - https://4rr5ndhaw3.execute-api.us-east-1.amazonaws.com/dev/{slug}
functions:
  main: url-shorter-dev-main
  create: url-shorter-dev-create
  redirect: url-shorter-dev-redirect
Serverless Domain Manager Summary
Domain Name
  x.pho.im
Distribution Domain Name
  d2s4y0p5nuw3k7.cloudfront.net
Serverless: Removing old service versions...

一切準(zhǔn)備就緒了。

  1. 訪問 https://x.pho.im/
  2. 然后輸入一個(gè)鏈接,如:https://github.com/phodal/serverless-guide
  3. 復(fù)制生成的地址:https://x.pho.im/rgQC,并返回
  4. 看是否會重定向到我們的網(wǎng)站上。

Done!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,326評論 25 708
  • 本文是GitChat《Serverless 風(fēng)格微服務(wù)的持續(xù)交付(上):架構(gòu)案例》部分內(nèi)容已做修改。文章聊天實(shí)錄請...
    顧宇閱讀 3,364評論 1 13
  • 高考那年有作文題目是拒絕平庸,但生活中往往是甘于平庸。諺語,槍打出頭鳥。正好說明了這個(gè)道理,比如上學(xué)的時(shí)候,我父母...
    社會我夢妮閱讀 732評論 0 0
  • 陰山多寶,世人皆知,所以來陰山的人不勝枚舉。 一日,陰山來了位俊俏少年,來陰山的人只有一個(gè)目的,尋寶。這少年也不例...
    襲姝Liner閱讀 437評論 0 0

友情鏈接更多精彩內(nèi)容