Skip to content

Commit

Permalink
feat(native fetch): Implement Node.js fetch (#1243)
Browse files Browse the repository at this point in the history
* generalize http request params from nodejs type

* complete fetch

* reduce complexity

* change flag to --use-node-fetch

* change flag to --native-fetch

* clean up doc
  • Loading branch information
syamsudotdev authored Mar 7, 2024
1 parent a069bae commit ca5c3ac
Show file tree
Hide file tree
Showing 11 changed files with 270 additions and 177 deletions.
6 changes: 3 additions & 3 deletions docs/src/pages/guides/cli-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,12 +283,12 @@ You can also set the maximum of delay by using the `--retryMaxDelayMs` flag. Def
monika --retryMaxDelayMs 30000
```

## Experimental Native Node Fetch
## Native Fetch from Node.js

Monika use Axios as HTTP client by default, use `--experimental-fetch` to switch to native fetch provided by Node.js runtime.
Monika use Axios as HTTP client by default, use `--native-fetch` to switch to native fetch provided by Node.js runtime.

```sh
monika --experimental-fetch
monika --native-fetch
```

## Follow Redirects
Expand Down
20 changes: 20 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
"sqlite3": "^5.0.2",
"ssl-checker": "2.0.7",
"stun": "^2.1.0",
"undici": "^6.6.2",
"unzipper": "^0.10.11",
"url-parse": "^1.5.10",
"uuid": "9.0.1",
Expand Down
4 changes: 2 additions & 2 deletions src/commands/monika.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ export default class Monika extends Command {
'Create config from HAR (-H), postman (-p), insomnia (-I), sitemap (--sitemap), textfile (--text) export file, or open Monika Configuration Generator using default browser',
}),

'experimental-fetch': Flags.boolean({
default: monikaFlagsDefaultValue['experimental-fetch'],
'native-fetch': Flags.boolean({
default: monikaFlagsDefaultValue['native-fetch'],
description:
'Use native fetch Node.js API instead of Axios for HTTP client',
}),
Expand Down
92 changes: 36 additions & 56 deletions src/components/config/__tests__/parse-postman.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,29 +81,24 @@ describe('parseConfigFromPostman', () => {
expect(req.body).to.deep.equals({ message: 'Hello, world!' })
}

if (mode === 'formdata') {
expect((req.headers || {})['Content-Type']).to.equals(
'multipart/form-data'
)
const headers = req.headers || {}
if (mode === 'formdata' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('multipart/form-data')
}

if (mode === 'urlencoded') {
expect((req.headers || {})['Content-Type']).to.equals(
if (mode === 'urlencoded' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals(
'application/x-www-form-urlencoded'
)
}

if (mode === 'raw') {
if (language === 'json') {
expect((req.headers || {})['Content-Type']).to.equals(
'application/json'
)
if (language === 'json' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('application/json')
}

if (language === 'text') {
expect((req.headers || {})['Content-Type']).to.equals(
'text/plain'
)
if (language === 'text' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('text/plain')
}
}
}
Expand Down Expand Up @@ -134,29 +129,24 @@ describe('parseConfigFromPostman', () => {
expect(req.body).to.deep.equals({ message: 'Hello, world!' })
}

if (mode === 'formdata') {
expect((req.headers || {})['Content-Type']).to.equals(
'multipart/form-data'
)
const headers = req.headers || {}
if (mode === 'formdata' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('multipart/form-data')
}

if (mode === 'urlencoded') {
expect((req.headers || {})['Content-Type']).to.equals(
if (mode === 'urlencoded' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals(
'application/x-www-form-urlencoded'
)
}

if (mode === 'raw') {
if (language === 'json') {
expect((req.headers || {})['Content-Type']).to.equals(
'application/json'
)
if (language === 'json' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('application/json')
}

if (language === 'text') {
expect((req.headers || {})['Content-Type']).to.equals(
'text/plain'
)
if (language === 'text' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('text/plain')
}
}
}
Expand Down Expand Up @@ -192,29 +182,24 @@ describe('parseConfigFromPostman', () => {
expect(req.body).to.deep.equals({ message: 'Hello, world!' })
}

if (mode === 'formdata') {
expect((req.headers || {})['Content-Type']).to.equals(
'multipart/form-data'
)
const headers = req.headers || {}
if (mode === 'formdata' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('multipart/form-data')
}

if (mode === 'urlencoded') {
expect((req.headers || {})['Content-Type']).to.equals(
if (mode === 'urlencoded' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals(
'application/x-www-form-urlencoded'
)
}

if (mode === 'raw') {
if (language === 'json') {
expect((req.headers || {})['Content-Type']).to.equals(
'application/json'
)
if (language === 'json' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('application/json')
}

if (language === 'text') {
expect((req.headers || {})['Content-Type']).to.equals(
'text/plain'
)
if (language === 'text' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('text/plain')
}
}
}
Expand Down Expand Up @@ -248,29 +233,24 @@ describe('parseConfigFromPostman', () => {
expect(req.body).to.deep.equals({ message: 'Hello, world!' })
}

if (mode === 'formdata') {
expect((req.headers || {})['Content-Type']).to.equals(
'multipart/form-data'
)
const headers = req.headers || {}
if (mode === 'formdata' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('multipart/form-data')
}

if (mode === 'urlencoded') {
expect((req.headers || {})['Content-Type']).to.equals(
if (mode === 'urlencoded' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals(
'application/x-www-form-urlencoded'
)
}

if (mode === 'raw') {
if (language === 'json') {
expect((req.headers || {})['Content-Type']).to.equals(
'application/json'
)
if (language === 'json' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('application/json')
}

if (language === 'text') {
expect((req.headers || {})['Content-Type']).to.equals(
'text/plain'
)
if (language === 'text' && 'Content-Type' in headers) {
expect(headers['Content-Type']).to.equals('text/plain')
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions src/components/logger/startup-message.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,16 +426,18 @@ describe('Startup message', () => {
// assert
expect(logMessage).include('config file')
})
})

// delete test on removing toggle
// delete tests on removing toggle
describe('Node fetch toggle', () => {
it('should show experimental fetch toggle', () => {
// act
logStartupMessage({
config: defaultConfig,
flags: {
config: ['./monika.yaml'],
verbose: false,
'experimental-fetch': true,
'native-fetch': true,
},
isFirstRun: false,
})
Expand All @@ -444,15 +446,14 @@ describe('Startup message', () => {
expect(logMessage).include('Using native Node.js fetch for HTTP client')
})

// delete test on removing toggle
it('should hide experimental fetch toggle', () => {
// act
logStartupMessage({
config: defaultConfig,
flags: {
config: ['./monika.yaml'],
verbose: false,
'experimental-fetch': false,
'native-fetch': false,
},
isFirstRun: false,
})
Expand Down
4 changes: 2 additions & 2 deletions src/components/logger/startup-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type LogStartupMessage = {
config: Config
flags: Pick<
MonikaFlags,
'config' | 'symonKey' | 'symonUrl' | 'verbose' | 'experimental-fetch'
'config' | 'symonKey' | 'symonUrl' | 'verbose' | 'native-fetch'
>
isFirstRun: boolean
}
Expand All @@ -62,7 +62,7 @@ export function logStartupMessage({
}
}

if (flags['experimental-fetch']) {
if (flags['native-fetch']) {
log.info('Using native Node.js fetch for HTTP client')
}

Expand Down
Loading

0 comments on commit ca5c3ac

Please sign in to comment.