Compare commits

...

118 Commits

Author SHA1 Message Date
d3d0649b73 2.0.8 2022-08-01 17:10:22 +02:00
fba43df3c4 fix(core): update 2022-08-01 17:10:22 +02:00
c6fa540543 2.0.7 2022-08-01 17:10:11 +02:00
1891b54389 fix(core): update 2022-08-01 17:10:11 +02:00
fee8443af1 2.0.6 2022-07-30 18:43:11 +02:00
c48f956ae3 fix(core): update 2022-07-30 18:43:10 +02:00
4a4b64a2c4 2.0.5 2022-07-30 02:01:20 +02:00
43d4b47782 fix(core): update 2022-07-30 02:01:20 +02:00
6d970cb925 2.0.4 2022-07-30 01:52:04 +02:00
43710c930e fix(core): update 2022-07-30 01:52:04 +02:00
306dd7c366 2.0.3 2022-07-29 15:45:04 +02:00
3d69d97891 fix(core): update 2022-07-29 15:45:04 +02:00
a6d52702fd 2.0.2 2022-07-29 15:43:56 +02:00
de31ee6093 fix(core): update 2022-07-29 15:43:55 +02:00
cd2d7b2525 2.0.1 2022-07-29 15:41:33 +02:00
2d4a75c9cd fix(core): update 2022-07-29 15:41:32 +02:00
557fec0386 2.0.0 2022-07-29 01:20:25 +02:00
e803f9e48d BREAKING CHANGE(core): switch to esm 2022-07-29 01:20:24 +02:00
76c714a931 1.1.57 2022-07-29 01:19:50 +02:00
e8669f0420 fix(core): update 2022-07-29 01:19:50 +02:00
d9e6214a7e 1.1.56 2022-02-15 23:09:15 +01:00
7c4227bfc6 fix(core): update 2022-02-15 23:09:15 +01:00
e55a521395 1.1.55 2022-02-15 19:02:44 +01:00
06fc279caf fix(core): update 2022-02-15 19:02:43 +01:00
e89e317bbc 1.1.54 2022-02-15 18:57:42 +01:00
d182832e47 fix(core): update 2022-02-15 18:57:42 +01:00
92059a50de 1.1.53 2022-02-15 18:53:02 +01:00
db80f2df7e fix(core): update 2022-02-15 18:53:02 +01:00
145505b891 1.1.52 2021-05-16 23:39:26 +00:00
f4f50c6a94 fix(core): update 2021-05-16 23:39:25 +00:00
d204059313 1.1.51 2020-09-29 15:22:25 +00:00
00210566d5 fix(core): update 2020-09-29 15:22:25 +00:00
14245b2521 1.1.50 2020-09-29 15:20:41 +00:00
f0fa91e2db fix(core): update 2020-09-29 15:20:40 +00:00
19a1fe1524 1.1.49 2020-08-24 12:04:11 +00:00
27770a8ad1 fix(core): update 2020-08-24 12:04:10 +00:00
ab48f11e83 1.1.48 2020-08-24 12:01:39 +00:00
a0a9e3f824 fix(core): update 2020-08-24 12:01:38 +00:00
c829b06169 1.1.47 2020-01-13 08:00:40 +00:00
80fa40baf4 fix(core): update 2020-01-13 08:00:39 +00:00
3659b80e1e 1.1.46 2020-01-13 07:58:54 +00:00
770e7d46ea fix(core): update 2020-01-13 07:58:54 +00:00
2a46f2a306 1.1.45 2020-01-12 19:36:58 +00:00
eae4d09664 fix(core): update 2020-01-12 19:36:58 +00:00
23a2f597fc 1.1.44 2020-01-12 19:32:20 +00:00
c278249c32 fix(core): update 2020-01-12 19:32:20 +00:00
a32c372374 1.1.43 2019-11-21 17:32:31 +00:00
f98972d9fe fix(core): update 2019-11-21 17:32:30 +00:00
acebe6a381 1.1.42 2019-10-28 16:18:15 +01:00
7031504852 1.1.41 2019-10-27 14:41:49 +01:00
3010a1da9a fix(core): update 2019-10-27 14:41:48 +01:00
cdead33be4 1.1.40 2019-10-27 14:39:07 +01:00
5e23649702 fix(core): update 2019-10-27 14:39:06 +01:00
cc6bd5726a 1.1.39 2019-10-27 14:38:13 +01:00
f487584e80 fix(core): update 2019-10-27 14:38:12 +01:00
443bccd4c9 1.1.38 2019-10-27 14:36:18 +01:00
f359856b1d fix(core): update 2019-10-27 14:36:17 +01:00
bda04f124b 1.1.37 2019-10-27 14:32:27 +01:00
466187fd52 fix(core): update 2019-10-27 14:32:27 +01:00
d22504317e 1.1.36 2019-09-29 16:42:56 +02:00
6e31d84798 fix(core): update 2019-09-29 16:42:56 +02:00
36472b7306 1.1.35 2019-09-29 00:56:56 +02:00
e86f14b8d8 fix(core): update 2019-09-29 00:56:56 +02:00
2b9e7f6dd2 1.1.34 2019-09-29 00:43:37 +02:00
5e4afccf9c fix(core): update 2019-09-29 00:43:37 +02:00
3de7a1a210 1.1.33 2019-09-29 00:42:51 +02:00
bd2a5eedff fix(core): update 2019-09-29 00:42:51 +02:00
aa18357d75 1.1.32 2019-09-28 22:50:35 +02:00
9960aff219 fix(core): update 2019-09-28 22:50:35 +02:00
03d884ed59 1.1.31 2019-09-28 22:27:10 +02:00
9a0ac6fc62 fix(core): update 2019-09-28 22:27:09 +02:00
ad35ea4eb8 1.1.30 2019-09-28 21:40:05 +02:00
ffb0195f04 fix(core): update 2019-09-28 21:40:04 +02:00
78737c24df 1.1.29 2019-09-28 21:34:30 +02:00
6e276eda00 1.1.28 2019-09-28 21:33:14 +02:00
021d26a23a fix(core): update 2019-09-28 21:33:13 +02:00
c9c8a1234c 1.1.27 2019-09-08 18:00:49 +02:00
dffabd905f fix(core): update 2019-09-08 18:00:48 +02:00
36f2707141 1.1.26 2019-09-08 17:57:28 +02:00
b00d674b6f fix(core): update 2019-09-08 17:57:28 +02:00
b09598d465 1.1.25 2019-09-08 17:49:33 +02:00
acc7b2d46f fix(core): update 2019-09-08 17:49:32 +02:00
16a97a420c 1.1.24 2019-09-08 17:47:31 +02:00
a73c78e54b fix(core): update 2019-09-08 17:47:30 +02:00
1f408b5123 1.1.23 2019-08-22 12:40:19 +02:00
284f4967f4 fix(core): update 2019-08-22 12:40:19 +02:00
55c80c1403 1.1.22 2019-08-22 12:38:55 +02:00
7a3e565dbb fix(core): update 2019-08-22 12:38:55 +02:00
6f5d10ccd3 1.1.21 2019-08-22 12:38:12 +02:00
f1ddab72f6 fix(core): update 2019-08-22 12:38:11 +02:00
376225888c 1.1.20 2019-08-21 12:55:20 +02:00
63e8660f6c fix(core): update 2019-08-21 12:55:19 +02:00
2358b1d48f 1.1.19 2019-08-16 22:00:01 +02:00
9db29bacc2 fix(core): update 2019-08-16 22:00:01 +02:00
5f27b6834c 1.1.18 2019-08-16 21:43:10 +02:00
6717ecf80c fix(core): update 2019-08-16 21:43:09 +02:00
7784f99878 1.1.17 2019-08-16 21:38:50 +02:00
54a0521f9e fix(core): update 2019-08-16 21:38:50 +02:00
ef25315d59 1.1.16 2019-06-12 15:16:28 +02:00
74b6bf230f fix(core): update 2019-06-12 15:16:27 +02:00
fe693e6383 1.1.15 2019-04-23 00:14:31 +02:00
6014e94ee0 fix(core): update 2019-04-23 00:14:30 +02:00
88927fa6f8 1.1.14 2018-08-14 01:47:55 +02:00
e8133247f7 fix(ci): remove ci dependencies 2018-08-14 01:47:54 +02:00
4e51ed315e 1.1.13 2018-08-14 01:46:13 +02:00
0ffc44b3ef fix(request): now allows sending of strings 2018-08-14 01:46:12 +02:00
a8291febec 1.1.12 2018-07-20 01:06:25 +02:00
c0704eb2d8 fix(core): update 2018-07-20 01:06:25 +02:00
9eeb9c16b6 1.1.11 2018-07-20 00:50:36 +02:00
52bf520eb9 fix(small fix): update 2018-07-20 00:50:36 +02:00
c9f6198114 1.1.10 2018-07-20 00:35:24 +02:00
0a17591eae fix(formData): refactor formData 2018-07-20 00:35:23 +02:00
3417f09cdb 1.1.9 2018-07-20 00:04:37 +02:00
20dc3c9230 fix(now including right headers): update 2018-07-20 00:04:37 +02:00
6f865a356f 1.1.8 2018-07-20 00:01:41 +02:00
71a6ffef96 fix(core): update 2018-07-20 00:01:41 +02:00
189916e62b 1.1.7 2018-07-19 23:32:44 +02:00
33e36b5d44 fix(formData): return response 2018-07-19 23:32:43 +02:00
20 changed files with 15070 additions and 779 deletions

