Lidemy HTTP Challenge 破關過程手札


Posted by estella00911 on 2021-05-10

前言

Link to Header
目標:熟悉網路基礎知識及練習使用 Node.js 串接基本的 API
具備知識: Node.js 串接基本的 API、網路基礎知識

以下為題目解說與所學內容,並於最後有附上解題過程。


Let's Start to play this game!

Lv 0 說明

https://lidemy-http-challenge.herokuapp.com/start

  1. 練習:網址搭配正確的 token

Lv 1 你叫什麼名字?

Lv 1: https://lidemy-http-challenge.herokuapp.com/lv1?token={GOGOGO}

  1. 練習: review 第 0 關的網址 token 結合
  2. API 文件:https://gist.github.com/aszx87410/3873b3d9cbb28cb6fcbb85bf493b63ba

Lv 2 可以幫我找出某一本書嗎?

Lv 2: https://lidemy-http-challenge.herokuapp.com/lv2?token={HellOWOrld}

  1. 看懂 API 文件敘述:新增/刪除/查詢/更改書籍需要用哪一個 Method,然後 path 是什麼。
  2. 結合 API 及網址使用

Lv 3 可以幫我優先上架這本新書《大腦喜歡這樣學》嗎?

Lv3: https://lidemy-http-challenge.herokuapp.com/lv3?token={5566NO1}

  1. API 文件上說:新增書籍,需要使用 POST method。
  2. 然後發現 HTTP 在 POST 所使用的規則: content type 為:application/x-www-form-urlencoded

在此使用 request 的 npm 套件,因此需要使用 POST 的話,需要符合格式傳送,這個格式就是上述的 content-type,在 HTTP 內容類型 (Content-Type) 提到「普遍用於 HTML 中的 POST 表單 (e.g., 提交帳號密碼),是『類似百分比編碼的鍵值對』形式,例如:『name=%E5%8B%9D&password=9487』」

利用 HTTP GET vs POST 的解說,對 request 中 GET method 做進一步瞭解,GET 有查詢/檢索/獲取的意思,如果需要使用GET 來找到書籍的話,需要額外在表單(form)輸入參數(parameter)中,會做 URL 編碼 (URL-Encoding)在 URL 透過查詢(query)會以鍵值對(key value)的形式顯示,例如:查詢幾歲的女生,key 為年紀,因此將 key 稱 age,value 為歲數,所以將 value 設為 24,加上條件為女生,再透過 get 查詢生成的 URL:https://echo.paw.cloud:443/hello/world?age=24&gender=female。

其中,urlencoded 就是產生編碼的意思,如果 form 內的資料呈現以下格式:

form:{
        name: 'littlePrince',
        ISBN: '324232&123=3'
    }

會在 URL加上資訊為 name=littlePrince&ISBN=324232&123=3,那這樣 server 會搞不清楚 form 內的 ISBN 為324232 還是 324232&123=3,因此需要透過編碼形式的轉換,避免混淆。在 URL 編碼中,會把字符分成兩種:保留字符(具特殊字元)及未保留字符,在 URL 編碼中會將特殊字符做轉換,如此一來,ISBN: 324232&123=3 就會轉換成324232%26123%3d3,這樣透過編碼後,就可以正確帶入資訊。


Lv 4 抱歉,我找錯書了,可以告訴我書名有「世界」、作者為村上春樹的ID嗎?

Lv 4: https://lidemy-http-challenge.herokuapp.com/lv4?token={LEarnHOWtoLeArn}

  1. 自己解的時候,只想到使用 process.argv 再執行 node.js 時輸入參數來印出書籍。
  2. 參考別人的心得後,突然想起這個小遊戲應該是循序漸進的關卡,可以利用上一關的「產生編碼」的概念來解。

Lv 5 有人捐錯書,要把書拿回去,所以要將這本書從系統中刪除

