neft
Version:
Universal Platform
164 lines (128 loc) • 5.05 kB
text/coffeescript
'use strict'
utils = require 'src/utils'
http = require 'http'
https = require 'https'
urlUtils = require 'url'
pathUtils = require 'path'
assert = require 'src/assert'
nodeStatic = require 'node-static'
FormData = require 'form-data'
qs = require 'qs'
EXT_TYPES =
__proto__: null
'.js': 'text'
'.txt': 'text'
'.json': 'json'
pending = Object.create null
staticServer = new nodeStatic.Server gzip: true
module.exports = (Networking) ->
Request: require('./request') Networking, pending
Response: Response = require('./response') Networking, pending
init: (networking) ->
assert.instanceOf networking, Networking
switch networking.protocol
when 'http'
server = http.createServer()
when 'https'
server = https.createServer()
else
throw new Error "Unsupported protocol '#{networking.protocol}'"
server.listen networking.port, networking.host
server.on 'request', (serverReq, serverRes) ->
serverRes.setTimeout 0
data = ''
serverReq.on 'data', (chunk) ->
data += chunk
serverReq.on 'end', ->
if ///^(?:\/static\/|\/build\/static\/)///.test(serverReq.url)
staticServer.serve serverReq, serverRes
return
{url} = serverReq
url = url.replace /(?:&|\?)now=\d+/, ''
uid = utils.uid()
parsedUrl = urlUtils.parse url
obj = pending[uid] =
networking: networking
server: server
req: null
serverReq: serverReq
serverRes: serverRes
type = serverReq.headers['x-expected-type']
unless type
extname = pathUtils.extname parsedUrl.pathname
type = EXT_TYPES[extname]
type ||= Networking.Request.HTML_TYPE
if data isnt ''
switch serverReq.headers['content-type']
when 'application/x-www-form-urlencoded'
reqData = qs.parse data
else
reqData = utils.tryFunction(JSON.parse, null, [data], data)
else
reqData = null
cookies = serverReq.headers['x-cookies']
if typeof cookies is 'string'
cookies = utils.tryFunction JSON.parse, null, [cookies], null
obj.req = networking.createLocalRequest
uid: uid
method: Networking.Request[serverReq.method]
uri: url
data: reqData
type: type
headers: serverReq.headers
cookies: cookies
sendRequest: (req, res, callback) ->
urlObject = urlUtils.parse req.uri.toString()
opts =
protocol: urlObject.protocol
hostname: urlObject.hostname
port: urlObject.port
auth: urlObject.auth
path: urlObject.path
method: req.method
headers: utils.clone(req.headers)
opts.headers['X-Expected-Type'] = req.type
if cookies = utils.tryFunction JSON.stringify, null, [req.cookies], null
opts.headers['X-Cookies'] = cookies
switch urlObject.protocol
when 'http:'
reqModule = http
when 'https:'
reqModule = https
else
callback
status: 500
data: new Error "Unsupported protocol '#{urlObject.protocol}'"
return
nodeReq = reqModule.request opts, (nodeRes) ->
nodeRes.setEncoding res.encoding
nodeRes.setTimeout 0
data = ''
nodeRes.on 'data', (chunk) ->
data += chunk
nodeRes.on 'end', ->
status = nodeRes.statusCode
if req.type is Networking.Request.JSON_TYPE
data = utils.tryFunction JSON.parse, null, [data], data
if cookies = nodeRes.headers['x-cookies']
cookies = utils.tryFunction JSON.parse, null, [cookies], null
callback
status: status
data: data
headers: nodeRes.headers
cookies: cookies
nodeReq.on 'error', (e) ->
callback
status: 500
data: e
data = Response._prepareData req.type, nodeReq, req.data
Response._sendData req.type, null, nodeReq, data, (err) ->
if err
callback err