20
.gitignore vendored
View File

@ -1,4 +1,20 @@
node_modules/ .nogit/
# artifacts
coverage/ coverage/
public/ public/
pages/ pages/
# installs
node_modules/
# caches
.yarn/
.cache/
.rpt2_cache
# builds
dist/
dist_*/
# custom

View File

@ -1,126 +1,122 @@
# gitzone standard # gitzone ci_default
image: hosttoday/ht-docker-node:npmci image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache: cache:
paths: paths:
- .npmci_cache/ - .npmci_cache/
key: "$CI_BUILD_STAGE" key: '$CI_BUILD_STAGE'
stages: stages:
- security - security
- test - test
- release - release
- metadata - metadata
before_script:
- npm install -g @shipzone/npmci
# ==================== # ====================
# security stage # security stage
# ==================== # ====================
mirror: auditProductionDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security stage: security
script: script:
- npmci git mirror - npmci npm prepare
- npmci command npm install --production --ignore-scripts
- npmci command npm config set registry https://registry.npmjs.org
- npmci command npm audit --audit-level=high --only=prod --production
tags: tags:
- docker - docker
- notpriv allow_failure: true
snyk: auditDevDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security stage: security
script: script:
- npmci command npm install -g snyk - npmci npm prepare
- npmci command npm install --ignore-scripts - npmci command npm install --ignore-scripts
- npmci command snyk test - npmci command npm config set registry https://registry.npmjs.org
- npmci command npm audit --audit-level=high --only=dev
tags: tags:
- docker - docker
- notpriv allow_failure: true
# ==================== # ====================
# test stage # test stage
# ==================== # ====================
testLEGACY:
stage: test
script:
- npmci node install legacy
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
allow_failure: true
testLTS: testStable:
stage: test stage: test
script: script:
- npmci node install lts - npmci npm prepare
- npmci npm install - npmci node install stable
- npmci npm test - npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- notpriv
testBuild:
testSTABLE:
stage: test stage: test
script: script:
- npmci node install stable - npmci npm prepare
- npmci npm install - npmci node install stable
- npmci npm test - npmci npm install
- npmci command npm run build
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- notpriv
release: release:
stage: release stage: release
script: script:
- npmci node install stable - npmci node install stable
- npmci npm publish - npmci npm publish
only: only:
- tags - tags
tags: tags:
- docker - lossless
- notpriv - docker
- notpriv
# ==================== # ====================
# metadata stage # metadata stage
# ==================== # ====================
codequality: codequality:
stage: metadata stage: metadata
image: docker:stable
allow_failure: true allow_failure: true
services: only:
- docker:stable-dind - tags
script: script:
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') - npmci command npm install -g typescript
- docker run - npmci npm prepare
--env SOURCE_CODE="$PWD" - npmci npm install
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
paths: [codeclimate.json]
tags: tags:
- docker - lossless
- priv - docker
- priv
trigger: trigger:
stage: metadata stage: metadata
script: script:
- npmci trigger - npmci trigger
only: only:
- tags - tags
tags: tags:
- docker - lossless
- notpriv - docker
- notpriv
pages: pages:
image: hosttoday/ht-docker-node:npmci
stage: metadata stage: metadata
script: script:
- npmci command npm install -g typedoc typescript - npmci node install stable
- npmci npm prepare
- npmci npm install - npmci npm install
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/ - npmci command npm run buildDocs
tags: tags:
- lossless
- docker - docker
- notpriv - notpriv
only: only:
@ -128,15 +124,5 @@ pages:
artifacts: artifacts:
expire_in: 1 week expire_in: 1 week
paths: paths:
- public - public
allow_failure: true
windowsCompatibility:
image: stefanscherer/node-windows:10-build-tools
stage: metadata
script:
- npm install & npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- windows
allow_failure: true allow_failure: true