Lv 5: https://lidemy-http-challenge.herokuapp.com/lv5?token={HarukiMurakami}

  1. 練習 request.delete method,和 lv 4 POST method 在 content-type 上做區別。
  2. 承 lv 4,也可以使用「產生編碼」來解。

Lv 6 圖書系統應該需要登入才能修改,怎麼沒有登入就能新增跟刪除呢?回報給工程師後,得到一個新的 API 文件,然後就來嘗試看看怎麼登入並修改吧!

新文件:https://gist.github.com/aszx87410/1e5e5105c1c35197f55c485a88b0328a
Lv 6: https://lidemy-http-challenge.herokuapp.com/lv6?token={CHICKENCUTLET}

  1. 認識「HTTP 基本認證」(英語:Basic access authentication),允許 http 使用者在瀏覽器發出請求(request)觀看一個需要身分認證的頁面時,需要使用者提供使用者名稱(username)及使用者密碼(password),通過認證,才能打開頁面。其優點為:簡單便捷,流行的網頁瀏覽器都支援 HTTP 基本認證;缺點為:沒有任何加密或演算,僅有 Base64 編碼跟傳輸,容易被破解,另一個是在不關閉瀏覽器的狀況下,有效讓使用者登出。
  2. 學習在 Node.js中使用「HTTP 基本認證」,並學習如何使用 Base64 編碼,此外 API 文件上也有教學說明。

Lv 7 系統修復完成囉!記得使用新的系統,有一本書老是被偷走,所以要把 id=89 的書從系統中刪除。

Lv 7: https://lidemy-http-challenge.herokuapp.com/lv7?token=%7BSECurityIsImPORTant%7D

  1. 照著 API 文件內的指示做就行囉!

Lv 8 發現在輸入資料時,把有一本書名有個「我」,作者名 4 個字的書,key 錯的 ISBN 最後一碼為 7,只要把最後一碼改成 3 就行了!

Lv 8: https://lidemy-http-challenge.herokuapp.com/lv8?token={HsifnAerok}

  1. 利用查詢書籍的方式,找出題目要求的書籍 ID。
  2. 利用更新書籍資訊(PATCH)的方式,更新書籍的 ISBN。

Lv 9 工程師說從一般方法活得的網址不太對,需要兩個資料才能獲得正確的網址!

Lv9: http://lidemy-http-challenge.herokuapp.com/lv9?token={NeuN}

條件

  • 加上 X-Library-Number 的 header,然後這個圖書館的編號為 20。
  • 伺服器會用 user agent 檢查是否是從 IE6 送出的 Request,不是的話,會被擋住。
  1. 條件一已給了 key and value,只要放進 header 即可。
  2. 條件二需要檢查數不是從 IE6 送出的 reqeust。

Lv 10 工程師說從一般方法活得的網址不太對,需要兩個資料才能獲得正確的網址!

Lv10: http://lidemy-http-challenge.herokuapp.com/lv10?token={duZDsG3tvoA}

  1. 根據提示,猜數字。

通關密碼:

Lv 1: https://lidemy-http-challenge.herokuapp.com/lv1?token={GOGOGO}&name=jean
Tip: 填上名字就行了!


Lv 2: https://lidemy-http-challenge.herokuapp.com/lv2?token={HellOWOrld}&id=56
Tip: id 從 54 ~ 58 一個一個輸入


Lv 3: https://lidemy-http-challenge.herokuapp.com/lv3?token={5566NO1}&id=1989
Tip: 見 API 文件上,新增書籍需要使用到 POST method,在 headers 內,除了寫提交表單(form),還要記得內容格式(content-type)為application/x-www-form-urlencoded(default),其他格式參見 npm request,表單格式,依照 API 文件說明,參數有:「name: 書名, ISBN: 書籍編號」,最後再使用 console.log(body),會印出{"message":"新增成功","id":"1989"}


Lv 4: https://lidemy-http-challenge.herokuapp.com/lv4?token={LEarnHOWtoLeArn}&id=79
法 1: 自己想到的解法:尋找書籍含有「世界」二字,可以使用 process.argv 的參數,在執行 node xx.js 時,加入所需參數「世界」,並印出所有包含「世界」的書名,尋找作者「村上春樹」。

