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')
})
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
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.