Lidemy HTTP Challenge 破關紀錄


Posted by ai86109 on 2020-07-09

前言

這是 Huli 大大做的一個有趣的 http 遊戲,可以藉由這個遊戲更加了解 http 的各項知識,建議先了解基礎知識再來解題會比較知道在幹嘛,可以參考我之前的筆記 網路的本質其實沒有你想的那麼難最熟悉的陌生人:API

那廢話不多說,就馬上開始吧!
.
.
.
.
以下為我的解題心得,有雷慎入
.
.
.
.
.


Lv0

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

這邊只是介紹這個遊戲,所以靠著這邊的提示,就可以到第一關。


lv1

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

這邊有提供一個串接 API 的文件,但這邊不會用到:API 文件

一樣是依照描述把 name 帶上,這邊就看你叫什麼就打什麼
https://lidemy-http-challenge.herokuapp.com/lv1?token={GOGOGO}&name=Derek


lv2

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

這邊我是從 54~58之間一個一個試的
https://lidemy-http-challenge.herokuapp.com/lv2?token={HellOWOrld}&id=56


lv3

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

這關就要利用到剛剛的 API 文件

因為這邊會用到 POST 這個 method,而文件上也說了如果使用 POST,他的 content type 是 application/x-www-form-urlencoded。

意思就是如果你要傳資料給他的話,必須符合 application/x-www-form-urlencoded 的格式傳送(這邊因為使用 request 這個 library,所以要按照這個格式),其他常見格式還有 multipart/form-dataapplication/json等。

確認好格式之後就可以來新增了,POST 成功印出 body 會得到 {"message":"新增成功","id":"1989"}

完整程式碼如下:

const request = require('request');

request.post(
    'https://lidemy-http-challenge.herokuapp.com/api/books',
    {form:{
        name: '《大腦喜歡這樣學》',
        ISBN: '9789863594475'
    }},
    (err, response, body) => {
        console.log(body)
    }
)

把得到的 id 帶上網址就是答案了!
https://lidemy-http-challenge.herokuapp.com/lv3?token={5566NO1}&id=1989

*這邊要補充的是,前面有說到 content type,他是放在 headers 裡的資訊。當 server 告訴你要使用 application/x-www-form-urlencoded 的格式傳送資料,而你也用相應的格式帶上了:

form:{
        name: '123',
        ISBN: 456
    }

透過編碼,就會透過這個格式產生像這樣的資料放在 body 裡 body: 'name=123&ISBN=456'
而 server 接收到這個 request 後才能做相對應的動作,但如果你給了不正確或不符合的格式,server 端就會看不懂,造成錯誤。

*另外,這樣的格式要小心的地方是,他可能輸出的跟你想的不一樣,什麼意思呢?

form:{
        name: '123',
        ISBN: 'a&b=1'
    }

假設你帶上這樣的資訊,它在轉換時就會變成 name=123&ISBN=a&b=1,是不是發現問題了。
x-www-form-urlencoded 最後面的 urlencoded 就是編碼的意思,我們必須使用編碼的方式,把它轉換成別種形式,才可以避免混淆。
所以這邊可以用 encodeURIComponent('a&b=1'),編碼完成再帶入。因為帶入的資訊是動態的,所以通常我們會都經過編碼後再帶入資訊。


lv4

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

這邊要你使用獲取所有書籍,並且後面帶入查詢書籍的參數,所以直覺的就寫成以下:

const request = require('request');

request.get(
    'https://lidemy-http-challenge.herokuapp.com/api/books?q=世界',
    (err, response, body) => {
        console.log(body)
    }
)

不過這時候會跳出報錯的訊息,TypeError [ERR_UNESCAPED_CHARACTERS]: Request path contains unescaped characters,表示使用 get 或 post 的方式發 request 到後台,且 url 中包含中文。

為了解決這個問題,便利用 encodeURI() 將中文字串轉為 UTF-8 編碼

const request = require('request');
const str = encodeURI('世界')

request.get(
    `https://lidemy-http-challenge.herokuapp.com/api/books?q=${str}`,
    (err, response, body) => {
        console.log(body)
    }
)

這樣便可以印出所有書名包含『世界』的書了。

根據線索就會知道是 id = 79 的『世界末日與冷酷異境』
https://lidemy-http-challenge.herokuapp.com/lv4?token={LEarnHOWtoLeArn}&id=79


