CoffeeScript 基本的 HTTP 服務(wù)器

2022-06-29 17:13 更新

基本的 HTTP 服務(wù)器

問(wèn)題

你想在網(wǎng)絡(luò)上創(chuàng)建一個(gè)HTTP服務(wù)器。在這個(gè)方法中,我們將逐步從最小的服務(wù)器成為一個(gè)功能鍵值存儲(chǔ)。

解決方案

我們將使用node.js HTTP庫(kù)并在Coffeescript中創(chuàng)建最簡(jiǎn)單的web服務(wù)器。

開始 'hi\n'

我們可以通過(guò)導(dǎo)入node.js HTTP模塊開始。這會(huì)包含createServer,一個(gè)簡(jiǎn)單的請(qǐng)求處理程序返回HTTP服務(wù)器。我們可以使用該服務(wù)器監(jiān)聽TCP端口。

http = require 'http'
server = http.createServer (req, res) -> res.end 'hi\n'
server.listen 8000

要運(yùn)行這個(gè)例子,只需放在一個(gè)文件中并運(yùn)行它。你可以用ctrl-c終止它。我們可以使用curl命令測(cè)試它,可用在大多數(shù)*nix平臺(tái):

$ curl -D - http://localhost:8000/
HTTP/1.1 200 OK
Connection: keep-alive
Transfer-Encoding: chunked

hi

發(fā)生什么了?

讓我們一點(diǎn)點(diǎn)來(lái)反饋服務(wù)器上發(fā)生的事情。這時(shí),我們可以友好的對(duì)待用戶并提供他們一些HTTP頭文件。

http = require 'http'

server = http.createServer (req, res) ->
    console.log req.method, req.url
    data = 'hi\n'
    res.writeHead 200,
        'Content-Type':     'text/plain'
        'Content-Length':   data.length
    res.end data

server.listen 8000

再次嘗試訪問(wèn)它,但是這一次使用不同的URL路徑,比如http://localhost:8000/coffee。你會(huì)看到這樣的服務(wù)器控制臺(tái):

$ coffee http-server.coffee 
GET /
GET /coffee
GET /user/1337

得到的東西

假如我們的網(wǎng)絡(luò)服務(wù)器能夠保存一些數(shù)據(jù)會(huì)怎么樣?我們將在通過(guò)GET方法請(qǐng)求檢索的元素中設(shè)法想出一個(gè)簡(jiǎn)單的鍵值存儲(chǔ)。并提供一個(gè)關(guān)鍵路徑,服務(wù)器將請(qǐng)求返回相應(yīng)的值,如果不存在則返回404錯(cuò)誤。

http = require 'http'

store = # we'll use a simple object as our store
    foo:    'bar'
    coffee: 'script'

server = http.createServer (req, res) ->
    console.log req.method, req.url

    value = store[req.url[1..]]

    if not value
        res.writeHead 404
    else
        res.writeHead 200,
            'Content-Type': 'text/plain'
            'Content-Length': value.length + 1
        res.write value + '\n'

    res.end()

server.listen 8000

我們可以試試幾種url,看看它們?nèi)绾位貞?yīng):

$ curl -D - http://localhost:8000/coffee
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 7
Connection: keep-alive

script

$ curl -D - http://localhost:8000/oops
HTTP/1.1 404 Not Found
Connection: keep-alive
Transfer-Encoding: chunked

使用你的頭文件

text/plain是站不住腳的。如果我們使用application/json或text/xml會(huì)怎么樣?同時(shí),我們的存儲(chǔ)檢索過(guò)程也可以用一點(diǎn)重構(gòu)——一些異常的拋出&處理怎么樣? 來(lái)看看我們能想出什么:

http = require 'http'

# known mime types
[any, json, xml] = ['*/*', 'application/json', 'text/xml']

# gets a value from the db in format [value, contentType]
get = (store, key, format) ->
    value = store[key]
    throw 'Unknown key' if not value
    switch format
        when any, json then [JSON.stringify({ key: key, value: value }), json]
        when xml then ["<key>#{ key }</key>\n<value>#{ value }</value>", xml]
        else throw 'Unknown format'

store =
    foo:    'bar'
    coffee: 'script'

