Skip to content

Commit

Permalink
feat: add json option to http (#34)
Browse files Browse the repository at this point in the history
- uses aegir test helps
- updates deps 
- adds more tests 

Co-authored-by: Alex Potsides <[email protected]>
  • Loading branch information
hugomrdias and achingbrain authored Apr 14, 2020
1 parent 34dc3c9 commit 070a456
Show file tree
Hide file tree
Showing 14 changed files with 71 additions and 108 deletions.
56 changes: 9 additions & 47 deletions .aegir.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,21 @@
'use strict'

const { promisify } = require('util')
const http = require('http')
const url = require('url')
const querystring = require('querystring')
const EchoServer = require('aegir/utils/echo-server')
const { format } =require('iso-url')

const echoServer = async (port = 3000) => {
const server = http.createServer()

server.on('request', (request, response) => {
try {

const uri = url.parse(request.url)
const qs = uri.query ? querystring.parse(uri.query) : {}
const status = qs.status || 200
const contentType = qs.contentType || 'text/plain'

const headers = {
'Access-Control-Allow-Origin': '*'
}

if (qs.body) {
headers['Content-Type'] = contentType
headers['Content-Length'] = qs.body.length
}

response.writeHead(status, headers)

if (qs.body) {
response.end(qs.body)
} else {
request.pipe(response)
}

} catch (err) {
console.error(err)
}
})

await promisify(server.listen.bind(server))(port)

return {
stop: promisify(server.close.bind(server))
}
}

let echo
let echo = new EchoServer()

module.exports = {
hooks: {
pre: async () => {
echo = await echoServer()
const server = await echo.start()
const { address, port } = server.server.address()
return {
env: { ECHO_SERVER : format({ protocol: 'http:', hostname: address, port })}
}
},
post: async () => {
await echo.stop()
}
}
}
}
7 changes: 2 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,13 @@
"iso-url": "^0.4.7",
"it-glob": "0.0.7",
"merge-options": "^2.0.0",
"nanoid": "^2.1.11",
"nanoid": "^3.1.3",
"node-fetch": "^2.6.0",
"stream-to-it": "^0.2.0"
},
"devDependencies": {
"aegir": "^21.4.2",
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"aegir": "^21.8.0",
"delay": "^4.3.0",
"dirty-chai": "^2.0.1",
"it-all": "^1.0.1",
"it-drain": "^1.0.0",
"it-last": "^1.0.1",
Expand Down
13 changes: 12 additions & 1 deletion src/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ const fetch = require('node-fetch')
const merge = require('merge-options')
const { URL, URLSearchParams } = require('iso-url')
const TextDecoder = require('./text-encoder')
const Request = require('./globalthis').Request
const AbortController = require('abort-controller')

const Request = fetch.Request
const Headers = fetch.Headers

class TimeoutError extends Error {
constructor () {
super('Request timed out')
Expand Down Expand Up @@ -49,6 +51,7 @@ const timeout = (promise, ms, abortController) => {
}

const defaults = {
headers: {},
throwHttpErrors: true,
credentials: 'same-origin',
transformSearchParams: p => p
Expand All @@ -57,6 +60,7 @@ const defaults = {
/**
* @typedef {Object} APIOptions - creates a new type named 'SpecialType'
* @prop {any} [body] - Request body
* @prop {Object} [json] - JSON shortcut
* @prop {string} [method] - GET, POST, PUT, DELETE, etc.
* @prop {string} [base] - The base URL to use in case url is a relative URL
* @prop {Headers|Record<string, string>} [headers] - Request header.
Expand All @@ -78,6 +82,7 @@ class HTTP {
constructor (options = {}) {
/** @type {APIOptions} */
this.opts = merge(defaults, options)
this.opts.headers = new Headers(options.headers)

// connect internal abort to external
this.abortController = new AbortController()
Expand All @@ -101,6 +106,7 @@ class HTTP {
async fetch (resource, options = {}) {
/** @type {APIOptions} */
const opts = merge(this.opts, options)
opts.headers = new Headers(opts.headers)

// validate resource type
if (typeof resource !== 'string' && !(resource instanceof URL || resource instanceof Request)) {
Expand All @@ -127,6 +133,11 @@ class HTTP {
url.search = opts.transformSearchParams(new URLSearchParams(opts.searchParams))
}

if (opts.json !== undefined) {
opts.body = JSON.stringify(opts.json)
opts.headers.set('content-type', 'application/json')
}

const response = await timeout(fetch(url, opts), opts.timeout, this.abortController)

if (!response.ok && opts.throwHttpErrors) {
Expand Down
2 changes: 1 addition & 1 deletion src/temp-dir.browser.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const nanoid = require('nanoid')
const { nanoid } = require('nanoid')

/**
* Temporary folder
Expand Down
2 changes: 1 addition & 1 deletion src/temp-dir.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const fs = require('fs')
const os = require('os')
const path = require('path')
const nanoid = require('nanoid')
const { nanoid } = require('nanoid')

/**
* Temporary folder
Expand Down
6 changes: 1 addition & 5 deletions test/env.spec.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
'use strict'

/* eslint-env mocha */
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const { expect } = require('aegir/utils/chai')
const env = require('../src/env')

chai.use(dirtyChai)
const expect = chai.expect

describe('env', function () {
it('isElectron should have the correct value in each env', function () {
switch (process.env.AEGIR_RUNNER) {
Expand Down
6 changes: 1 addition & 5 deletions test/files/format-mode.spec.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
'use strict'

/* eslint-env mocha */
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const { expect } = require('aegir/utils/chai')
const formatMode = require('../../src/files/format-mode')

chai.use(dirtyChai)
const expect = chai.expect

describe('format-mode', function () {
it('formats mode for directories', function () {
expect(formatMode(parseInt('0777', 8), true)).to.equal('drwxrwxrwx')
Expand Down
6 changes: 1 addition & 5 deletions test/files/format-mtime.spec.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
'use strict'

/* eslint-env mocha */
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const { expect } = require('aegir/utils/chai')
const formatMtime = require('../../src/files/format-mtime')

chai.use(dirtyChai)
const expect = chai.expect

describe('format-mtime', function () {
it('formats mtime', function () {
expect(formatMtime({ secs: 15768000, nsecs: 0 })).to.include('1970')
Expand Down
8 changes: 1 addition & 7 deletions test/files/glob-source.spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
'use strict'

/* eslint-env mocha */
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const chaiAsPromised = require('chai-as-promised')
const { expect } = require('aegir/utils/chai')
const globSource = require('../../src/files/glob-source')
const all = require('it-all')
const path = require('path')
Expand All @@ -12,10 +10,6 @@ const {
} = require('../../src/env')
const fs = require('fs')

chai.use(dirtyChai)
chai.use(chaiAsPromised)
const expect = chai.expect

function fixture (file) {
return path.resolve(path.join(__dirname, '..', 'fixtures', file))
}
Expand Down
8 changes: 2 additions & 6 deletions test/files/normalise-input.spec.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
'use strict'

/* eslint-env mocha */
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const { expect, assert } = require('aegir/utils/chai')
const normalise = require('../../src/files/normalise-input')
const { supportsFileReader } = require('../../src/supports')
const { Buffer } = require('buffer')
const all = require('it-all')
const globalThis = require('../../src/globalthis')

chai.use(dirtyChai)
const expect = chai.expect

const STRING = () => 'hello world'
const BUFFER = () => Buffer.from(STRING())
const ARRAY = () => Array.from(BUFFER())
Expand All @@ -36,7 +32,7 @@ async function verifyNormalisation (input) {
expect(input.length).to.equal(1)

if (!input[0].content[Symbol.asyncIterator] && !input[0].content[Symbol.iterator]) {
chai.assert.fail('Content should have been an iterable or an async iterable')
assert.fail('Content should have been an iterable or an async iterable')
}

expect(await all(input[0].content)).to.deep.equal([BUFFER()])
Expand Down
4 changes: 2 additions & 2 deletions test/files/url-source.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/* eslint-env mocha */

const { expect } = require('../utils/chai')
const { expect } = require('aegir/utils/chai')
const all = require('it-all')
const urlSource = require('../../src/files/url-source')
const last = require('it-last')
Expand All @@ -11,7 +11,7 @@ const { Buffer } = require('buffer')
describe('url-source', function () {
it('can get url content', async function () {
const content = 'foo'
const file = await last(urlSource(`http://localhost:3000?body=${content}`))
const file = await last(urlSource(`${process.env.ECHO_SERVER}/download?data=${content}`))

await expect(all(file.content)).to.eventually.deep.equal([Buffer.from(content)])
})
Expand Down
45 changes: 37 additions & 8 deletions test/http.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

/* eslint-env mocha */
const { expect } = require('./utils/chai')
const { expect } = require('aegir/utils/chai')
const HTTP = require('../src/http')
const toStream = require('it-to-stream')
const delay = require('delay')
Expand All @@ -13,15 +13,43 @@ const { Buffer } = require('buffer')

describe('http', function () {
it('makes a GET request', async function () {
const res = HTTP.get('http://localhost:3000')
const req = await HTTP.get(`${process.env.ECHO_SERVER}/echo/query?test=one`)
const rsp = await req.json()
expect(rsp).to.be.deep.eq({ test: 'one' })
})

it('makes a GET request with redirect', async function () {
const req = await HTTP.get(`${process.env.ECHO_SERVER}/redirect?to=${encodeURI(`${process.env.ECHO_SERVER}/echo/query?test=one`)}`)
const rsp = await req.json()
expect(rsp).to.be.deep.eq({ test: 'one' })
})

it('makes a JSON request', async () => {
const req = await HTTP.post(`${process.env.ECHO_SERVER}/echo`, {
json: {
test: 2
}
})

const out = await req.text()
expect(out).to.be.eq('{"test":2}')
})

it('makes a DELETE request', async () => {
const req = await HTTP.delete(`${process.env.ECHO_SERVER}/echo`, {
json: {
test: 2
}
})

await expect(res).to.eventually.be.fulfilled()
const out = await req.text()
expect(out).to.be.eq('{"test":2}')
})

it('allow async aborting', async function () {
const controller = new AbortController()

const res = HTTP.get('http://localhost:3000', {
const res = HTTP.get(process.env.ECHO_SERVER, {
signal: controller.signal
})
controller.abort()
Expand All @@ -30,7 +58,7 @@ describe('http', function () {
})

it('parses the response as ndjson', async function () {
const res = await HTTP.post('http://localhost:3000', {
const res = await HTTP.post(`${process.env.ECHO_SERVER}/echo`, {
body: '{}\n{}'
})

Expand All @@ -40,7 +68,8 @@ describe('http', function () {
})

it('parses the response as an async iterable', async function () {
const res = await HTTP.post('http://localhost:3000', {
const res = await HTTP.post('echo', {
base: process.env.ECHO_SERVER,
body: 'hello world'
})

Expand All @@ -64,7 +93,7 @@ describe('http', function () {
throw err
}())

const res = await HTTP.post('http://localhost:3000', {
const res = await HTTP.post(process.env.ECHO_SERVER, {
body: toStream.readable(body)
})

Expand All @@ -87,7 +116,7 @@ describe('http', function () {
throw err
}())

const res = await HTTP.post('http://localhost:3000', {
const res = await HTTP.post(process.env.ECHO_SERVER, {
body: toStream.readable(body),
signal: controller.signal
})
Expand Down
6 changes: 1 addition & 5 deletions test/supports.spec.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
'use strict'

/* eslint-env mocha */
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const { expect } = require('aegir/utils/chai')
const supports = require('../src/supports')
const env = require('../src/env')

chai.use(dirtyChai)
const expect = chai.expect

describe('supports', function () {
it('supportsFileReader should return false in node', function () {
if (env.isNode) {
Expand Down
10 changes: 0 additions & 10 deletions test/utils/chai.js

This file was deleted.

0 comments on commit 070a456

Please sign in to comment.