lv5

https://lidemy-http-challenge.herokuapp.com/lv5?token={HarukiMurakami}
*這邊的 token 就是村上春樹(Haruki Murakami)

照著文件做還滿簡單的

const request = require('request');

request.delete(
    'https://lidemy-http-challenge.herokuapp.com/api/books/23',
    (err, response, body) => {
        console.log(body)
    }
)

成功刪除後就會印出答案,{"message":"\n咦...是刪掉了沒錯,但總覺得哪裡怪怪的,算了,先這樣吧!下一關的 token 為 {CHICKENCUTLET}\n"}


lv6
https://lidemy-http-challenge.herokuapp.com/lv6?token={CHICKENCUTLET}

這邊拿到一個新文件:新文件

這關主要是要你將資訊放入 request 的 header 中,但這組帳密要以 base64 編碼後的形式帶入,所以就隨便找一個線上可以轉換的即可(提示:Encode to Base64 format)

const request = require('request');

const option = {
    url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/me',
    headers: {
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM='
    }
}

function callback (error, response, body) {
    console.log(body)
}

request(option, callback)

便可以得到 {"username":"admin","email":"lib@lidemy.com"}

按照題目指示放入 query string 中即可。
https://lidemy-http-challenge.herokuapp.com/lv6?token={CHICKENCUTLET}&email=lib@lidemy.com


lv7

https://lidemy-http-challenge.herokuapp.com/lv7?token={SECurityIsImPORTant}

這關一樣是按照文件,滿簡單的

const request = require('request');

const option = {
    url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/books/89',
    headers: {
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM='
    }
}

function callback (error, response, body) {
    console.log(body)
}

request.delete(option, callback)

最後就會印出 {"message":"\n希望下一次進這本書的時候不會再被偷走了。下一關的 token 為 {HsifnAerok}\n"}


lv8

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

這題一樣是先查詢書籍

const request = require('request');

const str = encodeURI('我')

const option = {
    url: `https://lidemy-http-challenge.herokuapp.com/api/v2/books?q=${str}`,
    headers: {
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM='
    }
}

function callback (error, response, body) {
    const json = JSON.parse(body)
    console.log(json)
}

request.get(option, callback)

藉由印出的資訊可以知道,就是 id = 72 的這本書

接下來要做的就是更新資料了

const request = require('request');

const option = {
    url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/books/72',
    headers: {
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM='
    },
    form: {
        ISBN: '9981835423',
    }
}

function callback (error, response, body) {
    console.log(body)
}

request.patch(option, callback)

成功更新資料後就會印出訊息 {"message":"\n希望之後他們能引進語音輸入系統,我就只要講講話就好。下一關的 token 為 {NeuN}\n"}


lv9

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

這邊說要獲取系統資料要符合兩個條件:

  • 第一個條件很簡單,key & value 都給你了
  • 第二個條件有點卡關,之後利用 devtool > network,去檢查 request header,可以看到裡面有 User-Agent 這一項(user agent 指的是你透過什麼來幫你發送 request),接著用關鍵字去找 IE6 的 user agent 要打什麼。
    找到了這個,剛開始只輸入了 Mozilla/4.0,結果印出 Invalid Browser,還想說是不是搞錯方向了,原來是整串都要輸入。
const request = require('request');

const option = {
    url: 'https://lidemy-http-challenge.herokuapp.com/api/v2/sys_info',
    headers: {
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM=',
        'X-Library-Number': '20',
        'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'
    },
}

function callback (error, response, body) {
    console.log(body)
}

request.get(option, callback)

成功印出 {"message":"success","version":"1A4938Jl7","owner":"lib","createdAt":"121290329301"}

最後把 version 的值放入 query string 就可以了!
https://lidemy-http-challenge.herokuapp.com/lv9?token={NeuN}&version=1A4938Jl7


lv10

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

這一關是猜數字,真是懷念XD
就按照給的提示很快就找到答案摟
https://lidemy-http-challenge.herokuapp.com/lv10?token={duZDsG3tvoA}&num=9613

原本應該是最後一關了,但 Huli 似乎又增加了新關卡,之後有空再來玩玩!


lv11

https://lidemy-http-challenge.herokuapp.com/lv11?token={IhateCORS}

這邊提供一份新的 API 文件