server = http.createServer (req, res) ->
    console.log req.method, req.url

    try
        key = req.url[1..]
        [value, contentType] = get store, key, req.headers.accept
        code = 200
    catch error
        contentType = 'text/plain'
        value = error
        code = 404

    res.writeHead code,
        'Content-Type': contentType
        'Content-Length': value.length + 1
    res.write value + '\n'
    res.end()

server.listen 8000

這個(gè)服務(wù)器仍然會(huì)返回一個(gè)匹配給定鍵的值,如果不存在則返回404錯(cuò)誤。但它根據(jù)標(biāo)頭Accept將響應(yīng)在JSON或XML結(jié)構(gòu)中??捎H眼看一下:

$ curl http://localhost:8000/
Unknown key

$ curl http://localhost:8000/coffee
{"key":"coffee","value":"script"}

$ curl -H "Accept: text/xml" http://localhost:8000/coffee
<key>coffee</key>
<value>script</value>

$ curl -H "Accept: image/png" http://localhost:8000/coffee
Unknown format

你需要有所返回

我們的最后一步是提供客戶端存儲(chǔ)數(shù)據(jù)的能力。我們將通過(guò)監(jiān)聽POST請(qǐng)求來(lái)保持RESTiness。

http = require 'http'

# known mime types
[any, json, xml] = ['*/*', 'application/json', 'text/xml']

# gets a value from the db in format [value, contentType]
get = (store, key, format) ->
    value = store[key]
    throw 'Unknown key' if not value
    switch format
        when any, json then [JSON.stringify({ key: key, value: value }), json]
        when xml then ["<key>#{ key }</key>\n<value>#{ value }</value>", xml]
        else throw 'Unknown format'

# puts a value in the db
put = (store, key, value) ->
    throw 'Invalid key' if not key or key is ''
    store[key] = value

store =
    foo:    'bar'
    coffee: 'script'

# helper function that responds to the client
respond = (res, code, contentType, data) ->
    res.writeHead code,
        'Content-Type': contentType
        'Content-Length': data.length
    res.write data
    res.end()

server = http.createServer (req, res) ->
    console.log req.method, req.url
    key = req.url[1..]
    contentType = 'text/plain'
    code = 404

    switch req.method
        when 'GET'
            try
                [value, contentType] = get store, key, req.headers.accept
                code = 200
            catch error
                value = error
            respond res, code, contentType, value + '\n'

        when 'POST'
            value = ''
            req.on 'data', (chunk) -> value += chunk
            req.on 'end', () ->
                try
                    put store, key, value
                    value = ''
                    code = 200
                catch error
                    value = error + '\n'
                respond res, code, contentType, value

server.listen 8000

在一個(gè)POST請(qǐng)求中注意數(shù)據(jù)是如何接收的。通過(guò)在“數(shù)據(jù)”和“結(jié)束”請(qǐng)求對(duì)象的事件中附上一些處理程序,我們最終能夠從客戶端緩沖和保存數(shù)據(jù)。

$ curl -D - http://localhost:8000/cookie
HTTP/1.1 404 Not Found # ...
Unknown key

$ curl -D - -d "monster" http://localhost:8000/cookie
HTTP/1.1 200 OK # ...

$ curl -D - http://localhost:8000/cookie
HTTP/1.1 200 OK # ...
{"key":"cookie","value":"monster"}

討論

給http.createServer一個(gè)函數(shù) (request,response) - >…… 它將返回一個(gè)服務(wù)器對(duì)象,我們可以用它來(lái)監(jiān)聽一個(gè)端口。讓服務(wù)器與request和response對(duì)象交互。使用server.listen 8000監(jiān)聽端口8000。

在這個(gè)問(wèn)題上的API和整體信息,參考node.js httphttps文檔頁(yè)面。此外,HTTP spec可能派上用場(chǎng)。

練習(xí)

在服務(wù)器和開發(fā)人員之間創(chuàng)建一個(gè)層,允許開發(fā)人員做類似的事情:

server = layer.createServer
    'GET /': (req, res) ->
        ...
    'GET /page': (req, res) ->
        ...
    'PUT /image': (req, res) ->
        ...
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)