const request = require('request')
const process = require('process')
if ( process.argv[2]  === 'read') {
  request.get(
    {
      url: 'https://lidemy-http-challenge.herokuapp.com/api/books/',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'},
    },
    (error, response, body) => {
      const json = JSON.parse(body)
      for (let i=0; i< json.length ; i++) {
        if (json[i].name.indexOf(process.argv[3]) !== -1) {
          console.log(json[i])
        }
      }
    }
  )
}
$ node lv4.js read 世界
{ id: 2, name: '當我想你時,全世界都救不了我', author: '肆一', ISBN: '5549173495' }
{ id: 27, name: '從你的全世界路過', author: '張嘉佳', ISBN: '8426216529' }
{ id: 79, name: '世界末日與冷酷異境', author: '村上春樹', ISBN: '9571313408' }
{
  id: 90,
  name: '文學的40堂公開課:從神話到當代暢銷書,文學如何影響我們、帶領我們理解這個世界',
  author: '約翰.薩德蘭',
  ISBN: '7978376866'
}

法 2: 參考他人的解法:利用 ‵encodeURI()‵ 將「世界」編碼,帶入 API 網址搜尋後印出結果。


Lv 5:

const request = require('request')
const process = require('process')

if (process.argv[2] === 'delete') {
    let idNum = process.argv[3];
    request.delete(
      'https://lidemy-http-challenge.herokuapp.com/api/books/'+idNum,
      (error, response, body) => {
        if (!error && response.statusCode >= 200) {
          console.log('body',body)
          console.log(`statusCode: ${response.statusCode}`)
        }
        }
    )
}
$ node lv5.js delete 23
{"message":"\n咦...是刪掉了沒錯,但總覺得哪裡怪怪的,算了,先這樣吧!下一關的 token 為 {CHICKENCUTLET}\n"}
statusCode: 200

lv 6: https://lidemy-http-challenge.herokuapp.com/lv6?token=%7BCHICKENCUTLET%7D&email=lib@lidemy.com

從 API 文件中,得知 username: password 的內容格式,拿去 Base64 編碼,得到Authorization: xxxx 後,放進 headers 裡面。

const request = require('request')
//https://lidemy-http-challenge.herokuapp.com/api/v2/sys_info
request.get(
  {
    url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/me',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': 'Basic YWRtaW46YWRtaW4xMjM='
    }
  },
  (error, response, body) => {
    if (!error && response.statusCode >= 200) {
      console.log('body:',body)
      console.log(`statusCode: ${response.statusCode}`)
    }
  }
)
$ node lv6.js
body: {"username":"admin","email":"lib@lidemy.com"}
statusCode: 200

lv 7:
依照 API 文件刪除書籍的 request method: delete,再用 console.log 印出 body 及 statusCode 確認結果。

const request = require('request')
if (process.argv[2] === 'delete') {
 let idNum = process.argv[3];
  request.delete(
    {
      url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/books/'+idNum,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM='
      }
    },
    (error, response, body) => {
      if (!error && response.statusCode >= 200) {
        const json = JSON.parse(body)
        console.log('body:',json.message)
        console.log(`statusCode: ${response.statusCode}`)
      }
    }
  )
}
$ node lv7.js delete 89
body:
希望下一次進這本書的時候不會再被偷走了。下一關的 token 為 {HsifnAerok}

statusCode: 200

Lv 8:

  1. 先使用 node xx..js read 我 尋找書本,但是將題目所要求的條件一:作者名稱 4 個字,及條件二: ISBN 末碼為 7 的書本利用 if 條件式挑出來,印出書本的 id,再使用 node xx.js update <idNumber> <BookNewISBN> 將書本更新資訊。
const request = require('request')
const process = require('process')