按照文件的方法打招呼果然有限制

const request = require('request');

request.get(
    'https://lidemy-http-challenge.herokuapp.com/api/v3/hello',
    (error, response, body) => {
        console.log(body)
    }
)

印出了 您的 origin 不被允許存取此資源,請確認您是從 lidemy.com 送出 request。

所以將 Origin 放進去

const request = require('request');

const option = {
    url: 'https://lidemy-http-challenge.herokuapp.com/api/v3/hello',
    headers: {
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM=',
        'Origin': 'lidemy.com'
    },
}

function callback (error, response, body) {
    console.log(body)
}

request.get(option, callback)

果然這樣就 OK 了!


lv12

https://lidemy-http-challenge.herokuapp.com/lv12?token={r3d1r3c7}

按照文件實作

const request = require('request');

const option = {
    url: 'https://lidemy-http-challenge.herokuapp.com/api/v3/deliver_token',
    headers: {
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM=',
        'Origin': 'lidemy.com'
    },
}

function callback (error, response, body) {
    console.log(body)
}

request.get(option, callback)

果然沒這麼簡單,印出了 我已經把運送要用的 token 給你囉,請你仔細找找

按照題目的提示,這裡應該要去看網頁經過了哪些轉址,再從裡面找線索。

打開 devtool > network,在網址列輸入 https://lidemy-http-challenge.herokuapp.com/api/v3/deliver_token 後可以看到,網頁會依序經過:

  • deliver_token
  • stopover
  • deliver_token_result

而在 deliver_token 和 stopover 的 response header 中都有 X-Lv13-Token,利用這個參數就可以過關啦!


lv13

https://lidemy-http-challenge.herokuapp.com/lv13?token={qspyz}

按照 API 文件

const request = require('request');

const option = {
    url: 'https://lidemy-http-challenge.herokuapp.com/api/v3/logs',
    headers: {
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM=',
        'Origin': 'lidemy.com',
    },
}

function callback (error, response, body) {
    console.log(body)
}

request.get(option, callback)

會印出訊息 此 request 不是來自菲律賓,禁止存取系統資訊。

這邊帶入參數 &hint=1 去看了提示,關鍵字是 proxy。

這邊去到 Chrome 的設定 > 開啟電腦的 proxy 設定 > Mac 會跳轉到網路的代理伺服器設定,這邊會需要輸入 proxy,所以就在網路上隨便搜一組 http 的 proxy,然後把 IP address & port 貼過來即可(記得 http 那一欄要打勾)。

最後把網址貼上 https://lidemy-http-challenge.herokuapp.com/api/v3/logs ,即可得到下一關的 token。

[
 { logType: 'token', value: '{SEOisHard}' }
]

lv14

https://lidemy-http-challenge.herokuapp.com/lv14?token={SEOisHard}

看完還是不知道在幹嘛XD,一樣直接看提示:
伺服器是怎麼辨識是不是 Google 搜尋引擎的?仔細想想之前我們怎麼偽裝自己是 IE6 的

哦哦原來要用 lv9 時用過的 User-Agent,下關鍵字 user agent google search 就可以找到了:Googlebot User Agents,第一個就是。

程式碼如下:

const request = require('request');

const option = {
    url: 'https://lidemy-http-challenge.herokuapp.com/api/v3/index',
    headers: {
        'Authorization': 'Basic YWRtaW46YWRtaW4xMjM=',
        'Origin': 'lidemy.com',
        'User-Agent': 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'
    },
}

function callback (error, response, body) {
    console.log(body)
}

request.get(option, callback)

就會印出最終的答案了!
token for lv15:{ILOVELIdemy!!!}


lv15

https://lidemy-http-challenge.herokuapp.com/lv15?token={ILOVELIdemy!!!}

這樣就破關溜,這裏 Huli 也開了一個 gist 讓大家留言XDD

這個小遊戲好玩又讓我學到很多,雖然中間有些地方真的卡了很久,不過拿到 token 時就是爽,有興趣可以不看解答先玩玩看喔~


#Lidemy HTTP Challenge #API







Related Posts

PHP CodeIgniter 資料庫字詞替換

PHP CodeIgniter 資料庫字詞替換

HTTP 常用 method

HTTP 常用 method

[Note] JS: OOP - Inheritance

[Note] JS: OOP - Inheritance


Comments