Full Code of brianleroux/tiny-json-http for AI

main 1cbfddbe4c62 cached
14 files
22.3 KB
6.6k tokens
1 symbols
1 requests
Download .txt
Repository: brianleroux/tiny-json-http
Branch: main
Commit: 1cbfddbe4c62
Files: 14
Total size: 22.3 KB

Directory structure:
gitextract_t8ymbo8n/

├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── .npmignore
├── .npmrc
├── _read.js
├── _write.js
├── index.js
├── package.json
├── readme.md
├── test-form-urlencoded.js
├── test-get.js
├── test-post.js
├── test-promise.js
└── test-qq-multipart.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/build.yml
================================================
name: Node CI

# Push tests commits; pull_request tests PR merges
on: [ push, pull_request ]

defaults:
  run:
    shell: bash

jobs:

  # Test the build
  build:
    # Setup
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        node-version: [ 12.x, 14.x, 16.x, 18.x ]
        os: [ windows-latest, ubuntu-latest, macOS-latest ]

    # Go
    steps:
      - name: Check out repo
        uses: actions/checkout@v3

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}

      - name: Env
        run: |
          echo "Event name: ${{ github.event_name }}"
          echo "Git ref:    ${{ github.ref }}"
          echo "GH actor:   ${{ github.actor }}"
          echo "SHA:        ${{ github.sha }}"
          VER=`node --version`; echo "Node ver:   $VER"
          VER=`npm --version`; echo "npm ver:    $VER"

      - name: Install
        run: npm install

      - name: Build
        run: npm run build

      - name: Test
        run: npm test
        env:
          CI: true

  # Publish to package registries
  publish:
    # Setup
    needs: build
    if: startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest

    # Go
    steps:
      - name: Check out repo
        uses: actions/checkout@v3

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: lts/*
          registry-url: https://registry.npmjs.org/

      - name: Install
        run: npm install

      - name: Build
        run: npm run build

      - name: Publish @latest to npm
        if: contains(github.ref, 'RC') == false #'!contains()'' doesn't work lol
        run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}


================================================
FILE: .gitignore
================================================
bundle.js
dist.js
node_modules/
package-lock.json


================================================
FILE: .npmignore
================================================
.*
test-*.js
index.js
_read.js
_write.js
node_modules


================================================
FILE: .npmrc
================================================
package-lock=false


================================================
FILE: _read.js
================================================
var http = require('http')
var https = require('https')
var url = require('url')
var qs = require('querystring')

module.exports = function _read(httpMethod, options, callback) {

  // deep copy options
  options = JSON.parse(JSON.stringify(options))

  // alias body = data
  if (options.body && !options.data) {
    options.data = options.body
  }

  // require options.url or fail noisily
  if (!options.url) {
    throw Error('options.url required')
  }

  // setup promise if there is no callback
  var promise
  if (!callback) {
    promise = new Promise(function(res, rej) {
      callback = function(err, result) {
        err ? rej(err) : res(result)
      }
    })
  }

  // parse out the options from options.url
  var opts = url.parse(options.url)
  var method = opts.protocol === 'https:' ? https.request : http.request
  var defaultContentType = 'application/json; charset=utf-8'

  // check for additional query params
  if (options.data) {
    var isSearch = !!opts.search
    options.url += (isSearch? '&' : '?') + qs.stringify(options.data)
    opts = url.parse(options.url)
  }

  // add timeout if it exists
  if (options.timeout) {
    opts.timeout = options.timeout
  }

  // wrangle defaults
  opts.method = httpMethod
  opts.headers = options.headers || {}
  opts.headers['user-agent'] = opts.headers['user-agent'] || opts.headers['User-Agent'] || 'tiny-http'
  opts.headers['content-type'] = opts.headers['content-type'] || opts.headers['Content-Type'] || defaultContentType

  // make a request
  var req = method(opts, function _res(res) {
    var raw = [] // keep our buffers here
    var ok = res.statusCode >= 200 && res.statusCode < 303

    res.on('data', function _data(chunk) {
      raw.push(chunk)
    })

    res.on('end', function _end() {
      var err = null
      var result = null
      var isJSON = res.headers['content-type'] &&
                  (res.headers['content-type'].startsWith('application/json') ||
                   res.headers['content-type'].match(/^application\/.*json/))
      try {
        result = Buffer.concat(raw)

        if (!options.buffer) {
          var strRes = result.toString()
          result = strRes && isJSON ? JSON.parse(strRes) : strRes
        }
      }
      catch(e) {
        err = e
      }

      if (!ok) {
        err = Error('GET failed with: ' + res.statusCode)
        err.raw = res
        err.body = isJSON? JSON.stringify(result) : result.toString()
        err.statusCode = res.statusCode
        callback(err)
      }
      else {
        callback(err, {body:result, headers:res.headers})
      }
    })
  })

  req.on('error', callback)
  req.end()

  return promise
}


================================================
FILE: _write.js
================================================
var qs = require('querystring')
var http = require('http')
var https = require('https')
var FormData = require('@brianleroux/form-data')
var url = require('url')

module.exports = function _write(httpMethod, options, callback) {

  // deep copy options if no buffers being passed in
  let formopts = options.data || options.body
  let notplain = k => typeof formopts[k] != 'string'
  let basic = formopts && Object.keys(formopts).some(notplain) === false
  if (basic) {
    options = JSON.parse(JSON.stringify(options))
  }

  // alias body = data
  if (options.body && !options.data) {
    options.data = options.body
  }

  // require options.url or fail noisily
  if (!options.url) {
    throw Error('options.url required')
  }

  // setup promise if there is no callback
  var promise
  if (!callback) {
    promise = new Promise(function(res, rej) {
      callback = function(err, result) {
        err ? rej(err) : res(result)
      }
    })
  }

  // parse out the options from options.url
  var opts = url.parse(options.url)
  var method = opts.protocol === 'https:'? https.request : http.request
  var defaultContentType = 'application/json; charset=utf-8'

  // add timeout
  if (options.timeout) {
    opts.timeout = timeout
  }

  // wrangle defaults
  opts.method = httpMethod
  opts.headers = options.headers || {}
  opts.headers['user-agent'] = opts.headers['user-agent'] || opts.headers['User-Agent'] || 'tiny-http'
  opts.headers['content-type'] = opts.headers['content-type'] || opts.headers['Content-Type'] || defaultContentType

  // default to regular POST body (url enc)
  var postData = qs.stringify(options.data || {})

  function is(headers, type) {
    var regex = type instanceof RegExp
    var upper = headers['Content-Type']
    var lower = headers['content-type']
    var isU = upper && (regex ? upper.match(type) : upper.startsWith(type))
    var isL = lower && (regex ? lower.match(type) : lower.startsWith(type))
    return isU || isL
  }

  // if we're posting JSON stringify options.data
  var isJSON = is(opts.headers, /^application\/.*json/)
  if (isJSON) {
    postData = JSON.stringify(options.data || {})
  }

    // if we're doing a application/x-www-form-urlencoded to upload files
  // we'll overload `method` and use the custom form-data submit instead of http.request
  var isUrlEncoded = is(opts.headers, 'application/x-www-form-urlencoded')
  if (isUrlEncoded) {
    postData = Object.keys(options.data)
      .map(k => `${encodeURI(k)}=${encodeURI(options.data[k])}`)
      .join('&')
  }

  // ensure we know the len ~after~ we set the postData
  opts.headers['Content-Length'] = Buffer.byteLength(postData)

  // if we're doing a mutipart/form-data to upload files
  // we'll overload `method` and use the custom form-data submit instead of http.request
  var isMultipart = is(opts.headers, 'multipart/form-data')
  if (isMultipart) {
    method = function _multiPartFormDataPost(params, streamback) {
      var form = new FormData
      Object.keys(options.data).forEach(k=> {
        form.append(k, options.data[k])
      })
      // remove stuff generated by form.submit
      delete opts.headers['Content-Type']
      delete opts.headers['content-type']
      delete opts.headers['Content-Length']
      delete opts.headers['content-length']
      // perform a multipart/form-data POST request
      form.submit(opts, function _submit(err, res) {
        if (err) callback(err)
        else streamback(res)
      })
    }
  }

  // make a request
  var req = method(opts, function(res) {
    var raw = [] // keep our buffers here
    var ok = res.statusCode >= 200 && res.statusCode < 303

    res.on('data', function _data(chunk) {
      raw.push(chunk)
    })

    res.on('end', function _end() {
      var err = null
      var result = null

      try {
        result = Buffer.concat(raw)

        if (!options.buffer) {
          var isJSON = is(res.headers, /^application\/.*json/)
          var strRes = result.toString()
          result = strRes && isJSON ? JSON.parse(strRes) : strRes
        }
      }
      catch (e) {
        err = e
      }

      if (!ok) {
        err = Error(httpMethod + ' failed with: ' + res.statusCode)
        err.raw = res
        err.body = result
        err.statusCode = res.statusCode
        callback(err)
      }
      else {
        callback(err, {body:result, headers:res.headers})
      }
    })
  })

  if (!isMultipart) {
    req.on('error', callback)
    req.write(postData)
    req.end()
  }

  return promise
}


================================================
FILE: index.js
================================================
var _read = require('./_read')
var _write = require('./_write')

module.exports = {
  get: _read.bind({}, 'GET'),
  head: _read.bind({}, 'HEAD'),
  options: _read.bind({}, 'OPTIONS'),
  post: _write.bind({}, 'POST'),
  put: _write.bind({}, 'PUT'),
  patch: _write.bind({}, 'PATCH'),
  del: _write.bind({}, 'DELETE'),
  delete: _write.bind({}, 'DELETE'),
}


================================================
FILE: package.json
================================================
{
  "name": "tiny-json-http",
  "version": "7.5.1",
  "main": "dist.js",
  "scripts": {
    "test": "npm run build && tape test-* | tap-spec",
    "build": "esbuild index.js --bundle --outfile=dist.js --platform=node"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/brianleroux/tiny-json-http.git"
  },
  "author": "Brian LeRoux <b@brian.io>",
  "license": "Apache-2.0",
  "devDependencies": {
    "@brianleroux/form-data": "^1.0.3",
    "body-parser": "^1.20.2",
    "esbuild": "^0.17.10",
    "express": "^4.18.2",
    "tap-spec": "^5.0.0",
    "tape": "^5.6.3",
    "uglify-es": "^3.3.7"
  }
}


================================================
FILE: readme.md
================================================
# tiny-json-http

Minimalist `HTTP` client for `GET`, `POST`, `PUT`, `PATCH` and `DELETE` `JSON` payloads

- Zero dependencies: perfect for AWS Lambda
- Sensible default: assumes buffered JSON responses
- System symmetry: Node style errback API, or Promises for use with Async/Await

```bash
npm i tiny-json-http --save
```

### API

#### Read methods
- `tiny.get(options[, callback])`
- `tiny.head(options[, callback])`
- `tiny.options(options[, callback])`

#### Write methods
- `tiny.post(options[, callback])`
- `tiny.put(options[, callback])`
- `tiny.patch(options[, callback])`
- `tiny.del(options[, callback)]`

_*callback is optional, tiny methods will return a promise if no callback is provided_

### Options

- `url` *required*
- `data` form vars for `tiny.post`, `tiny.put`, `tiny.patch`, and `tiny.delete` otherwise querystring vars for `tiny.get`
- `headers` key/value map used for headers (including support for uploading files with `multipart/form-data`)
- `buffer` if set to `true` the response body is returned as a buffer

### Callback values

- `err` a real javascript `Error` if there was one
- `data` an object with `headers` and `body` keys

### Promises

- if no `callback` is provided to the tiny-json-http methods, a promise is returned
- perfect for use of async/await

## Examples

#### With Async / Await

```javascript
var tiny = require('tiny-json-http')
var url = 'http://www.randomkittengenerator.com'

;(async function _iife() {
  try {
    console.log(await tiny.get({url}))
  } catch (err) {
    console.log('ruh roh!', err)
  }
})();
```

#### With Callback

```javascript
var tiny = require('tiny-json-http')
var url = 'http://www.randomkittengenerator.com'

tiny.get({url}, function _get(err, result) {
  if (err) {
    console.log('ruh roh!', err)
  }
  else {
    console.log(result)
  }
})
```

Check out the tests for more examples! :heart_decoration:


================================================
FILE: test-form-urlencoded.js
================================================
var test = require('tape')
var tiny = require('./dist.js')
var http = require('http')
var server
let body = ''

test('startup', t=> {
  t.plan(1)
  server = http.createServer((req, res) => {
    req.on('data', chunk => body += chunk)
    req.on('end', () => {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({
        body: body.concat(),
        gotPost:true,
        ok:true
      }))
    })
  })
  server.listen(3000)
  t.pass('started server')
})

test('supports form-urlencoded bodies', t=> {
  t.plan(3)
  var url = 'http://localhost:3000'
  var data = { foo: 'bar', this: 'is form url encoded!' }
  var headers = { 'content-type': 'application/x-www-form-urlencoded' }
  tiny.post({url, data, headers}, function __posted(err, result) {
    if (err) {
      t.fail(err)
    }
    else {
      t.ok(result, 'got a result')
      t.ok(result.body.gotPost, 'got a post')
      t.equal(result.body.body, 'foo=bar&this=is%20form%20url%20encoded!', 'got form-urlencoded response')
      console.log(result)
    }
  })
})

test('shutdown', t=> {
  t.plan(1)
  server.close()
  t.ok(true, 'closed server')
})


================================================
FILE: test-get.js
================================================
var test = require('tape')
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
var tiny = require('./dist.js')
var server

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended:true}))

app.get('/json', (req, res)=> {
  res.json({hello: 'there'})
})

app.get('/void', (req, res)=> {
  res.json('')
})

app.options('/opts', (req, res) => {
  res.setHeader('allow', 'OPTIONS, GET')
  res.json('')
})

app.get('/goaway', (req, res) => {
  res.setHeader('location', '/')
  res.statusCode = 302
  res.send()
})

test('startup', t=> {
  t.plan(1)
  server = app.listen(3001, x=> {
    t.ok(true, 'started server')
  })
})

test('can get a url', t=> {
  t.plan(3)
  var url = 'https://brian.io'
  tiny.get({url}, function __got(err, result) {
    if (err) {
      t.fail(err.statusCode, 'failed to get')
    }
    else {
      t.ok(result, 'got a result')
      t.ok(result.headers, 'got headers')
      t.ok(result.body, 'got body')
      console.log(result)
    }
  })
})

test('can get json', t=> {
  t.plan(2)
  var url = 'http://localhost:3001/json'
  tiny.get({url}, function __json(err, result) {
    if (err) {
      t.fail(err)
    }
    else {
      t.ok(result, 'got a result')
      t.equal(result.body.hello, 'there', 'body is an object')
      console.log(err, result)
    }
  })
})

test('can get and handle "no content"', t=> {
  t.plan(2)
  var url = 'http://localhost:3001/void'
  tiny.get({url}, function __void(err, result) {
    if (err) {
      t.fail(err)
    }
    else {
      t.ok(result, 'got a result (empty tho)')
      t.is(result.body, '')
      console.log(result)
    }
  })
})


test('get fails gracefully', t=> {
  t.plan(1)
  var url = 'http://nop333.ca'
  tiny.get({url}, function __ruhroh(err, result) {
    if (err) {
      t.ok(err, 'got err as expected')
      console.log(err)
    }
    else {
      t.fail(result, 'should not succeed')
    }
  })
})

test('can head a url', t=> {
  t.plan(2)
  var url = 'https://www.google.com'
  tiny.head({url}, function __got(err, result) {
    if (err) {
      t.fail(err.statusCode, 'failed to head')
    }
    else {
      t.ok(result, 'got a result')
      t.ok(result.headers, 'got headers')
      console.log(JSON.stringify(result, null, 2).substring(0,75), '...')
    }
  })
})

test('can options a url', t=> {
  t.plan(2)
  var url = 'http://localhost:3001/opts'
  tiny.options({url}, function __got(err, result) {
    if (err) {
      t.fail(err.statusCode, 'failed to options')
    }
    else {
      t.ok(result, 'got a result')
      t.ok(result.headers.allow, 'got headers')
      console.log(result)
    }
  })
})

test('can handles redirect', t=> {
  t.plan(2)
  var url = 'http://localhost:3001/goaway'
  tiny.get({url}, function __got(err, result) {
    if (err) {
      t.fail(err.statusCode, 'failed to handle redirect')
    } else {
      t.ok(result, 'got a result')
      t.ok(result.headers.location, 'got a location header')
      console.log(result)
    }
  })
})

test('shutdown', t=> {
  t.plan(1)
  server.close()
  t.ok(true, 'closed server')
})


================================================
FILE: test-post.js
================================================
var test = require('tape')
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
var tiny = require('./dist.js')
var server

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended:true}))

app.post('/', (req, res)=> {
  res.json(Object.assign(req.body, {gotPost:true, ok:true}))
})

app.post('/void', (req, res)=> {
  res.json('')
})

app.put('/', (req, res)=> {
  res.json(Object.assign(req.body, {gotPut:true, ok:true}))
})

app.patch('/', (req, res)=> {
  res.json(Object.assign(req.body, {gotPatch:true, ok:true}))
})

app.delete('/', (req, res)=> {
  res.json(Object.assign(req.body, {gotDel:true, ok:true}))
})

app.post('/goaway', (req, res) => {
  res.setHeader('location', '/')
  res.statusCode = 302
  res.send()
})

app.post('/boom', (req, res)=> {
  res.setHeader('test-header', 'foo')
  res.statusCode = 400
  res.json({calls:3})
})

test('startup', t=> {
  t.plan(1)
  server = app.listen(3000, x=> {
    t.ok(true, 'started server')
  })
})

test('can post', t=> {
  t.plan(2)
  var url = 'http://localhost:3000/'
  var data = {a:1, b:new Date(Date.now()).toISOString()}
  tiny.post({url, data}, function __posted(err, result) {
    if (err) {
      t.fail(err)
    }
    else {
      t.ok(result, 'got a result')
      t.ok(result.body.gotPost, 'got a post')
      console.log(result)
    }
  })
})

test('can post and handle "no content"', t=> {
  t.plan(2)
  var url = 'http://localhost:3000/void'
  var data = {a:1, b:new Date(Date.now()).toISOString()}
  tiny.post({url, data}, function __posted(err, result) {
    if (err) {
      t.fail(err)
    }
    else {
      t.ok(result, 'got a result (empty tho)')
      t.is(result.body, '')
      console.log(result)
    }
  })
})

test('can put', t=> {
  t.plan(2)
  var url = 'http://localhost:3000/'
  var data = {a:1, b:new Date(Date.now()).toISOString()}
  tiny.put({url, data}, function __posted(err, result) {
    if (err) {
      t.fail(err)
    }
    else {
      t.ok(result, 'got a result')
      t.ok(result.body.gotPut, 'got a put')
      console.log(result)
    }
  })
})

test('can patch', t=> {
  t.plan(2)
  var url = 'http://localhost:3000/'
  var data = {a:1, b:new Date(Date.now()).toISOString()}
  tiny.patch({url, data}, function __posted(err, result) {
    if (err) {
      t.fail(err)
    }
    else {
      t.ok(result, 'got a result')
      t.ok(result.body.gotPatch, 'got a patch')
      console.log(result)
    }
  })
})

test('can del', t=> {
  t.plan(3)
  var url = 'http://localhost:3000/'
  var data = {a:1, b:new Date(Date.now()).toISOString()}
  tiny.del({url, data}, function __posted(err, result) {
    if (err) {
      t.fail(err)
    }
    else {
      t.ok(result, 'got a result')
      t.ok(result.body.gotDel, 'got a del')
      t.ok(result.body.a, 'passed params via query I guess')
      console.log(result)
    }
  })
})

test('can delete (aliased to del)', t=> {
  t.plan(3)
  var url = 'http://localhost:3000/'
  var data = {a:1, b:new Date(Date.now()).toISOString()}
  tiny.delete({url, data}, function __posted(err, result) {
    if (err) {
      t.fail(err)
    }
    else {
      t.ok(result, 'got a result')
      t.ok(result.body.gotDel, 'got a del')
      t.ok(result.body.a, 'passed params via query I guess')
      console.log(result)
    }
  })
})

test('can access response on errors', t=> {
  t.plan(5)
  var url = 'http://localhost:3000/boom'
  var data = {};
  tiny.post({url, data}, function __posted(err, result) {
    t.ok(err, 'got an error')
    t.ok(err.raw, 'has raw response')
    t.equal(err.raw.statusCode, 400)
    t.equal(err.raw.headers['test-header'], 'foo')
    t.deepEqual(err.body, {calls: 3})
  })
})

test('can handle redirects', t=> {
  t.plan(2)
  var url = 'http://localhost:3000/goaway'
  var data = {}
  tiny.post({url, data}, function __posted(err, result) {
    if (err) {
      t.fail(err)
      t.end()
    } else {
      t.ok(result, 'got a result')
      t.ok(result.headers.location, 'got a location header')
      console.log(result)
    }
  })
})

test('shutdown', t=> {
  t.plan(1)
  server.close()
  t.ok(true, 'closed server')
})


================================================
FILE: test-promise.js
================================================
var test = require('tape')
var tiny = require('./dist.js')

test('env', t=> {
  t.plan(7)
  t.ok(tiny, 'got a tiny')
  t.ok(tiny.get, 'got a tiny.get')
  t.ok(tiny.post, 'got a tiny.post')
  t.ok(tiny.put, 'got a tiny.put')
  t.ok(tiny.patch, 'got a tiny.patch')
  t.ok(tiny.del, 'got a tiny.delete')
  t.ok(tiny.delete, 'got a tiny.delete')
  console.log(tiny)
})

test('can get a url', async t=> {
  t.plan(3)
  var url = 'https://brian.io'
  try {
    var result = await tiny.get({url})
    t.ok(result, 'got a result')
    t.ok(result.headers, 'got headers')
    t.ok(result.body, 'got body')
    console.log(result)
  }
  catch(e) {
    t.fail(err.statusCode, 'failed to get')
    console.log(err)
  }
})

test('get fails gracefully', t=> {
  t.plan(1)
  var url = 'http://nop333.ca'
  tiny.get({url}, function __ruhroh(err, result) {
    if (err) {
      t.ok(err, 'got err as expected')
      console.log(err)
    }
    else {
      t.fail(result, 'should not succeed')
    }
  })
})

test('bad url gives a acually useful error with a fucking line number holy shit', async t=> {
  t.plan(1)
  try {
    var res = await tiny.get('')
    t.fail(res)
    console.log(res)
  }
  catch(e) {
    t.ok(e, 'res')
    console.log(e)
  }
})


================================================
FILE: test-qq-multipart.js
================================================
let test = require('tape')
let fs = require('fs')
let path = require('path')
let tiny = require('./dist.js')
let http = require('http')
let port = 3000
let host = 'localhost'
let server

test('make a multipart post', t=> {
  t.plan(1)
  t.ok(tiny, 'got env')
})

test('start a fake server', t=> {
  t.plan(1)
  // somebody thought this was intuitive
  server = http.createServer((req, res)=> {
    let body = []
    req.on('data', chunk => body.push(chunk))
    req.on('end', function _end() {
      body = Buffer.concat(body).toString()
      res.end(body)
    })
  })
  server.listen({port, host}, err=> {
    if (err) t.fail(err)
    else t.pass(`Started server`)
  })
})

test('can multipart/form-data post', t=> {
  t.plan(1)
  let file = fs.readFileSync(path.join(__dirname, 'readme.md'))
  tiny.post({
    url: `http://${host}:${port}`,
    headers: {
      'content-type': 'multipart/form-data'
    },
    data: {
      one: 1,
      file
    }
  },
  function _post(err, data) {
    if (err) {
      t.fail(err, err)
      console.log(err)
    }
    else {
      t.ok(data.body.includes(file.toString()), 'posted')
      console.log(data)
    }
  })
})

test('close fake server', t=> {
  t.plan(1)
  server.close()
  t.ok(true, 'server closed')
})
Download .txt
gitextract_t8ymbo8n/

├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── .npmignore
├── .npmrc
├── _read.js
├── _write.js
├── index.js
├── package.json
├── readme.md
├── test-form-urlencoded.js
├── test-get.js
├── test-post.js
├── test-promise.js
└── test-qq-multipart.js
Download .txt
SYMBOL INDEX (1 symbols across 1 files)

FILE: _write.js
  function is (line 56) | function is(headers, type) {
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (24K chars).
[
  {
    "path": ".github/workflows/build.yml",
    "chars": 1768,
    "preview": "name: Node CI\n\n# Push tests commits; pull_request tests PR merges\non: [ push, pull_request ]\n\ndefaults:\n  run:\n    shell"
  },
  {
    "path": ".gitignore",
    "chars": 50,
    "preview": "bundle.js\ndist.js\nnode_modules/\npackage-lock.json\n"
  },
  {
    "path": ".npmignore",
    "chars": 54,
    "preview": ".*\ntest-*.js\nindex.js\n_read.js\n_write.js\nnode_modules\n"
  },
  {
    "path": ".npmrc",
    "chars": 19,
    "preview": "package-lock=false\n"
  },
  {
    "path": "_read.js",
    "chars": 2668,
    "preview": "var http = require('http')\nvar https = require('https')\nvar url = require('url')\nvar qs = require('querystring')\n\nmodule"
  },
  {
    "path": "_write.js",
    "chars": 4519,
    "preview": "var qs = require('querystring')\nvar http = require('http')\nvar https = require('https')\nvar FormData = require('@brianle"
  },
  {
    "path": "index.js",
    "chars": 356,
    "preview": "var _read = require('./_read')\nvar _write = require('./_write')\n\nmodule.exports = {\n  get: _read.bind({}, 'GET'),\n  head"
  },
  {
    "path": "package.json",
    "chars": 626,
    "preview": "{\n  \"name\": \"tiny-json-http\",\n  \"version\": \"7.5.1\",\n  \"main\": \"dist.js\",\n  \"scripts\": {\n    \"test\": \"npm run build && ta"
  },
  {
    "path": "readme.md",
    "chars": 1895,
    "preview": "# tiny-json-http\n\nMinimalist `HTTP` client for `GET`, `POST`, `PUT`, `PATCH` and `DELETE` `JSON` payloads\n\n- Zero depend"
  },
  {
    "path": "test-form-urlencoded.js",
    "chars": 1154,
    "preview": "var test = require('tape')\nvar tiny = require('./dist.js')\nvar http = require('http')\nvar server\nlet body = ''\n\ntest('st"
  },
  {
    "path": "test-get.js",
    "chars": 3102,
    "preview": "var test = require('tape')\nvar express = require('express')\nvar bodyParser = require('body-parser')\nvar app = express()\n"
  },
  {
    "path": "test-post.js",
    "chars": 4142,
    "preview": "var test = require('tape')\nvar express = require('express')\nvar bodyParser = require('body-parser')\nvar app = express()\n"
  },
  {
    "path": "test-promise.js",
    "chars": 1238,
    "preview": "var test = require('tape')\nvar tiny = require('./dist.js')\n\ntest('env', t=> {\n  t.plan(7)\n  t.ok(tiny, 'got a tiny')\n  t"
  },
  {
    "path": "test-qq-multipart.js",
    "chars": 1257,
    "preview": "let test = require('tape')\nlet fs = require('fs')\nlet path = require('path')\nlet tiny = require('./dist.js')\nlet http = "
  }
]

About this extraction

This page contains the full source code of the brianleroux/tiny-json-http GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 14 files (22.3 KB), approximately 6.6k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!