if (process.argv[2] === 'update') {
 let idNum = process.argv[3];
 let newISBN = process.argv[4];
  request.patch(
    {
      url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/books/'+idNum,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM='
      },
      form: {
          ISBN: newISBN
      }
    },
    (error, response, body) => {
      if (!error && response.statusCode >= 200) {
        const json = JSON.parse(body)
        console.log('body message:',json.message)
        console.log(`statusCode: ${response.statusCode}`)
      }
    }
  )
} else if (process.argv[2] === 'read') {
  let keyword = process.argv[3]
  request.get(
    {
      url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/books?q=',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM='
      },
    },
    (error, response, body) => {
      if (!error && response.statusCode >= 200) {
        const json = JSON.parse(body)
        for (let i=0; i< json.length; i++) {
          let bookname=json[i].name;
          let thisISBN = json[i].ISBN
          let thisAuthor = json[i].author
          if ( bookname.indexOf(process.argv[3]) !== -1) {
            if (thisAuthor.length === 4) {
               if (thisISBN[thisISBN.length-1] === '7') {
                //console.log('thisISBN.length:',thisISBN.length-1, thisISBN[thisISBN.length-1])
                console.log(json[i].id, json[i].name, json[i].ISBN)
               }
            }  
          }
        }
      }
      console.log(`statusCode: ${response.statusCode}`)
    }
  )
}
$ node lv8.js read 我
72 日日好日:茶道教我的幸福15味【電影書腰版】 9981835427
statusCode: 200

$ node lv8.js update 72 9981835423
body message:
希望之後他們能引進語音輸入系統,我就只要講講話就好。下一關的 token 為 {NeuN}

statusCode: 200

Lv9: http://lidemy-http-challenge.herokuapp.com/lv9?token=%7BNeuN%7D&version=1A4938Jl7

什麼是 User Agent 呢?中文為「使用者代理」,當 server 端一旦收到 client 端的身份識別後,就會做出相對的回應,例如:client 端是從電腦端還是手機端,這樣就 server 端就可以 response 出手機形式的網頁或者是電腦形式的網頁,提升 client 的使用體驗。

那 IE6 的 user Agent 是什麼呢?搜尋了 MDN 等等,好像都是其他版本的瀏覽器,例如 Chrome、IE9等等,然後複製上 user Agent,得到的是 Invalid。所以又搜尋了一番!終於在 stackFlow 上找到 IE6 的 user Agent。

const request = require('request')
const process = require('process')
request.get(
  {
    url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/sys_info',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': 'Basic YWRtaW46YWRtaW4xMjM=',
      'X-Library-Number': '20',
      'User-Agent': 'MMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'
    }
  },
  (error, response, body) => {
    if (!error && response.statusCode >= 200) {
      const json = JSON.parse(body)
      console.log(body)
      console.log(`statusCode: ${response.statusCode}`)
    }
  }
)
$ node lv9_1.js
body {"message":"success","version":"1A4938Jl7","owner":"lib","createdAt":"121290329301"}
statusCode: 200

Lv 10: http://lidemy-http-challenge.herokuapp.com/lv10?token=%7BduZDsG3tvoA%7D&num=9613


參考:

  1. 參考別種解法:Lidemy HTTP Challenge 破關紀錄

  2. 什麼是 URLEncode:[轉] 混亂的 URLEncode

  3. URL 編碼意思:UrlEncodeDecode

  4. 什麼是 HTTP 基本認證:HTTP基本認證 Wikipedia

  5. 什麼是 userAgent:要怎麼辨別使用者瀏覽者用哪種瀏覽器呢?用UserAgent是最簡單的方式喔!

  6. IE6 的 userAgent:Why is IE9 sending a user agent string of IE6?


#API #node.js







Related Posts

不可不知的小工具-cURL

不可不知的小工具-cURL

[極短篇] 資料庫的 ACID 是什麼?

[極短篇] 資料庫的 ACID 是什麼?

有空的話來學一下 Tailwind CSS - Week 1

有空的話來學一下 Tailwind CSS - Week 1


Comments