11
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "npm test",
"name": "Run npm test",
"request": "launch",
"type": "node-terminal"
}
]
}

26
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"json.schemas": [
{
"fileMatch": ["/npmextra.json"],
"schema": {
"type": "object",
"properties": {
"npmci": {
"type": "object",
"description": "settings for npmci"
},
"gitzone": {
"type": "object",
"description": "settings for gitzone",
"properties": {
"projectType": {
"type": "string",
"enum": ["website", "element", "service", "npm", "wcc"]
}
}
}
}
}
}
]
}

View File

@ -1,69 +0,0 @@
# smartrequest
dropin replacement for request
## Availabililty
[![npm](https://push.rocks/assets/repo-button-npm.svg)](https://www.npmjs.com/package/smartrequest)
[![git](https://push.rocks/assets/repo-button-git.svg)](https://GitLab.com/pushrocks/smartrequest)
[![git](https://push.rocks/assets/repo-button-mirror.svg)](https://github.com/pushrocks/smartrequest)
[![docs](https://push.rocks/assets/repo-button-docs.svg)](https://pushrocks.gitlab.io/smartrequest/)
## Status for master
[![build status](https://GitLab.com/pushrocks/smartrequest/badges/master/build.svg)](https://GitLab.com/pushrocks/smartrequest/commits/master)
[![coverage report](https://GitLab.com/pushrocks/smartrequest/badges/master/coverage.svg)](https://GitLab.com/pushrocks/smartrequest/commits/master)
[![npm downloads per month](https://img.shields.io/npm/dm/smartrequest.svg)](https://www.npmjs.com/package/smartrequest)
[![Dependency Status](https://david-dm.org/pushrocks/smartrequest.svg)](https://david-dm.org/pushrocks/smartrequest)
[![bitHound Dependencies](https://www.bithound.io/github/pushrocks/smartrequest/badges/dependencies.svg)](https://www.bithound.io/github/pushrocks/smartrequest/master/dependencies/npm)
[![bitHound Code](https://www.bithound.io/github/pushrocks/smartrequest/badges/code.svg)](https://www.bithound.io/github/pushrocks/smartrequest)
[![TypeScript](https://img.shields.io/badge/TypeScript-2.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/)
[![node](https://img.shields.io/badge/node->=%206.x.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
## Usage
Use TypeScript for best in class instellisense.
> note: smartrequest uses the **native** node request module under the hood (not the one from npm)
```javascript
import * as smartrequest from 'smartrequest'
// simple post
let options: smartrequest.ISmartRequestOptions = { // typed options
headers: {
"Content-Type": "application/json"
"Authorization": "Bearer token"
},
requestBody: {
key1: 'value1',
key2: 3
}
}
smartrequest.post('https://example.com', options).then(res => {
console.log(res.status)
console.log(res.body) // if json, body will be parsed automatically
}).catch(err => {
console.log(err)
})
// also available
smartrequest.get(...)
smartrequest.put(...)
smartrequest.del(...)
// streaming
smartrequest.get('https://example.com/bigfile.mp4', optionsArg, true).then(res => { // third arg = true signals streaming
console.log(res.status)
res.on('data', data => {
// do something with the data chunk here
}
res.on('end', () => {
// do something when things have ended
})
})
```
[![npm](https://push.rocks/assets/repo-header.svg)](https://push.rocks)

View File

@ -3,9 +3,18 @@
"coverageTreshold": 50 "coverageTreshold": 50
}, },
"npmci": { "npmci": {
"npmGlobalTools": [ "npmGlobalTools": [],
"npmts"
],
"npmAccessLevel": "public" "npmAccessLevel": "public"
},
"gitzone": {
"projectType": "npm",
"module": {
"githost": "gitlab.com",
"gitscope": "pushrocks",
"gitrepo": "smartrequest",
"description": "dropin replacement for request",
"npmPackagename": "@pushrocks/smartrequest",
"license": "MIT"
}
} }
} }

15023
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,15 @@
{ {
"name": "@pushrocks/smartrequest", "name": "@pushrocks/smartrequest",
"version": "1.1.6", "version": "2.0.8",
"private": false, "private": false,
"description": "dropin replacement for request", "description": "dropin replacement for request",
"main": "dist/index.js", "main": "dist_ts/index.js",
"typings": "dist/index.d.ts", "typings": "dist_ts/index.d.ts",
"type": "module",
"scripts": { "scripts": {
"test": "tsrun test/test.ts", "test": "(tstest test/ --web)",
"build": "(npmts)" "build": "(tsbuild --web)",
"buildDocs": "tsdoc"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -23,13 +25,31 @@
}, },
"homepage": "https://gitlab.com/pushrocks/smartrequest#README", "homepage": "https://gitlab.com/pushrocks/smartrequest#README",
"dependencies": { "dependencies": {
"@pushrocks/smartpromise": "^2.0.5", "@pushrocks/smartpromise": "^3.1.7",
"@types/form-data": "^2.2.1", "@pushrocks/smarturl": "^3.0.2",
"form-data": "^2.3.2" "agentkeepalive": "^4.2.1",
"form-data": "^4.0.0"
}, },
"devDependencies": { "devDependencies": {
"@gitzone/tsrun": "^1.1.9", "@gitzone/tsbuild": "^2.1.63",
"@pushrocks/tapbundle": "^3.0.1", "@gitzone/tsrun": "^1.2.37",
"@types/node": "^10.5.2" "@gitzone/tstest": "^1.0.72",
} "@pushrocks/tapbundle": "^5.0.4",
"@types/node": "^18.6.2"
},
"files": [
"ts/**/*",
"ts_web/**/*",
"dist/**/*",
"dist_*/**/*",
"dist_ts/**/*",
"dist_ts_web/**/*",
"assets/**/*",
"cli.js",
"npmextra.json",
"readme.md"
],
"browserslist": [
"last 1 chrome versions"
]
} }

96
readme.md Normal file
View File

@ -0,0 +1,96 @@
# @pushrocks/smartrequest
dropin replacement for request
## Availabililty and Links
* [npmjs.org (npm package)](https://www.npmjs.com/package/@pushrocks/smartrequest)
* [gitlab.com (source)](https://gitlab.com/pushrocks/smartrequest)
* [github.com (source mirror)](https://github.com/pushrocks/smartrequest)
* [docs (typedoc)](https://pushrocks.gitlab.io/smartrequest/)
## Status for master
Status Category | Status Badge
-- | --
GitLab Pipelines | [![pipeline status](https://gitlab.com/pushrocks/smartrequest/badges/master/pipeline.svg)](https://lossless.cloud)
GitLab Pipline Test Coverage | [![coverage report](https://gitlab.com/pushrocks/smartrequest/badges/master/coverage.svg)](https://lossless.cloud)
npm | [![npm downloads per month](https://badgen.net/npm/dy/@pushrocks/smartrequest)](https://lossless.cloud)
Snyk | [![Known Vulnerabilities](https://badgen.net/snyk/pushrocks/smartrequest)](https://lossless.cloud)
TypeScript Support | [![TypeScript](https://badgen.net/badge/TypeScript/>=%203.x/blue?icon=typescript)](https://lossless.cloud)
node Support | [![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
Code Style | [![Code Style](https://badgen.net/badge/style/prettier/purple)](https://lossless.cloud)
PackagePhobia (total standalone install weight) | [![PackagePhobia](https://badgen.net/packagephobia/install/@pushrocks/smartrequest)](https://lossless.cloud)
PackagePhobia (package size on registry) | [![PackagePhobia](https://badgen.net/packagephobia/publish/@pushrocks/smartrequest)](https://lossless.cloud)
BundlePhobia (total size when bundled) | [![BundlePhobia](https://badgen.net/bundlephobia/minzip/@pushrocks/smartrequest)](https://lossless.cloud)
Platform support | [![Supports Windows 10](https://badgen.net/badge/supports%20Windows%2010/yes/green?icon=windows)](https://lossless.cloud) [![Supports Mac OS X](https://badgen.net/badge/supports%20Mac%20OS%20X/yes/green?icon=apple)](https://lossless.cloud)
## Usage
Use TypeScript for best in class instellisense.
### Features
- supports http
- supports https
- supports unix socks
- supports formData
- supports file uploads
- supports best practice keepAlive
- dedicated functions for working with JSON request/response cycles
- written in TypeScript
- continuously updated
- uses node native http and https modules
- used in modules like @pushrocks/smartproxy and @apiglobal/typedrequest
- commercial support available at [https://lossless.support](https://lossless.support)
> note: smartrequest uses the **native** node http/https modules under the hood (not the bloated one from npm)
```javascript
import * as smartrequest from 'smartrequest'
// simple post
const options: smartrequest.ISmartRequestOptions = { // typed options
headers: {
"Content-Type": "application/json"
"Authorization": "Bearer token"
},
requestBody: JSON.stringify({
key1: 'value1',
key2: 3
})
}
smartrequest.request('https://example.com', options).then(res => {
console.log(res.status)
console.log(res.body) // if json, body will be parsed automatically
}).catch(err => {
console.log(err)
})
// dedicated JSON methods are available:
smartrequest.getJson(...)
smartrequest.postJson(...)
smartrequest.putJson(...)
smartrequest.delJson(...)
// streaming
smartrequest.get('https://example.com/bigfile.mp4', optionsArg, true).then(res => { // third arg = true signals streaming
console.log(res.status)
res.on('data', data => {
// do something with the data chunk here
}
res.on('end', () => {
// do something when things have ended
})
})
```
## Contribution
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
For further information read the linked docs at the top of this readme.
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
[![repo-footer](https://lossless.gitlab.io/publicrelations/repofooter.svg)](https://maintainedby.lossless.com)

View File

@ -1,39 +1,38 @@
import { tap, expect } from '@pushrocks/tapbundle'; import { tap, expect, expectAsync } from '@pushrocks/tapbundle';
import * as smartrequest from '../ts/index'; import * as smartrequest from '../ts/index.js';
tap.test('should request a html document over https', async () => { tap.test('should request a html document over https', async () => {
await expect(smartrequest.getJson('https://encrypted.google.com/')) await expectAsync(smartrequest.getJson('https://encrypted.google.com/')).toHaveProperty('body');
.to.eventually.property('body')
.be.a('string');
}); });
tap.test('should request a JSON document over https', async () => { tap.test('should request a JSON document over https', async () => {
await expect(smartrequest.getJson('https://jsonplaceholder.typicode.com/posts/1')) await expectAsync(smartrequest.getJson('https://jsonplaceholder.typicode.com/posts/1'))
.to.eventually.property('body') .property('body')
.property('id') .property('id')
.equal(1); .toEqual(1);
}); });
tap.test('should post a JSON document over http', async () => { tap.skip.test('should post a JSON document over http', async () => {
await expect(smartrequest.postJson('http://md5.jsontest.com/?text=example_text')) await expectAsync(smartrequest.postJson('http://md5.jsontest.com/?text=example_text'))
.to.eventually.property('body') .property('body')
.property('md5') .property('md5')
.equal('fa4c6baa0812e5b5c80ed8885e55a8a6'); .toEqual('fa4c6baa0812e5b5c80ed8885e55a8a6');
}); });
tap.skip.test('should deal with unix socks', async () => { tap.skip.test('should deal with unix socks', async () => {
const socketResponse = await smartrequest.request('http://unix:/var/run/docker.sock:/containers/json', { const socketResponse = await smartrequest.request(
headers: { 'http://unix:/var/run/docker.sock:/containers/json',
"Content-Type": "application/json", {
"Host": "docker.sock" headers: {
'Content-Type': 'application/json',
Host: 'docker.sock',
},
} }
}); );
console.log(socketResponse.body); console.log(socketResponse.body);
}); });
tap.skip.test('should correctly upload a file using formData', async () => { tap.skip.test('should correctly upload a file using formData', async () => {});
})
tap.start(); tap.start();

8
ts/00_commitinfo_data.ts Normal file
View File

@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @pushrocks/commitinfo
*/
export const commitinfo = {
name: '@pushrocks/smartrequest',
version: '2.0.8',
description: 'dropin replacement for request'
}

View File

@ -1,6 +1,7 @@
export { request, IExtendedIncomingMessage } from './smartrequest.request'; export { request } from './smartrequest.request.js';
export { ISmartRequestOptions } from './smartrequest.interfaces'; export type { IExtendedIncomingMessage } from './smartrequest.request.js';
export type { ISmartRequestOptions } from './smartrequest.interfaces.js';
export * from './smartrequest.jsonrest'; export * from './smartrequest.jsonrest.js';
export * from './smartrequest.binaryrest'; export * from './smartrequest.binaryrest.js';
export * from './smartrequest.formdata'; export * from './smartrequest.formdata.js';

View File

@ -1,27 +1,31 @@
// this file implements methods to get and post binary data. // this file implements methods to get and post binary data.
import * as interfaces from './smartrequest.interfaces'; import * as interfaces from './smartrequest.interfaces.js';
import { request } from './smartrequest.request'; import { request } from './smartrequest.request.js';
import * as plugins from './smartrequest.plugins'; import * as plugins from './smartrequest.plugins.js';
export const getBinary = async ( export const getBinary = async (
domainArg: string, domainArg: string,
optionsArg: interfaces.ISmartRequestOptions = {} optionsArg: interfaces.ISmartRequestOptions = {}
) => { ) => {
optionsArg = {
...optionsArg,
autoJsonParse: false,
};
const done = plugins.smartpromise.defer(); const done = plugins.smartpromise.defer();
const response = await request(domainArg, optionsArg, true); const response = await request(domainArg, optionsArg, true);
const data = []; const data: Array<Buffer> = [];
response response
.on('data', function(chunk) { .on('data', function (chunk: Buffer) {
data.push(chunk); data.push(chunk);
}) })
.on('end', function() { .on('end', function () {
//at this point data is an array of Buffers //at this point data is an array of Buffers
//so Buffer.concat() can make us a new Buffer //so Buffer.concat() can make us a new Buffer
//of all of them together //of all of them together
const buffer = Buffer.concat(data); const buffer = Buffer.concat(data);
response.body = buffer.toString('binary'); response.body = buffer;
done.resolve(); done.resolve();
}); });
await done.promise; await done.promise;

View File

@ -1,45 +1,45 @@
import * as plugins from "./smartrequest.plugins"; import * as plugins from './smartrequest.plugins.js';
import * as interfaces from "./smartrequest.interfaces"; import * as interfaces from './smartrequest.interfaces.js';
import { request } from "./smartrequest.request"; import { request } from './smartrequest.request.js';
/** /**
* the interfae for FormFieldData * the interfae for FormFieldData
*/ */
export interface IFormField { export interface IFormField {
name: string; name: string;
type: "string" | "filePath" | "Buffer"; type: 'string' | 'filePath' | 'Buffer';
payload: string; payload: string | Buffer;
fileName?: string;
contentType?: string;
} }
/** const appendFormField = async (formDataArg: plugins.formData, formDataField: IFormField) => {
* retrieve the FormData headers in reliable way switch (formDataField.type) {
* @param formDataArg case 'string':
*/ formDataArg.append(formDataField.name, formDataField.payload);
const getFormDataHeaders = (formDataArg: plugins.formData) => { break;
const done = plugins.smartpromise.defer(); case 'filePath':
formDataArg.getLength((err, length) => { if (typeof formDataField.payload !== 'string') {
if (err) { throw new Error(
done.reject(err); `Payload for key ${
} formDataField.name
const headers = Object.assign( } must be of type string. Got ${typeof formDataField.payload} instead.`
{ "Content-Length": length }, );
formDataArg.getHeaders() }
); const fileData = plugins.fs.readFileSync(
done.resolve(headers); plugins.path.join(process.cwd(), formDataField.payload)
}); );
return done.promise; formDataArg.append('file', fileData, {
}; filename: formDataField.fileName ? formDataField.fileName : 'upload.pdf',
contentType: 'application/pdf',
const appendFormField = async ( });
formDataArg: plugins.formData, break;
formDataField: IFormField case 'Buffer':
) => { formDataArg.append(formDataField.name, formDataField.payload, {
if (formDataField.type === "filePath") { filename: formDataField.fileName ? formDataField.fileName : 'upload.pdf',
formDataArg.append("type", "image"); contentType: formDataField.contentType ? formDataField.contentType : 'application/pdf',
let fileData = plugins.fs.createReadStream( });
plugins.path.join(process.cwd(), formDataField.payload) break;
);
formDataArg.append("media", fileData, "upload.pdf");
} }
}; };
@ -52,11 +52,48 @@ export const postFormData = async (
for (const formField of payloadArg) { for (const formField of payloadArg) {
await appendFormField(form, formField); await appendFormField(form, formField);
} }
const pipeLog: any = async (...args) => { const requestOptions = {
console.log(args); ...optionsArg,
method: 'POST',
headers: {
...optionsArg.headers,
...form.getHeaders(),
},
requestBody: form,
}; };
const requestOptions = Object.assign({}, optionsArg, { requestBody: form });
// lets fire the actual request for sending the formdata // lets fire the actual request for sending the formdata
request(urlArg, requestOptions); const response = await request(urlArg, requestOptions);
return response;
};
export const postFormDataUrlEncoded = async (
urlArg: string,
optionsArg: interfaces.ISmartRequestOptions = {},
payloadArg: { key: string; content: string }[]
) => {
let resultString = '';
for (const keyContentPair of payloadArg) {
if (resultString) {
resultString += '&';
}
resultString += `${encodeURIComponent(keyContentPair.key)}=${encodeURIComponent(
keyContentPair.content
)}`;
}
const requestOptions: interfaces.ISmartRequestOptions = {
...optionsArg,
method: 'POST',
headers: {
...optionsArg.headers,
'content-type': 'application/x-www-form-urlencoded',
},
requestBody: resultString,
};
// lets fire the actual request for sending the formdata
const response = await request(urlArg, requestOptions);
return response;
}; };

View File

@ -1,6 +1,9 @@
import * as plugins from './smartrequest.plugins'; import * as plugins from './smartrequest.plugins.js';
import * as https from 'https'; import * as https from 'https';
export interface ISmartRequestOptions extends https.RequestOptions { export interface ISmartRequestOptions extends https.RequestOptions {
keepAlive?: boolean;
requestBody?: any; requestBody?: any;
autoJsonParse?: boolean;
queryParams?: { [key: string]: string };
} }

View File

@ -1,7 +1,7 @@
// This file implements methods to get and post JSON in a simple manner. // This file implements methods to get and post JSON in a simple manner.
import * as interfaces from './smartrequest.interfaces'; import * as interfaces from './smartrequest.interfaces.js';
import { request } from './smartrequest.request'; import { request } from './smartrequest.request.js';
/** /**
* gets Json and puts the right headers + handles response aggregation * gets Json and puts the right headers + handles response aggregation
@ -14,7 +14,7 @@ export const getJson = async (
) => { ) => {
optionsArg.method = 'GET'; optionsArg.method = 'GET';
optionsArg.headers = { optionsArg.headers = {
...optionsArg.headers ...optionsArg.headers,
}; };
let response = await request(domainArg, optionsArg); let response = await request(domainArg, optionsArg);
return response; return response;
@ -37,7 +37,7 @@ export const postJson = async (
// assign the right Content-Type, leaving all other headers in place // assign the right Content-Type, leaving all other headers in place
optionsArg.headers = { optionsArg.headers = {
...optionsArg.headers, ...optionsArg.headers,
'Content-Type': 'application/json' 'Content-Type': 'application/json',
}; };
} }
let response = await request(domainArg, optionsArg); let response = await request(domainArg, optionsArg);

View File

@ -1,10 +1,19 @@
import * as formData from 'form-data'; // node native scope
import * as fs from 'fs'; import * as fs from 'fs';
import * as http from 'http'; import * as http from 'http';
import * as https from 'https'; import * as https from 'https';
import * as path from 'path'; import * as path from 'path';
import * as url from 'url';
export { http, https, fs, path };
// pushrocks scope
import * as smartpromise from '@pushrocks/smartpromise'; import * as smartpromise from '@pushrocks/smartpromise';
import * as smarturl from '@pushrocks/smarturl';
export {formData, http, https, fs, path, url, smartpromise }; export { smartpromise, smarturl };
// third party scope
import agentkeepalive from 'agentkeepalive';
import formData from 'form-data';
export { agentkeepalive, formData };

View File

@ -1,27 +1,31 @@
import * as https from "https"; import * as plugins from './smartrequest.plugins.js';
import * as plugins from "./smartrequest.plugins"; import * as interfaces from './smartrequest.interfaces.js';
import * as interfaces from "./smartrequest.interfaces";
import { IncomingMessage } from "http"; import { IncomingMessage } from 'http';
export interface IExtendedIncomingMessage extends IncomingMessage { export interface IExtendedIncomingMessage extends IncomingMessage {
body: any; body: any;
} }
const buildUtf8Response = ( const buildUtf8Response = (
incomingMessageArg: IncomingMessage incomingMessageArg: IncomingMessage,
autoJsonParse = true
): Promise<IExtendedIncomingMessage> => { ): Promise<IExtendedIncomingMessage> => {
let done = plugins.smartpromise.defer<IExtendedIncomingMessage>(); const done = plugins.smartpromise.defer<IExtendedIncomingMessage>();
// Continuously update stream with data // Continuously update stream with data
let body = ""; let body = '';
incomingMessageArg.on("data", function(chunkArg) { incomingMessageArg.on('data', (chunkArg) => {
body += chunkArg; body += chunkArg;
}); });
incomingMessageArg.on("end", function() { incomingMessageArg.on('end', () => {
try { if (autoJsonParse) {
(incomingMessageArg as IExtendedIncomingMessage).body = JSON.parse(body); try {
} catch (err) { (incomingMessageArg as IExtendedIncomingMessage).body = JSON.parse(body);
} catch (err) {
(incomingMessageArg as IExtendedIncomingMessage).body = body;
}
} else {
(incomingMessageArg as IExtendedIncomingMessage).body = body; (incomingMessageArg as IExtendedIncomingMessage).body = body;
} }
done.resolve(incomingMessageArg as IExtendedIncomingMessage); done.resolve(incomingMessageArg as IExtendedIncomingMessage);
@ -46,77 +50,144 @@ const parseSocketPathAndRoute = (stringToParseArg: string) => {
const result = parseRegex.exec(stringToParseArg); const result = parseRegex.exec(stringToParseArg);
return { return {
socketPath: result[1], socketPath: result[1],
path: result[2] path: result[2],
} };
} };
/**
* a custom http agent to make sure we can set custom keepAlive options for speedy subsequent calls
*/
const httpAgent = new plugins.agentkeepalive({
keepAlive: true,
maxFreeSockets: 10,
maxSockets: 100,
maxTotalSockets: 1000,
timeout: 60000,
});
/**
* a custom http agent to make sure we can set custom keepAlive options for speedy subsequent calls
*/
const httpAgentKeepAliveFalse = new plugins.agentkeepalive({
keepAlive: false,
timeout: 60000
});
/**
* a custom https agent to make sure we can set custom keepAlive options for speedy subsequent calls
*/
const httpsAgent = new plugins.agentkeepalive.HttpsAgent({
keepAlive: true,
maxFreeSockets: 10,
maxSockets: 100,
maxTotalSockets: 1000,
timeout: 60000
});
/**
* a custom https agent to make sure we can set custom keepAlive options for speedy subsequent calls
*/
const httpsAgentKeepAliveFalse = new plugins.agentkeepalive.HttpsAgent({
keepAlive: false,
timeout: 60000
});
export let request = async ( export let request = async (
domainArg: string, urlArg: string,
optionsArg: interfaces.ISmartRequestOptions = {}, optionsArg: interfaces.ISmartRequestOptions = {},
streamArg: boolean = false responseStreamArg: boolean = false,
requestDataFunc: (req: plugins.http.ClientRequest) => void = null
): Promise<IExtendedIncomingMessage> => { ): Promise<IExtendedIncomingMessage> => {
let done = plugins.smartpromise.defer<any>(); const done = plugins.smartpromise.defer<any>();
// merge options
const defaultOptions: interfaces.ISmartRequestOptions = {
// agent: agent,
autoJsonParse: true,
keepAlive: true,
};
optionsArg = {
...defaultOptions,
...optionsArg,
};
// parse url // parse url
let parsedUrl: plugins.url.Url; const parsedUrl = plugins.smarturl.Smarturl.createFromUrl(urlArg, {
parsedUrl = plugins.url.parse(domainArg); searchParams: optionsArg.queryParams || {},
});
optionsArg.hostname = parsedUrl.hostname; optionsArg.hostname = parsedUrl.hostname;
if (parsedUrl.port) { if (parsedUrl.port) {
optionsArg.port = parseInt(parsedUrl.port); optionsArg.port = parseInt(parsedUrl.port, 10);
} }
optionsArg.path = parsedUrl.path; optionsArg.path = parsedUrl.path;
optionsArg.queryParams = parsedUrl.searchParams;
// determine if unixsock // determine if unixsock
if(testForUnixSock(domainArg)) { if (testForUnixSock(urlArg)) {
const detailedUnixPath = parseSocketPathAndRoute(optionsArg.path) const detailedUnixPath = parseSocketPathAndRoute(optionsArg.path);
optionsArg.socketPath = detailedUnixPath.socketPath; optionsArg.socketPath = detailedUnixPath.socketPath;
optionsArg.path = detailedUnixPath.path; optionsArg.path = detailedUnixPath.path;
} }
// TODO: support tcp sockets
// lets determine the request module to use // lets determine the request module to use
const requestModule = (() => { const requestModule = (() => {
if (parsedUrl.protocol === "https:") { switch (true) {
return plugins.https; case parsedUrl.protocol === 'https' && optionsArg.keepAlive:
} else if (parsedUrl.protocol === "http:") { optionsArg.agent = httpsAgent;
return plugins.http; return plugins.https;
} else { case parsedUrl.protocol === 'https' && !optionsArg.keepAlive:
throw new Error(`unsupported protocol: ${parsedUrl.protocol}`); optionsArg.agent = httpsAgentKeepAliveFalse;
return plugins.https;
case parsedUrl.protocol === 'http' && optionsArg.keepAlive:
optionsArg.agent = httpAgent;
return plugins.http;
case parsedUrl.protocol === 'http' && !optionsArg.keepAlive:
optionsArg.agent = httpAgentKeepAliveFalse;
return plugins.http;
} }
})() as typeof plugins.https; })() as typeof plugins.https;
if (!requestModule) {
console.error(`The request to ${urlArg} is missing a viable protocol. Must be http or https`);
return;
}
// lets perform the actual request // lets perform the actual request
let request = requestModule.request(optionsArg); const requestToFire = requestModule.request(optionsArg, async (response) => {
if (responseStreamArg) {
done.resolve(response);
} else {
const builtResponse = await buildUtf8Response(response, optionsArg.autoJsonParse);
done.resolve(builtResponse);
}
});
// lets write the requestBody // lets write the requestBody
if (optionsArg.requestBody) { if (optionsArg.requestBody) {
if ( if (optionsArg.requestBody instanceof plugins.formData) {
typeof optionsArg.requestBody !== "string" optionsArg.requestBody.pipe(requestToFire).on('finish', (event: any) => {
&& !(optionsArg.requestBody instanceof plugins.formData) requestToFire.end();
) { });
optionsArg.requestBody = JSON.stringify(optionsArg.requestBody); } else {
request.write(optionsArg.requestBody); if (typeof optionsArg.requestBody !== 'string') {
request.end(); optionsArg.requestBody = JSON.stringify(optionsArg.requestBody);
} else if (optionsArg.requestBody instanceof plugins.formData) { }
optionsArg.requestBody.pipe(request); requestToFire.write(optionsArg.requestBody);
requestToFire.end();
} }
} else if (requestDataFunc) {
requestDataFunc(requestToFire);
} else { } else {
request.end(); requestToFire.end();
} }
// lets handle an error // lets handle an error
request.on("error", e => { requestToFire.on('error', (e) => {
console.error(e); console.error(e);
}); requestToFire.destroy();
// lets handle the response
request.on("response", async response => {
if (streamArg) {
done.resolve(response);
} else {
const builtResponse = await buildUtf8Response(response)
done.resolve(builtResponse);
}
}); });
const result = await done.promise; const result = await done.promise;

10
tsconfig.json Normal file
View File

@ -0,0 +1,10 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": false,
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "nodenext",
"esModuleInterop": true
}
}

View File

@ -1,3 +0,0 @@
{
"extends": "tslint-config-standard"
}