From fc067aff1b36332df667da68dc6b37572b102f2f Mon Sep 17 00:00:00 2001 From: Marco Palladino <88.marco@gmail.com> Date: Fri, 29 Sep 2023 16:30:57 -0400 Subject: [PATCH 01/35] Switching to Apache License Version 2.0 --- LICENSE | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 202 insertions(+), 21 deletions(-) diff --git a/LICENSE b/LICENSE index dafaf46b4..2b684dabe 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,202 @@ -The MIT License (MIT) - -Copyright (c) 2022 Kong (https://www.konghq.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016-2023 Kong Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 7c3d401b51609aa7e42754fa72f7dc6fab588fd2 Mon Sep 17 00:00:00 2001 From: Itsik Maman Date: Mon, 18 Dec 2023 04:09:41 -0500 Subject: [PATCH 02/35] Support Node v20 (#333) * Support node v20 * Support node v20 --- .github/workflows/build.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e9674d67e..0d9704cab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [16, 18] + node-version: [16, 18, 20] steps: - name: Checkout branch uses: actions/checkout@v3 diff --git a/package.json b/package.json index 577b7b65a..1dcad8df2 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "xmlhttprequest" ], "engines": { - "node": "^14.19.1 || ^16.14.2 || ^18.0.0" + "node": "^14.19.1 || ^16.14.2 || ^18.0.0 || ^20.0.0" }, "repository": "Kong/httpsnippet", "bugs": { From 7efd8e0f9ac6fb922e4be4f21cd658010d17c9ce Mon Sep 17 00:00:00 2001 From: saisatishkarra Date: Tue, 23 Jan 2024 10:25:15 -0600 Subject: [PATCH 03/35] Add SAST scanning using semgrep (#336) --- .github/workflows/sast.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/sast.yml diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml new file mode 100644 index 000000000..86672638d --- /dev/null +++ b/.github/workflows/sast.yml @@ -0,0 +1,26 @@ +name: SAST + +on: + pull_request: {} + push: + branches: + - master + workflow_dispatch: {} + + +jobs: + semgrep: + name: Semgrep SAST + runs-on: ubuntu-latest + permissions: + # required for all workflows + security-events: write + # only required for workflows in private repositories + actions: read + contents: read + + if: (github.actor != 'dependabot[bot]') + + steps: + - uses: actions/checkout@v4 + - uses: Kong/public-shared-actions/security-actions/semgrep@bd3d75259607dd015bea3b3313123f53b80e9d7f From 2e8c285aed8e5dbaa300db81cb3d5a2f8b016802 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Thu, 16 May 2024 13:40:52 +0100 Subject: [PATCH 04/35] chore(feat/slsa)[SEC-1085]: add publish pipeline [INS-3792] (#347) * chore: add publish pipeline [INS-3792] * refactor build and publish pipeline to add provenance and sbom scan --------- Co-authored-by: saisatishkarra --- .github/workflows/build.yml | 52 ++++++++++++++++++++++++++++++++++- .github/workflows/release.yml | 43 +++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0d9704cab..41da6acea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,9 +1,11 @@ -name: Build +name: Build and Publish Httpsnippet on: push: branches: - master + tags: + - '*' # Restrict any specific tag formats pull_request: types: - opened @@ -11,6 +13,26 @@ on: workflow_dispatch: jobs: + scan: + permissions: + packages: write + contents: write # publish sbom to GH releases/tag assets + runs-on: ubuntu-latest + steps: + - name: Checkout branch + uses: actions/checkout@v3 + with: + path: ${{ github.repository }} + + # Perform SCA analysis for the code repository + # Produces SBOM and CVE report + # Helps understand vulnerabilities / license compliance across third party dependencies + - id: sca-project + uses: Kong/public-shared-actions/security-actions/sca@2f02738ecb1670f01391162e43fe3f5d4e7942a1 # v2.2.2 + with: + dir: ${{ github.repository }} + upload-sbom-release-assets: true + build: runs-on: ubuntu-latest strategy: @@ -37,3 +59,31 @@ jobs: - name: Build run: npm run build + + publish: + runs-on: ubuntu-latest + if: ${{ github.ref_type == 'tag' && github.repository_owner == 'Kong' }} + steps: + # checkout tag + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20.9.0 + registry-url: 'https://registry.npmjs.org' + + - name: Install + run: npm ci + + - name: Build + run: npm run build + + - name: Publish to NPM + run: npm publish --no-git-checks --provenance --tag ${{ github.sha }} + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..45e30afd4 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,43 @@ +name: Release httpsnippet + +on: + workflow_dispatch: + inputs: + version: + description: 'Tag version to release' + required: true + +env: + # Release Tag to build and publish + TAG: ${{ github.event.inputs.version }} + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Configure Git user + uses: Homebrew/actions/git-user-config@master + with: + username: ${{ (github.event_name == 'workflow_dispatch' && github.actor) || 'insomnia-infra' }} + + - name: Tag the Repository + run: | + git tag ${{ env.TAG }} + git push origin ${{ env.TAG }} + + - name: Create Tag and Release + uses: ncipollo/release-action@v1 + id: core_tag_and_release + with: + tag: ${{ env.TAG }} + name: "httpsnippet ${{ env.TAG }} 📦" + generateReleaseNotes: true + prerelease: false + draft: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 2aaed3475c806ccc4356054da349833f3e25562c Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Thu, 16 May 2024 16:23:35 +0100 Subject: [PATCH 05/35] fix(CI): add pat for triggering releases [no-ticket] (#349) --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 45e30afd4..04d6a4d07 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,7 +29,7 @@ jobs: run: | git tag ${{ env.TAG }} git push origin ${{ env.TAG }} - + - name: Create Tag and Release uses: ncipollo/release-action@v1 id: core_tag_and_release @@ -40,4 +40,4 @@ jobs: prerelease: false draft: false env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.PAT_INSOMNIA_INFRA }} From 36d0de12b5ce0115b986bc0dc7060f18c3f2d2e5 Mon Sep 17 00:00:00 2001 From: saisatishkarra Date: Thu, 16 May 2024 08:38:12 -0700 Subject: [PATCH 06/35] fix(CI): Persist PAT to trigger downstream workflow on tag push (#350) --- .github/workflows/build.yml | 1 + .github/workflows/release.yml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 41da6acea..0d45ca5eb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,6 +34,7 @@ jobs: upload-sbom-release-assets: true build: + needs: [scan] runs-on: ubuntu-latest strategy: fail-fast: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 04d6a4d07..f5464af1d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,6 +19,8 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + token: ${{ secrets.PAT_INSOMNIA_INFRA }} + - name: Configure Git user uses: Homebrew/actions/git-user-config@master From cfb34a752442d8a984f255dd6a1dd2bf6a6374a0 Mon Sep 17 00:00:00 2001 From: saisatishkarra Date: Thu, 16 May 2024 09:02:31 -0700 Subject: [PATCH 07/35] fix(ci): permissions to publish npm provenance (#351) --- .github/workflows/build.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0d45ca5eb..7e9a7ff6a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -63,6 +63,11 @@ jobs: publish: runs-on: ubuntu-latest + permissions: + contents: write + id-token: write # For using token to sign images + actions: read # For getting workflow run info to build provenance + packages: write # Required for publishing provenance. Issue: https://github.com/slsa-framework/slsa-github-generator/tree/main/internal/builders/container#known-issues if: ${{ github.ref_type == 'tag' && github.repository_owner == 'Kong' }} steps: # checkout tag From c4a69065fd070557d1854fcd3b5a779f7fc42d3d Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 17 May 2024 14:58:17 +0100 Subject: [PATCH 08/35] feat: add npm version to release pipeline [INS-3853] (#352) * feat: add npm version to release pipeline [INS-3853] * fix * add npm ci --- .github/workflows/release.yml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f5464af1d..9c656ae7d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,16 +21,32 @@ jobs: fetch-depth: 0 token: ${{ secrets.PAT_INSOMNIA_INFRA }} - - name: Configure Git user uses: Homebrew/actions/git-user-config@master with: username: ${{ (github.event_name == 'workflow_dispatch' && github.actor) || 'insomnia-infra' }} + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install + run: npm ci + + - name: Create new package version + run: npm version "${{ env.TAG }}" + + - name: Git Commit + run: git commit -am "Bump version to ${{ env.TAG }}" + - name: Tag the Repository run: | git tag ${{ env.TAG }} - git push origin ${{ env.TAG }} + remote_repo="https://${GITHUB_ACTOR}:${RELEASE_GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + git push "${remote_repo}" --follow-tags + env: + RELEASE_GH_TOKEN: ${{ secrets.PAT_INSOMNIA_INFRA }} - name: Create Tag and Release uses: ncipollo/release-action@v1 From 91be017439eca955b51f8f60b1beea5d51dee796 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 17 May 2024 15:19:53 +0100 Subject: [PATCH 09/35] fix: rm extra commit on release.yml [INS-3853] (#353) --- .github/workflows/release.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9c656ae7d..297c1373a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,9 +37,6 @@ jobs: - name: Create new package version run: npm version "${{ env.TAG }}" - - name: Git Commit - run: git commit -am "Bump version to ${{ env.TAG }}" - - name: Tag the Repository run: | git tag ${{ env.TAG }} From aa711ef70bfb7f21959b18959583fa1308303760 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 17 May 2024 15:33:02 +0100 Subject: [PATCH 10/35] fix: release push [INS-3853] (#354) --- .github/workflows/release.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 297c1373a..c56dcd0ec 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,11 +37,10 @@ jobs: - name: Create new package version run: npm version "${{ env.TAG }}" - - name: Tag the Repository + - name: Merge version commit into master run: | - git tag ${{ env.TAG }} remote_repo="https://${GITHUB_ACTOR}:${RELEASE_GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" - git push "${remote_repo}" --follow-tags + git push "${remote_repo}" env: RELEASE_GH_TOKEN: ${{ secrets.PAT_INSOMNIA_INFRA }} From b81e7074933d97761585f7dca884381ef8ffc2a3 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 17 May 2024 14:53:38 +0000 Subject: [PATCH 11/35] 3.0.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index fdcf2cdbb..eab902436 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "httpsnippet", - "version": "3.0.1", + "version": "3.0.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "httpsnippet", - "version": "3.0.1", + "version": "3.0.2", "license": "MIT", "dependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index 1dcad8df2..fa9a90217 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "3.0.1", + "version": "3.0.2", "name": "httpsnippet", "description": "HTTP Request snippet generator for *most* languages", "author": "Kong ", From a3ddd6cd9640e3ee7dca029710cb9bf74d8649ac Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 17 May 2024 16:12:42 +0100 Subject: [PATCH 12/35] fix: tag weirdness (#355) * fix: tag weirdness * fix * fix * fix --- .github/workflows/release.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c56dcd0ec..5a813b667 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,12 +37,13 @@ jobs: - name: Create new package version run: npm version "${{ env.TAG }}" - - name: Merge version commit into master + - name: DEBUG see tags run: | - remote_repo="https://${GITHUB_ACTOR}:${RELEASE_GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" - git push "${remote_repo}" - env: - RELEASE_GH_TOKEN: ${{ secrets.PAT_INSOMNIA_INFRA }} + git tag --list + git remote -v + + - name: Merge version commit into master + run: git push origin ${{ env.TAG }} - name: Create Tag and Release uses: ncipollo/release-action@v1 @@ -52,6 +53,4 @@ jobs: name: "httpsnippet ${{ env.TAG }} 📦" generateReleaseNotes: true prerelease: false - draft: false - env: - GITHUB_TOKEN: ${{ secrets.PAT_INSOMNIA_INFRA }} + draft: false \ No newline at end of file From 140d4b7d0e77ec84e8c71900ab0138fbc5728510 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 17 May 2024 16:17:46 +0100 Subject: [PATCH 13/35] fix: release tags --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5a813b667..fc7dffc44 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,14 +43,14 @@ jobs: git remote -v - name: Merge version commit into master - run: git push origin ${{ env.TAG }} + run: git push origin v${{ env.TAG }} - name: Create Tag and Release uses: ncipollo/release-action@v1 id: core_tag_and_release with: - tag: ${{ env.TAG }} - name: "httpsnippet ${{ env.TAG }} 📦" + tag: v${{ env.TAG }} + name: "httpsnippet v${{ env.TAG }} 📦" generateReleaseNotes: true prerelease: false draft: false \ No newline at end of file From 771796620002b53e4f58f39ce5d1953baa869922 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 17 May 2024 16:24:57 +0100 Subject: [PATCH 14/35] fix: push also to origin --- .github/workflows/release.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fc7dffc44..4b98f66ef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,9 @@ jobs: git remote -v - name: Merge version commit into master - run: git push origin v${{ env.TAG }} + run: | + git push origin v${{ env.TAG }} + git push origin master - name: Create Tag and Release uses: ncipollo/release-action@v1 From 63650f3f6a921e4a617316ba12f14904d9af4b76 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 17 May 2024 15:25:55 +0000 Subject: [PATCH 15/35] 3.0.4 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index eab902436..2dd07b596 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "httpsnippet", - "version": "3.0.2", + "version": "3.0.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "httpsnippet", - "version": "3.0.2", + "version": "3.0.4", "license": "MIT", "dependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index fa9a90217..ea2456625 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "3.0.2", + "version": "3.0.4", "name": "httpsnippet", "description": "HTTP Request snippet generator for *most* languages", "author": "Kong ", From 143bb6d3c9c7acd8fa6e0b9d412cbacd25ae5b39 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Tue, 2 Jul 2024 01:14:23 +0100 Subject: [PATCH 16/35] Create SECURITY.md [SEC-1138] --- SECURITY.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..b423b5d6f --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,32 @@ +# Security Policy + +## Reporting a Vulnerability + +At HTTPSnippet, we take security issues very seriously. If you believe you have found a security vulnerability in our project, we encourage you to disclose it responsibly. Please report any potential security vulnerabilities to us by sending an email to [vulnerability@konghq.com](mailto:vulnerability@konghq.com). + +## How to Report + +1. **Do not publicly disclose the vulnerability**: Please do not create a GitHub issue or post the vulnerability on public forums. Instead, contact us directly at [vulnerability@konghq.com](mailto:vulnerability@konghq.com). +2. **Provide detailed information**: When reporting a vulnerability, please include as much information as possible to help us understand and reproduce the issue. This may include: + - Description of the vulnerability + - Steps to reproduce the issue + - Potential impact + - Any relevant logs or screenshots + +## What to Expect + +- **Acknowledgment**: We will acknowledge receipt of your vulnerability report within 48 hours. +- **Investigation**: Our security team will investigate the report and will keep you informed of the progress. We aim to resolve critical vulnerabilities within 30 days of confirmation. +- **Disclosure**: We prefer coordinated disclosure and will work with you to schedule the disclosure of the vulnerability in a way that minimizes the risk to users. + +## Bug Bounty Program + +We encourage security researchers to participate in our bug bounty program as outlined on the [Kong Vulnerability Disclosure](https://konghq.com/compliance/bug-bounty) page. This program provides rewards for discovering and reporting security vulnerabilities in accordance with our disclosure guidelines. + +Thank you for helping to keep HTTPSnippet secure. + +For more information on our security policies and guidelines, please visit the [Kong Vulnerability Disclosure](https://konghq.com/compliance/bug-bounty) page. + +## Contact + +For any questions or further assistance, please contact us at [vulnerability@konghq.com](mailto:vulnerability@konghq.com). From e901d614579904928555b223f9d864938fa968c7 Mon Sep 17 00:00:00 2001 From: Ben Schofield <47790940+Benjscho@users.noreply.github.com> Date: Fri, 12 Jul 2024 09:28:10 -0700 Subject: [PATCH 17/35] Add rust target with reqwest (#328) * Create initial rust files Create initial rust files to support the target. Create all of the demo fixture files for the different request types. These also require specific `Cargo.toml` dependencies with some features, but I've tried to keep them fully qualified where possible. I'm not sure yet how best to show adding dependencies to a project to enable these features. * Start work on reqwest client Start working on the reqwest conversion client after adding targets. * Complete Adding Rust as target Completed adding Rust as a target. All of the fixtures have been tested in a separate Rust project to verify that they build and successfully run against the Har test endpoint. All tests are running and passing, except for the snapshot that verifies all available targets, not sure where to update that. * Run linter Ran the linter defined in `package.json` All tests except snapshot for targets passing. * Update snapshot to fix available targets test Update the available targets test to fix the snapshot. * lint --------- Co-authored-by: Filipe Freire --- .github/workflows/build.yml | 7 +- .github/workflows/release.yml | 4 +- .github/workflows/sast.yml | 3 +- SECURITY.md | 2 +- package-lock.json | 2 +- package.json | 3 +- src/helpers/__snapshots__/utils.test.ts.snap | 14 + src/helpers/code-builder.ts | 12 + src/helpers/escape.test.ts | 20 +- src/helpers/escape.ts | 69 +++-- src/helpers/headers.ts | 2 - src/targets/c/libcurl/client.ts | 6 +- src/targets/ocaml/cohttp/client.ts | 4 +- src/targets/php/guzzle/client.ts | 8 +- src/targets/php/helpers.ts | 2 +- src/targets/powershell/common.ts | 9 +- src/targets/r/httr/client.ts | 25 +- src/targets/rust/helpers.ts | 84 ++++++ src/targets/rust/reqwest/client.ts | 239 ++++++++++++++++++ .../fixtures/application-form-encoded.rs | 29 +++ .../rust/reqwest/fixtures/application-json.rs | 33 +++ src/targets/rust/reqwest/fixtures/cookies.rs | 22 ++ .../rust/reqwest/fixtures/custom-method.rs | 19 ++ src/targets/rust/reqwest/fixtures/full.rs | 35 +++ src/targets/rust/reqwest/fixtures/headers.rs | 24 ++ src/targets/rust/reqwest/fixtures/https.rs | 18 ++ .../reqwest/fixtures/jsonObj-multiline.rs | 26 ++ .../reqwest/fixtures/jsonObj-null-value.rs | 26 ++ .../rust/reqwest/fixtures/multipart-data.rs | 34 +++ .../rust/reqwest/fixtures/multipart-file.rs | 33 +++ .../fixtures/multipart-form-data-no-params.rs | 24 ++ .../reqwest/fixtures/multipart-form-data.rs | 24 ++ src/targets/rust/reqwest/fixtures/nested.rs | 25 ++ src/targets/rust/reqwest/fixtures/query.rs | 25 ++ src/targets/rust/reqwest/fixtures/short.rs | 18 ++ .../rust/reqwest/fixtures/text-plain.rs | 26 ++ src/targets/rust/target.ts | 14 + src/targets/targets.test.ts | 12 +- src/targets/targets.ts | 2 + tsconfig.build.json | 2 +- 40 files changed, 897 insertions(+), 89 deletions(-) create mode 100644 src/targets/rust/helpers.ts create mode 100644 src/targets/rust/reqwest/client.ts create mode 100644 src/targets/rust/reqwest/fixtures/application-form-encoded.rs create mode 100644 src/targets/rust/reqwest/fixtures/application-json.rs create mode 100644 src/targets/rust/reqwest/fixtures/cookies.rs create mode 100644 src/targets/rust/reqwest/fixtures/custom-method.rs create mode 100644 src/targets/rust/reqwest/fixtures/full.rs create mode 100644 src/targets/rust/reqwest/fixtures/headers.rs create mode 100644 src/targets/rust/reqwest/fixtures/https.rs create mode 100644 src/targets/rust/reqwest/fixtures/jsonObj-multiline.rs create mode 100644 src/targets/rust/reqwest/fixtures/jsonObj-null-value.rs create mode 100644 src/targets/rust/reqwest/fixtures/multipart-data.rs create mode 100644 src/targets/rust/reqwest/fixtures/multipart-file.rs create mode 100644 src/targets/rust/reqwest/fixtures/multipart-form-data-no-params.rs create mode 100644 src/targets/rust/reqwest/fixtures/multipart-form-data.rs create mode 100644 src/targets/rust/reqwest/fixtures/nested.rs create mode 100644 src/targets/rust/reqwest/fixtures/query.rs create mode 100644 src/targets/rust/reqwest/fixtures/short.rs create mode 100644 src/targets/rust/reqwest/fixtures/text-plain.rs create mode 100644 src/targets/rust/target.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e9a7ff6a..ab177cee8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,7 +15,7 @@ on: jobs: scan: permissions: - packages: write + packages: write contents: write # publish sbom to GH releases/tag assets runs-on: ubuntu-latest steps: @@ -74,14 +74,14 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 + fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20.9.0 registry-url: 'https://registry.npmjs.org' - + - name: Install run: npm ci @@ -92,4 +92,3 @@ jobs: run: npm publish --no-git-checks --provenance --tag ${{ github.sha }} env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4b98f66ef..20d87aedc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,7 +52,7 @@ jobs: id: core_tag_and_release with: tag: v${{ env.TAG }} - name: "httpsnippet v${{ env.TAG }} 📦" + name: 'httpsnippet v${{ env.TAG }} 📦' generateReleaseNotes: true prerelease: false - draft: false \ No newline at end of file + draft: false diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index 86672638d..92cfb5440 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -4,10 +4,9 @@ on: pull_request: {} push: branches: - - master + - master workflow_dispatch: {} - jobs: semgrep: name: Semgrep SAST diff --git a/SECURITY.md b/SECURITY.md index b423b5d6f..17989d2a4 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -7,7 +7,7 @@ At HTTPSnippet, we take security issues very seriously. If you believe you have ## How to Report 1. **Do not publicly disclose the vulnerability**: Please do not create a GitHub issue or post the vulnerability on public forums. Instead, contact us directly at [vulnerability@konghq.com](mailto:vulnerability@konghq.com). -2. **Provide detailed information**: When reporting a vulnerability, please include as much information as possible to help us understand and reproduce the issue. This may include: +1. **Provide detailed information**: When reporting a vulnerability, please include as much information as possible to help us understand and reproduce the issue. This may include: - Description of the vulnerability - Steps to reproduce the issue - Potential impact diff --git a/package-lock.json b/package-lock.json index 2dd07b596..289dab03d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,7 @@ "typescript": "^4.6.3" }, "engines": { - "node": "^14.19.1 || ^16.14.2 || ^18.0.0" + "node": "^14.19.1 || ^16.14.2 || ^18.0.0 || ^20.0.0" } }, "node_modules/@aashutoshrathi/word-wrap": { diff --git a/package.json b/package.json index ea2456625..2613b2b27 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "request", "requests", "ruby", + "rust", "shell", "snippet", "swift", @@ -72,8 +73,8 @@ "eslint-plugin-jest": "^26.1.3", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-simple-import-sort": "^7.0.0", - "markdownlint-cli2": "^0.5.1", "jest": "^27.5.1", + "markdownlint-cli2": "^0.5.1", "prettier": "^2.6.2", "ts-jest": "^27.1.4", "type-fest": "^2.12.2", diff --git a/src/helpers/__snapshots__/utils.test.ts.snap b/src/helpers/__snapshots__/utils.test.ts.snap index 7abba1405..d8af8e024 100644 --- a/src/helpers/__snapshots__/utils.test.ts.snap +++ b/src/helpers/__snapshots__/utils.test.ts.snap @@ -322,6 +322,20 @@ Array [ "key": "ruby", "title": "Ruby", }, + Object { + "clients": Array [ + Object { + "description": "reqwest HTTP library", + "key": "reqwest", + "link": "https://docs.rs/reqwest/latest/reqwest/", + "title": "reqwest", + }, + ], + "default": "reqwest", + "extname": ".rs", + "key": "rust", + "title": "Rust", + }, Object { "clients": Array [ Object { diff --git a/src/helpers/code-builder.ts b/src/helpers/code-builder.ts index 8ad78d65f..b0d4b26d8 100644 --- a/src/helpers/code-builder.ts +++ b/src/helpers/code-builder.ts @@ -56,6 +56,18 @@ export class CodeBuilder { this.code.push(newLine); }; + /** + * Add the line to the end of the last line. Creates a new line + * if no lines exist yet. + */ + pushToLast = (line: string) => { + if (!this.code) { + this.push(line); + } + const updatedLine = `${this.code[this.code.length - 1]}${line}`; + this.code[this.code.length - 1] = updatedLine; + }; + /** * Add an empty line at the end of current lines */ diff --git a/src/helpers/escape.test.ts b/src/helpers/escape.test.ts index 4750ec381..c9a2e1e26 100644 --- a/src/helpers/escape.test.ts +++ b/src/helpers/escape.test.ts @@ -1,34 +1,26 @@ import { escapeString } from './escape'; -describe('Escape methods', () => { +describe('escape methods', () => { describe('escapeString', () => { it('does nothing to a safe string', () => { - expect( - escapeString("hello world") - ).toBe("hello world"); + expect(escapeString('hello world')).toBe('hello world'); }); it('escapes double quotes by default', () => { - expect( - escapeString('"hello world"') - ).toBe('\\"hello world\\"'); + expect(escapeString('"hello world"')).toBe('\\"hello world\\"'); }); it('escapes newlines by default', () => { - expect( - escapeString('hello\r\nworld') - ).toBe('hello\\r\\nworld'); + expect(escapeString('hello\r\nworld')).toBe('hello\\r\\nworld'); }); it('escapes backslashes', () => { - expect( - escapeString('hello\\world') - ).toBe('hello\\\\world'); + expect(escapeString('hello\\world')).toBe('hello\\\\world'); }); it('escapes unrepresentable characters', () => { expect( - escapeString('hello \u0000') // 0 = ASCII 'null' character + escapeString('hello \u0000'), // 0 = ASCII 'null' character ).toBe('hello \\u0000'); }); }); diff --git a/src/helpers/escape.ts b/src/helpers/escape.ts index cbedfda90..fabe32904 100644 --- a/src/helpers/escape.ts +++ b/src/helpers/escape.ts @@ -31,47 +31,42 @@ export interface EscapeOptions { * for the complete original algorithm. */ export function escapeString(rawValue: any, options: EscapeOptions = {}) { - const { - delimiter = '"', - escapeChar = '\\', - escapeNewlines = true - } = options; + const { delimiter = '"', escapeChar = '\\', escapeNewlines = true } = options; const stringValue = rawValue.toString(); - return [...stringValue].map((c) => { - if (c === '\b') { - return escapeChar + 'b'; - } else if (c === '\t') { - return escapeChar + 't'; - } else if (c === '\n') { - if (escapeNewlines) { - return escapeChar + 'n'; - } else { + return [...stringValue] + .map(c => { + if (c === '\b') { + return `${escapeChar}b`; + } else if (c === '\t') { + return `${escapeChar}t`; + } else if (c === '\n') { + if (escapeNewlines) { + return `${escapeChar}n`; + } return c; // Don't just continue, or this is caught by < \u0020 - } - } else if (c === '\f') { - return escapeChar + 'f'; - } else if (c === '\r') { - if (escapeNewlines) { - return escapeChar + 'r'; - } else { + } else if (c === '\f') { + return `${escapeChar}f`; + } else if (c === '\r') { + if (escapeNewlines) { + return `${escapeChar}r`; + } return c; // Don't just continue, or this is caught by < \u0020 + } else if (c === escapeChar) { + return escapeChar + escapeChar; + } else if (c === delimiter) { + return escapeChar + delimiter; + } else if (c < '\u0020' || c > '\u007E') { + // Delegate the trickier non-ASCII cases to the normal algorithm. Some of these + // are escaped as \uXXXX, whilst others are represented literally. Since we're + // using this primarily for header values that are generally (though not 100% + // strictly?) ASCII-only, this should almost never happen. + return JSON.stringify(c).slice(1, -1); } - } else if (c === escapeChar) { - return escapeChar + escapeChar; - } else if (c === delimiter) { - return escapeChar + delimiter; - } else if (c < '\u0020' || c > '\u007E') { - // Delegate the trickier non-ASCII cases to the normal algorithm. Some of these - // are escaped as \uXXXX, whilst others are represented literally. Since we're - // using this primarily for header values that are generally (though not 100% - // strictly?) ASCII-only, this should almost never happen. - return JSON.stringify(c).slice(1, -1); - } else { return c; - } - }).join(''); + }) + .join(''); } /** @@ -81,8 +76,7 @@ export function escapeString(rawValue: any, options: EscapeOptions = {}) { * * If value is not a string, it will be stringified with .toString() first. */ -export const escapeForSingleQuotes = (value: any) => - escapeString(value, { delimiter: "'" }); +export const escapeForSingleQuotes = (value: any) => escapeString(value, { delimiter: "'" }); /** * Make a string value safe to insert literally into a snippet within double quotes, @@ -91,5 +85,4 @@ export const escapeForSingleQuotes = (value: any) => * * If value is not a string, it will be stringified with .toString() first. */ -export const escapeForDoubleQuotes = (value: any) => - escapeString(value, { delimiter: '"' }); +export const escapeForDoubleQuotes = (value: any) => escapeString(value, { delimiter: '"' }); diff --git a/src/helpers/headers.ts b/src/helpers/headers.ts index b8353863a..dfae16c72 100644 --- a/src/helpers/headers.ts +++ b/src/helpers/headers.ts @@ -1,5 +1,3 @@ -import { ValueOf } from 'type-fest'; - type Headers = Record; /** diff --git a/src/targets/c/libcurl/client.ts b/src/targets/c/libcurl/client.ts index 7f6e9b42d..7eb778fce 100644 --- a/src/targets/c/libcurl/client.ts +++ b/src/targets/c/libcurl/client.ts @@ -26,7 +26,11 @@ export const libcurl: Client = { push('struct curl_slist *headers = NULL;'); headers.forEach(header => { - push(`headers = curl_slist_append(headers, "${header}: ${escapeForDoubleQuotes(headersObj[header])}");`); + push( + `headers = curl_slist_append(headers, "${header}: ${escapeForDoubleQuotes( + headersObj[header], + )}");`, + ); }); push('curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);'); diff --git a/src/targets/ocaml/cohttp/client.ts b/src/targets/ocaml/cohttp/client.ts index 0528ead78..07fad6065 100644 --- a/src/targets/ocaml/cohttp/client.ts +++ b/src/targets/ocaml/cohttp/client.ts @@ -39,7 +39,9 @@ export const cohttp: Client = { if (headers.length === 1) { push( - `let headers = Header.add (Header.init ()) "${headers[0]}" "${escapeForDoubleQuotes(allHeaders[headers[0]])}" in`, + `let headers = Header.add (Header.init ()) "${headers[0]}" "${escapeForDoubleQuotes( + allHeaders[headers[0]], + )}" in`, ); } else if (headers.length > 1) { push('let headers = Header.add_list (Header.init ()) ['); diff --git a/src/targets/php/guzzle/client.ts b/src/targets/php/guzzle/client.ts index 6daf3effd..a9a15fde4 100644 --- a/src/targets/php/guzzle/client.ts +++ b/src/targets/php/guzzle/client.ts @@ -123,7 +123,9 @@ export const guzzle: Client = { const headers = Object.keys(headersObj) .sort() .map(function (key) { - return `${opts.indent}${opts.indent}'${key}' => '${escapeForSingleQuotes(headersObj[key])}',`; + return `${ + opts.indent + }${opts.indent}'${key}' => '${escapeForSingleQuotes(headersObj[key])}',`; }); // construct cookies @@ -131,7 +133,9 @@ export const guzzle: Client = { .map(cookie => `${encodeURIComponent(cookie.name)}=${encodeURIComponent(cookie.value)}`) .join('; '); if (cookieString.length) { - headers.push(`${opts.indent}${opts.indent}'cookie' => '${escapeForSingleQuotes(cookieString)}',`); + headers.push( + `${opts.indent}${opts.indent}'cookie' => '${escapeForSingleQuotes(cookieString)}',`, + ); } if (headers.length) { diff --git a/src/targets/php/helpers.ts b/src/targets/php/helpers.ts index 5d6670e9d..b64a932b3 100644 --- a/src/targets/php/helpers.ts +++ b/src/targets/php/helpers.ts @@ -1,4 +1,4 @@ -import { escapeString } from "../../helpers/escape"; +import { escapeString } from '../../helpers/escape'; export const convertType = (obj: any[] | any, indent?: string, lastIndent?: string) => { lastIndent = lastIndent || ''; diff --git a/src/targets/powershell/common.ts b/src/targets/powershell/common.ts index bba0789b9..9cf395def 100644 --- a/src/targets/powershell/common.ts +++ b/src/targets/powershell/common.ts @@ -56,9 +56,12 @@ export const generatePowershellConvert = (command: PowershellCommand) => { } if (postData.text) { - commandOptions.push(`-ContentType '${ - escapeString(getHeader(allHeaders, 'content-type'), { delimiter: "'", escapeChar: '`' }) - }'`); + commandOptions.push( + `-ContentType '${escapeString(getHeader(allHeaders, 'content-type'), { + delimiter: "'", + escapeChar: '`', + })}'`, + ); commandOptions.push(`-Body '${postData.text}'`); } diff --git a/src/targets/r/httr/client.ts b/src/targets/r/httr/client.ts index 0d1e92eab..c8c2f2061 100644 --- a/src/targets/r/httr/client.ts +++ b/src/targets/r/httr/client.ts @@ -98,31 +98,26 @@ export const httr: Client = { // Construct headers const cookieHeader = getHeader(allHeaders, 'cookie'); - let acceptHeader = getHeader(allHeaders, 'accept'); + const acceptHeader = getHeader(allHeaders, 'accept'); const setCookies = cookieHeader ? `set_cookies(\`${String(cookieHeader) .replace(/;/g, '", `') .replace(/` /g, '`') - .replace(/[=]/g, '` = "') - }")` - : undefined + .replace(/[=]/g, '` = "')}")` + : undefined; - const setAccept = acceptHeader - ? `accept("${escapeForDoubleQuotes(acceptHeader)}")` - : undefined + const setAccept = acceptHeader ? `accept("${escapeForDoubleQuotes(acceptHeader)}")` : undefined; - const setContentType = `content_type("${escapeForDoubleQuotes(postData.mimeType)}")` + const setContentType = `content_type("${escapeForDoubleQuotes(postData.mimeType)}")`; const otherHeaders = Object.entries(allHeaders) // These headers are all handled separately: .filter(([key]) => !['cookie', 'accept', 'content-type'].includes(key.toLowerCase())) .map(([key, value]) => `'${key}' = '${escapeForSingleQuotes(value)}'`) - .join(', ') + .join(', '); - const setHeaders = otherHeaders - ? `add_headers(${otherHeaders})` - : undefined + const setHeaders = otherHeaders ? `add_headers(${otherHeaders})` : undefined; // Construct request let request = `response <- VERB("${method}", url`; @@ -135,10 +130,12 @@ export const httr: Client = { request += ', query = queryString'; } - const headerAdditions = [setHeaders, setContentType, setAccept, setCookies].filter(x => !!x).join(', '); + const headerAdditions = [setHeaders, setContentType, setAccept, setCookies] + .filter(x => !!x) + .join(', '); if (headerAdditions) { - request += ', ' + headerAdditions + request += `, ${headerAdditions}`; } if (postData.text || postData.jsonObj || postData.params) { diff --git a/src/targets/rust/helpers.ts b/src/targets/rust/helpers.ts new file mode 100644 index 000000000..39844ed88 --- /dev/null +++ b/src/targets/rust/helpers.ts @@ -0,0 +1,84 @@ +function concatValues( + concatType: 'array' | 'object', + values: any, + pretty: boolean, + indentation: string, + indentLevel: number, +): string { + const currentIndent = indentation.repeat(indentLevel); + const closingBraceIndent = indentation.repeat(indentLevel - 1); + const join = pretty ? `,\n${currentIndent}` : ', '; + const openingBrace = concatType === 'object' ? 'json!({' : '('; + const closingBrace = concatType === 'object' ? '})' : ')'; + + if (pretty) { + return `${openingBrace}\n${currentIndent}${values.join( + join, + )}\n${closingBraceIndent}${closingBrace}`; + } + + return `${openingBrace}${values.join(join)}${closingBrace}`; +} + +/** + * Create a valid Rust string of a literal value using serde_json according to its type. + * + * @param {*} value Any Javascript literal + * @param {Object} opts Target options + * @return {string} + */ +export const literalRepresentation = ( + value: any, + opts: Record, + indentLevel?: number, +): any => { + /* + * Note: this version is almost entirely borrowed from the Python client helper. The + * only real modification involves the braces and the types. The helper + * could potentially be parameterised for reuse. + */ + indentLevel = indentLevel === undefined ? 1 : indentLevel + 1; + + switch (Object.prototype.toString.call(value)) { + case '[object Number]': + return value; + + case '[object Array]': { + let pretty = false; + const valuesRep: any = (value as any[]).map(v => { + // Switch to prettify if the value is a dict with more than one key. + if (Object.prototype.toString.call(v) === '[object Object]') { + pretty = Object.keys(v).length > 1; + } + return literalRepresentation(v, opts, indentLevel); + }); + return concatValues('array', valuesRep, pretty, opts.indent, indentLevel); + } + + case '[object Object]': { + const keyValuePairs = []; + for (const key in value) { + keyValuePairs.push(`"${key}": ${literalRepresentation(value[key], opts, indentLevel)}`); + } + return concatValues( + 'object', + keyValuePairs, + opts.pretty && keyValuePairs.length > 1, + opts.indent, + indentLevel, + ); + } + + case '[object Null]': + return 'json!(null)'; + + case '[object Boolean]': + return value ? 'true' : 'false'; + + default: + if (value === null || value === undefined) { + return ''; + } + return `"${value.toString().replace(/"/g, '\\"')}"`; + } +}; diff --git a/src/targets/rust/reqwest/client.ts b/src/targets/rust/reqwest/client.ts new file mode 100644 index 000000000..b06f413f5 --- /dev/null +++ b/src/targets/rust/reqwest/client.ts @@ -0,0 +1,239 @@ +/** + * @description + * HTTP code snippet generator for Rust using reqwest + * + * @author + * @Benjscho + * + * for any questions or issues regarding the generated code snippet, please open an issue mentioning the author. + */ + +import { CodeBuilder } from '../../../helpers/code-builder'; +import { Client } from '../../targets'; +import { literalRepresentation } from '../helpers'; + +export const reqwest: Client = { + info: { + key: 'reqwest', + title: 'reqwest', + link: 'https://docs.rs/reqwest/latest/reqwest/', + description: 'reqwest HTTP library', + }, + convert: ({ queryObj, url, postData, allHeaders, method }, options) => { + const opts = { + indent: ' ', + pretty: true, + ...options, + }; + + let indentLevel = 0; + + // start snippet + const { push, blank, join, pushToLast, unshift } = new CodeBuilder({ indent: opts.indent }); + + // import reqwest + push('use reqwest;', indentLevel); + blank(); + + // start async main for tokio + push('#[tokio::main]', indentLevel); + push('pub async fn main() {', indentLevel); + indentLevel += 1; + + // add url + push(`let url = "${url}";`, indentLevel); + blank(); + + let hasQuery = false; + // construct query string + if (Object.keys(queryObj).length) { + hasQuery = true; + push('let querystring = [', indentLevel); + indentLevel += 1; + for (const [key, value] of Object.entries(queryObj)) { + push(`("${key}", "${value}"),`, indentLevel); + } + indentLevel -= 1; + push('];', indentLevel); + blank(); + } + + // construct payload + let payload: Record = {}; + const files: Record = {}; + + let hasFiles = false; + let hasForm = false; + let hasBody = false; + let jsonPayload = false; + let isMultipart = false; + switch (postData.mimeType) { + case 'application/json': + if (postData.jsonObj) { + push( + `let payload = ${literalRepresentation(postData.jsonObj, opts, indentLevel)};`, + indentLevel, + ); + } + jsonPayload = true; + break; + + case 'multipart/form-data': + isMultipart = true; + + if (!postData.params) { + push(`let form = reqwest::multipart::Form::new()`, indentLevel); + push(`.text("", "");`, indentLevel + 1); + break; + } + + payload = {}; + postData.params.forEach(p => { + if (p.fileName) { + files[p.name] = p.fileName; + hasFiles = true; + } else { + payload[p.name] = p.value; + } + }); + + if (hasFiles) { + for (const line of fileToPartString) { + push(line, indentLevel); + } + blank(); + } + push(`let form = reqwest::multipart::Form::new()`, indentLevel); + + for (const [name, fileName] of Object.entries(files)) { + push(`.part("${name}", file_to_part("${fileName}").await)`, indentLevel + 1); + } + for (const [name, value] of Object.entries(payload)) { + push(`.text("${name}", "${value}")`, indentLevel + 1); + } + pushToLast(';'); + + break; + + default: { + if (postData.mimeType === 'application/x-www-form-urlencoded' && postData.paramsObj) { + push( + `let payload = ${literalRepresentation(postData.paramsObj, opts, indentLevel)};`, + indentLevel, + ); + hasForm = true; + break; + } + + if (postData.text) { + push( + `let payload = ${literalRepresentation(postData.text, opts, indentLevel)};`, + indentLevel, + ); + hasBody = true; + break; + } + } + } + + if (hasForm || jsonPayload || hasBody) { + unshift(`use serde_json::json;`); + blank(); + } + + let hasHeaders = false; + // construct headers + if (Object.keys(allHeaders).length) { + hasHeaders = true; + push('let mut headers = reqwest::header::HeaderMap::new();', indentLevel); + for (const [key, value] of Object.entries(allHeaders)) { + // Skip setting content-type if there is a file, as this header will + // cause the request to hang, and reqwest will set it for us. + if (key.toLowerCase() === 'content-type' && isMultipart) { + continue; + } + push( + `headers.insert("${key}", ${literalRepresentation(value, opts)}.parse().unwrap());`, + indentLevel, + ); + } + blank(); + } + + // construct client + push('let client = reqwest::Client::new();', indentLevel); + + // construct query + switch (method) { + case 'POST': + push(`let response = client.post(url)`, indentLevel); + break; + + case 'GET': + push(`let response = client.get(url)`, indentLevel); + break; + + default: { + push( + `let response = client.request(reqwest::Method::from_str("${method}").unwrap(), url)`, + indentLevel, + ); + unshift(`use std::str::FromStr;`); + break; + } + } + + if (hasQuery) { + push(`.query(&querystring)`, indentLevel + 1); + } + + if (isMultipart) { + push(`.multipart(form)`, indentLevel + 1); + } + + if (hasHeaders) { + push(`.headers(headers)`, indentLevel + 1); + } + + if (jsonPayload) { + push(`.json(&payload)`, indentLevel + 1); + } + + if (hasForm) { + push(`.form(&payload)`, indentLevel + 1); + } + + if (hasBody) { + push(`.body(payload)`, indentLevel + 1); + } + + // send query + push('.send()', indentLevel + 1); + push('.await;', indentLevel + 1); + blank(); + + // Print response + push('let results = response.unwrap()', indentLevel); + push('.json::()', indentLevel + 1); + push('.await', indentLevel + 1); + push('.unwrap();', indentLevel + 1); + blank(); + + push('dbg!(results);', indentLevel); + + push('}\n'); + + return join(); + }, +}; + +const fileToPartString = [ + `async fn file_to_part(file_name: &'static str) -> reqwest::multipart::Part {`, + ` let file = tokio::fs::File::open(file_name).await.unwrap();`, + ` let stream = tokio_util::codec::FramedRead::new(file, tokio_util::codec::BytesCodec::new());`, + ` let body = reqwest::Body::wrap_stream(stream);`, + ` reqwest::multipart::Part::stream(body)`, + ` .file_name(file_name)`, + ` .mime_str("text/plain").unwrap()`, + `}`, +]; diff --git a/src/targets/rust/reqwest/fixtures/application-form-encoded.rs b/src/targets/rust/reqwest/fixtures/application-form-encoded.rs new file mode 100644 index 000000000..cfd4e7058 --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/application-form-encoded.rs @@ -0,0 +1,29 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let payload = json!({ + "foo": "bar", + "hello": "world" + }); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("content-type", "application/x-www-form-urlencoded".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .form(&payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/application-json.rs b/src/targets/rust/reqwest/fixtures/application-json.rs new file mode 100644 index 000000000..9c2f155d3 --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/application-json.rs @@ -0,0 +1,33 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let payload = json!({ + "number": 1, + "string": "f\"oo", + "arr": (1, 2, 3), + "nested": json!({"a": "b"}), + "arr_mix": (1, "a", json!({"arr_mix_nested": json!({})})), + "boolean": false + }); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("content-type", "application/json".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .json(&payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/cookies.rs b/src/targets/rust/reqwest/fixtures/cookies.rs new file mode 100644 index 000000000..fd84c788d --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/cookies.rs @@ -0,0 +1,22 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("cookie", "foo=bar; bar=baz".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/custom-method.rs b/src/targets/rust/reqwest/fixtures/custom-method.rs new file mode 100644 index 000000000..be726a016 --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/custom-method.rs @@ -0,0 +1,19 @@ +use std::str::FromStr; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let client = reqwest::Client::new(); + let response = client.request(reqwest::Method::from_str("PROPFIND").unwrap(), url) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/full.rs b/src/targets/rust/reqwest/fixtures/full.rs new file mode 100644 index 000000000..6f5d0eb9d --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/full.rs @@ -0,0 +1,35 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let querystring = [ + ("foo", "bar,baz"), + ("baz", "abc"), + ("key", "value"), + ]; + + let payload = json!({"foo": "bar"}); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("cookie", "foo=bar; bar=baz".parse().unwrap()); + headers.insert("accept", "application/json".parse().unwrap()); + headers.insert("content-type", "application/x-www-form-urlencoded".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .query(&querystring) + .headers(headers) + .form(&payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/headers.rs b/src/targets/rust/reqwest/fixtures/headers.rs new file mode 100644 index 000000000..9552aac2f --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/headers.rs @@ -0,0 +1,24 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("accept", "application/json".parse().unwrap()); + headers.insert("x-foo", "Bar".parse().unwrap()); + headers.insert("quoted-value", "\"quoted\" 'string'".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.get(url) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/https.rs b/src/targets/rust/reqwest/fixtures/https.rs new file mode 100644 index 000000000..ce06b998b --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/https.rs @@ -0,0 +1,18 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "https://mockbin.com/har"; + + let client = reqwest::Client::new(); + let response = client.get(url) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/jsonObj-multiline.rs b/src/targets/rust/reqwest/fixtures/jsonObj-multiline.rs new file mode 100644 index 000000000..2d43904dd --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/jsonObj-multiline.rs @@ -0,0 +1,26 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let payload = json!({"foo": "bar"}); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("content-type", "application/json".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .json(&payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/jsonObj-null-value.rs b/src/targets/rust/reqwest/fixtures/jsonObj-null-value.rs new file mode 100644 index 000000000..4c82a8567 --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/jsonObj-null-value.rs @@ -0,0 +1,26 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let payload = json!({"foo": json!(null)}); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("content-type", "application/json".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .json(&payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/multipart-data.rs b/src/targets/rust/reqwest/fixtures/multipart-data.rs new file mode 100644 index 000000000..72644efce --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/multipart-data.rs @@ -0,0 +1,34 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + async fn file_to_part(file_name: &'static str) -> reqwest::multipart::Part { + let file = tokio::fs::File::open(file_name).await.unwrap(); + let stream = tokio_util::codec::FramedRead::new(file, tokio_util::codec::BytesCodec::new()); + let body = reqwest::Body::wrap_stream(stream); + reqwest::multipart::Part::stream(body) + .file_name(file_name) + .mime_str("text/plain").unwrap() + } + + let form = reqwest::multipart::Form::new() + .part("foo", file_to_part("hello.txt").await) + .text("bar", "Bonjour le monde"); + let mut headers = reqwest::header::HeaderMap::new(); + + let client = reqwest::Client::new(); + let response = client.post(url) + .multipart(form) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/multipart-file.rs b/src/targets/rust/reqwest/fixtures/multipart-file.rs new file mode 100644 index 000000000..fa1260c6e --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/multipart-file.rs @@ -0,0 +1,33 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + async fn file_to_part(file_name: &'static str) -> reqwest::multipart::Part { + let file = tokio::fs::File::open(file_name).await.unwrap(); + let stream = tokio_util::codec::FramedRead::new(file, tokio_util::codec::BytesCodec::new()); + let body = reqwest::Body::wrap_stream(stream); + reqwest::multipart::Part::stream(body) + .file_name(file_name) + .mime_str("text/plain").unwrap() + } + + let form = reqwest::multipart::Form::new() + .part("foo", file_to_part("test/fixtures/files/hello.txt").await); + let mut headers = reqwest::header::HeaderMap::new(); + + let client = reqwest::Client::new(); + let response = client.post(url) + .multipart(form) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/multipart-form-data-no-params.rs b/src/targets/rust/reqwest/fixtures/multipart-form-data-no-params.rs new file mode 100644 index 000000000..8cc2a5f0d --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/multipart-form-data-no-params.rs @@ -0,0 +1,24 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let form = reqwest::multipart::Form::new() + .text("", ""); + let mut headers = reqwest::header::HeaderMap::new(); + + let client = reqwest::Client::new(); + let response = client.post(url) + .multipart(form) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/multipart-form-data.rs b/src/targets/rust/reqwest/fixtures/multipart-form-data.rs new file mode 100644 index 000000000..f17bcb008 --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/multipart-form-data.rs @@ -0,0 +1,24 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let form = reqwest::multipart::Form::new() + .text("foo", "bar"); + let mut headers = reqwest::header::HeaderMap::new(); + + let client = reqwest::Client::new(); + let response = client.post(url) + .multipart(form) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/nested.rs b/src/targets/rust/reqwest/fixtures/nested.rs new file mode 100644 index 000000000..d0eec9b8f --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/nested.rs @@ -0,0 +1,25 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let querystring = [ + ("foo[bar]", "baz,zap"), + ("fiz", "buz"), + ("key", "value"), + ]; + + let client = reqwest::Client::new(); + let response = client.get(url) + .query(&querystring) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/query.rs b/src/targets/rust/reqwest/fixtures/query.rs new file mode 100644 index 000000000..3b715402d --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/query.rs @@ -0,0 +1,25 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let querystring = [ + ("foo", "bar,baz"), + ("baz", "abc"), + ("key", "value"), + ]; + + let client = reqwest::Client::new(); + let response = client.get(url) + .query(&querystring) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/short.rs b/src/targets/rust/reqwest/fixtures/short.rs new file mode 100644 index 000000000..886d61d45 --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/short.rs @@ -0,0 +1,18 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let client = reqwest::Client::new(); + let response = client.get(url) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/reqwest/fixtures/text-plain.rs b/src/targets/rust/reqwest/fixtures/text-plain.rs new file mode 100644 index 000000000..d23f14879 --- /dev/null +++ b/src/targets/rust/reqwest/fixtures/text-plain.rs @@ -0,0 +1,26 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let payload = "Hello World"; + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("content-type", "text/plain".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .body(payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} diff --git a/src/targets/rust/target.ts b/src/targets/rust/target.ts new file mode 100644 index 000000000..2b0ff4984 --- /dev/null +++ b/src/targets/rust/target.ts @@ -0,0 +1,14 @@ +import { Target } from '../targets'; +import { reqwest } from './reqwest/client'; + +export const rust: Target = { + info: { + key: 'rust', + title: 'Rust', + extname: '.rs', + default: 'reqwest', + }, + clientsById: { + reqwest, + }, +}; diff --git a/src/targets/targets.test.ts b/src/targets/targets.test.ts index bbd10748d..befb3c68c 100644 --- a/src/targets/targets.test.ts +++ b/src/targets/targets.test.ts @@ -4,7 +4,17 @@ import path from 'path'; import short from '../fixtures/requests/short.json'; import { availableTargets, extname } from '../helpers/utils'; import { HTTPSnippet, Request } from '../httpsnippet'; -import { addTarget, addTargetClient, Client, ClientId, isClient, isTarget, Target, TargetId, targets } from './targets'; +import { + addTarget, + addTargetClient, + Client, + ClientId, + isClient, + isTarget, + Target, + TargetId, + targets, +} from './targets'; const expectedBasePath = ['src', 'fixtures', 'requests']; diff --git a/src/targets/targets.ts b/src/targets/targets.ts index c2215d5ec..bba9eccd1 100644 --- a/src/targets/targets.ts +++ b/src/targets/targets.ts @@ -18,6 +18,7 @@ import { powershell } from './powershell/target'; import { python } from './python/target'; import { r } from './r/target'; import { ruby } from './ruby/target'; +import { rust } from './rust/target'; import { shell } from './shell/target'; import { swift } from './swift/target'; @@ -73,6 +74,7 @@ export const targets = { python, r, ruby, + rust, shell, swift, }; diff --git a/tsconfig.build.json b/tsconfig.build.json index c87a0e044..052744692 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -9,7 +9,7 @@ "downlevelIteration": true, "lib": ["ESNext"], "declaration": true, - "declarationMap": true, + "declarationMap": true }, "include": ["src"], "exclude": ["dist", "**/*.test.ts"] From bb81dca186934625ffe211167c5b4c7049448d7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 17:29:11 +0100 Subject: [PATCH 18/35] chore(deps-dev): bump ws from 7.5.7 to 7.5.10 (#358) Bumps [ws](https://github.com/websockets/ws) from 7.5.7 to 7.5.10. - [Release notes](https://github.com/websockets/ws/releases) - [Commits](https://github.com/websockets/ws/compare/7.5.7...7.5.10) --- updated-dependencies: - dependency-name: ws dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 289dab03d..90b85528d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5207,9 +5207,10 @@ } }, "node_modules/ws": { - "version": "7.5.7", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.3.0" }, @@ -8728,7 +8729,9 @@ } }, "ws": { - "version": "7.5.7", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, "requires": {} }, From b6b20213e7f313e903213f37bba44bcf4d9be677 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 17:29:47 +0100 Subject: [PATCH 19/35] chore(deps-dev): bump braces from 3.0.2 to 3.0.3 (#357) Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 90b85528d..bdef6f37d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1709,11 +1709,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, - "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2536,9 +2537,10 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2931,8 +2933,9 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -4854,8 +4857,9 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -6475,10 +6479,12 @@ } }, "braces": { - "version": "3.0.2", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browser-process-hrtime": { @@ -6987,7 +6993,9 @@ } }, "fill-range": { - "version": "7.0.1", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -7227,6 +7235,8 @@ }, "is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, "is-obj": { @@ -8519,6 +8529,8 @@ }, "to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { "is-number": "^7.0.0" From 893da8bde10ecc790ac3826b9bf60a92b1ea9ade Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 17:30:43 +0100 Subject: [PATCH 20/35] chore(deps-dev): bump @babel/traverse from 7.22.6 to 7.24.5 (#348) Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.22.6 to 7.24.5. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.24.5/packages/babel-traverse) --- updated-dependencies: - dependency-name: "@babel/traverse" dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 306 ++++++++++++++++++++++------------------------ 1 file changed, 148 insertions(+), 158 deletions(-) diff --git a/package-lock.json b/package-lock.json index bdef6f37d..6f47a2a4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -69,12 +69,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -120,14 +121,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz", - "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -169,22 +170,22 @@ "dev": true }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -254,30 +255,30 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", "dev": true, "engines": { "node": ">=6.9.0" @@ -307,14 +308,15 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", + "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.24.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -383,9 +385,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.6.tgz", - "integrity": "sha512-EIQu22vNkceq3LbjAq7knDf/UmtI2qbcNI8GRBlijez6TpQLvSodJPYfydQmNA5buwkxxxa/PVI44jjYZ+/cLw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -544,34 +546,34 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.6.tgz", - "integrity": "sha512-53CijMvKlLIDlOTrdWiHileRddlIiwUIyCKqYa7lYnnPldXCG5dUSN38uT0cA6i7rHWNKJLH0VU/Kxdr1GzB3w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.6", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -587,13 +589,13 @@ } }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -961,14 +963,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -984,9 +986,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" @@ -999,21 +1001,15 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, "node_modules/@nicolo-ribaudo/semver-v6": { "version": "6.3.3", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz", @@ -5312,12 +5308,13 @@ } }, "@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, "requires": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" } }, "@babel/compat-data": { @@ -5350,14 +5347,14 @@ } }, "@babel/generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz", - "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", "dev": true, "requires": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" } }, @@ -5392,19 +5389,19 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true }, "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { @@ -5455,24 +5452,24 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" } }, "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", "dev": true }, "@babel/helper-validator-option": { @@ -5493,14 +5490,15 @@ } }, "@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", + "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.24.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "dependencies": { "ansi-styles": { @@ -5556,9 +5554,9 @@ } }, "@babel/parser": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.6.tgz", - "integrity": "sha512-EIQu22vNkceq3LbjAq7knDf/UmtI2qbcNI8GRBlijez6TpQLvSodJPYfydQmNA5buwkxxxa/PVI44jjYZ+/cLw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -5653,31 +5651,31 @@ } }, "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" } }, "@babel/traverse": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.6.tgz", - "integrity": "sha512-53CijMvKlLIDlOTrdWiHileRddlIiwUIyCKqYa7lYnnPldXCG5dUSN38uT0cA6i7rHWNKJLH0VU/Kxdr1GzB3w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", "dev": true, "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.6", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", + "debug": "^4.3.1", "globals": "^11.1.0" }, "dependencies": { @@ -5688,13 +5686,13 @@ } }, "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", "to-fast-properties": "^2.0.0" } }, @@ -5979,14 +5977,14 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } }, "@jridgewell/resolve-uri": { @@ -5996,9 +5994,9 @@ "dev": true }, "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true }, "@jridgewell/sourcemap-codec": { @@ -6008,21 +6006,13 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - }, - "dependencies": { - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - } + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@nicolo-ribaudo/semver-v6": { From b9e1d7be8be1b2c79207b51e71c94aaf9a3c5908 Mon Sep 17 00:00:00 2001 From: Sunrise Date: Sat, 13 Jul 2024 01:21:46 +0800 Subject: [PATCH 21/35] Generate Crystal language code (#343) * Generate Crystal language code * Generate Crystal language code * Remove a blank line * fix crystal tests --------- Co-authored-by: Filipe Freire --- README.md | 2 +- package.json | 1 + src/helpers/__snapshots__/utils.test.ts.snap | 14 ++++ src/targets/crystal/native/client.test.ts | 18 +++++ src/targets/crystal/native/client.ts | 72 +++++++++++++++++++ .../fixtures/application-form-encoded.cr | 10 +++ .../native/fixtures/application-json.cr | 10 +++ .../crystal/native/fixtures/cookies.cr | 9 +++ .../crystal/native/fixtures/custom-method.cr | 6 ++ src/targets/crystal/native/fixtures/full.cr | 12 ++++ .../crystal/native/fixtures/headers.cr | 11 +++ src/targets/crystal/native/fixtures/https.cr | 6 ++ .../native/fixtures/insecure-skip-verify.cr | 6 ++ .../native/fixtures/jsonObj-multiline.cr | 10 +++ .../native/fixtures/jsonObj-null-value.cr | 10 +++ .../crystal/native/fixtures/multipart-data.cr | 10 +++ .../crystal/native/fixtures/multipart-file.cr | 10 +++ .../fixtures/multipart-form-data-no-params.cr | 9 +++ .../native/fixtures/multipart-form-data.cr | 10 +++ src/targets/crystal/native/fixtures/nested.cr | 6 ++ src/targets/crystal/native/fixtures/query.cr | 6 ++ src/targets/crystal/native/fixtures/short.cr | 6 ++ .../crystal/native/fixtures/text-plain.cr | 10 +++ src/targets/crystal/target.ts | 14 ++++ src/targets/targets.test.ts | 1 + src/targets/targets.ts | 2 + 26 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 src/targets/crystal/native/client.test.ts create mode 100644 src/targets/crystal/native/client.ts create mode 100644 src/targets/crystal/native/fixtures/application-form-encoded.cr create mode 100644 src/targets/crystal/native/fixtures/application-json.cr create mode 100644 src/targets/crystal/native/fixtures/cookies.cr create mode 100644 src/targets/crystal/native/fixtures/custom-method.cr create mode 100644 src/targets/crystal/native/fixtures/full.cr create mode 100644 src/targets/crystal/native/fixtures/headers.cr create mode 100644 src/targets/crystal/native/fixtures/https.cr create mode 100644 src/targets/crystal/native/fixtures/insecure-skip-verify.cr create mode 100644 src/targets/crystal/native/fixtures/jsonObj-multiline.cr create mode 100644 src/targets/crystal/native/fixtures/jsonObj-null-value.cr create mode 100644 src/targets/crystal/native/fixtures/multipart-data.cr create mode 100644 src/targets/crystal/native/fixtures/multipart-file.cr create mode 100644 src/targets/crystal/native/fixtures/multipart-form-data-no-params.cr create mode 100644 src/targets/crystal/native/fixtures/multipart-form-data.cr create mode 100644 src/targets/crystal/native/fixtures/nested.cr create mode 100644 src/targets/crystal/native/fixtures/query.cr create mode 100644 src/targets/crystal/native/fixtures/short.cr create mode 100644 src/targets/crystal/native/fixtures/text-plain.cr create mode 100644 src/targets/crystal/target.ts diff --git a/README.md b/README.md index d0c551b86..b3afc23ed 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![version][npm-version]][npm-url] [![License][npm-license]][license-url] -> HTTP Request snippet generator for _many_ languages & tools including: `cURL`, `HTTPie`, `JavaScript`, `Node`, `C`, `Java`, `PHP`, `Objective-C`, `Swift`, `Python`, `Ruby`, `C#`, `Go`, `OCaml` and [more](https://github.com/Kong/httpsnippet/wiki/Targets)! +> HTTP Request snippet generator for _many_ languages & tools including: `cURL`, `HTTPie`, `JavaScript`, `Node`, `C`, `Java`, `PHP`, `Objective-C`, `Swift`, `Python`, `Ruby`, `C#`, `Go`, `OCaml`, `Crystal` and [more](https://github.com/Kong/httpsnippet/wiki/Targets)! Relies on the popular [HAR](http://www.softwareishard.com/blog/har-12-spec/#request) format to import data and describe HTTP calls. diff --git a/package.json b/package.json index 2613b2b27..37fcc158f 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "keywords": [ "api", "clojure", + "crystal", "csharp", "curl", "go", diff --git a/src/helpers/__snapshots__/utils.test.ts.snap b/src/helpers/__snapshots__/utils.test.ts.snap index d8af8e024..8464d7bd4 100644 --- a/src/helpers/__snapshots__/utils.test.ts.snap +++ b/src/helpers/__snapshots__/utils.test.ts.snap @@ -30,6 +30,20 @@ Array [ "key": "clojure", "title": "Clojure", }, + Object { + "clients": Array [ + Object { + "description": "Crystal HTTP client", + "key": "native", + "link": "https://crystal-lang.org/api/master/HTTP/Client.html", + "title": "http::client", + }, + ], + "default": "native", + "extname": ".cr", + "key": "crystal", + "title": "Crystal", + }, Object { "clients": Array [ Object { diff --git a/src/targets/crystal/native/client.test.ts b/src/targets/crystal/native/client.test.ts new file mode 100644 index 000000000..f61a181f4 --- /dev/null +++ b/src/targets/crystal/native/client.test.ts @@ -0,0 +1,18 @@ +import https from '../../../fixtures/requests/https.json'; +import { runCustomFixtures } from '../../../fixtures/runCustomFixtures'; +import { Request } from '../../../httpsnippet'; + +runCustomFixtures({ + targetId: 'crystal', + clientId: 'native', + tests: [ + { + it: 'should support the insecureSkipVerify option', + input: https as Request, + options: { + insecureSkipVerify: true, + }, + expected: 'insecure-skip-verify.cr', + }, + ], +}); diff --git a/src/targets/crystal/native/client.ts b/src/targets/crystal/native/client.ts new file mode 100644 index 000000000..faba72c05 --- /dev/null +++ b/src/targets/crystal/native/client.ts @@ -0,0 +1,72 @@ +/** + * @description + * HTTP code snippet generator for native Crystal + * + * @author + * @18183883296 + * + * for any questions or issues regarding the generated code snippet, please open an issue mentioning the author. + */ +import { CodeBuilder } from '../../../helpers/code-builder'; +import { escapeForDoubleQuotes } from '../../../helpers/escape'; +import { Client } from '../../targets'; + +export interface CrystalNativeOptions { + insecureSkipVerify?: boolean; +} + +export const native: Client = { + info: { + key: 'native', + title: 'http::client', + link: 'https://crystal-lang.org/api/master/HTTP/Client.html', + description: 'Crystal HTTP client', + }, + convert: ({ method: rawMethod, fullUrl, postData, allHeaders }, options = {}) => { + const { insecureSkipVerify = false } = options; + + const { push, blank, join } = new CodeBuilder(); + + push('require "http/client"'); + + blank(); + + push(`url = "${fullUrl}"`); + + const headers = Object.keys(allHeaders); + if (headers.length) { + push('headers = HTTP::Headers{'); + headers.forEach(key => { + push(` "${key}" => "${escapeForDoubleQuotes(allHeaders[key])}"`); + }); + push('}'); + } + + if (postData.text) { + push(`reqBody = ${JSON.stringify(postData.text)}`); + } + + blank(); + + const method = rawMethod.toUpperCase(); + const methods = ['GET', 'POST', 'HEAD', 'DELETE', 'PATCH', 'PUT', 'OPTIONS']; + + const headersContext = headers.length ? ', headers: headers' : ''; + const bodyContext = postData.text ? ', body: reqBody' : ''; + const sslContext = insecureSkipVerify ? ', tls: OpenSSL::SSL::Context::Client.insecure' : ''; + + if (methods.includes(method)) { + push( + `response = HTTP::Client.${method.toLowerCase()} url${headersContext}${bodyContext}${sslContext}`, + ); + } else { + push( + `response = HTTP::Client.exec "${method}", url${headersContext}${bodyContext}${sslContext}`, + ); + } + + push('puts response.body'); + + return join(); + }, +}; diff --git a/src/targets/crystal/native/fixtures/application-form-encoded.cr b/src/targets/crystal/native/fixtures/application-form-encoded.cr new file mode 100644 index 000000000..1a88422b8 --- /dev/null +++ b/src/targets/crystal/native/fixtures/application-form-encoded.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "application/x-www-form-urlencoded" +} +reqBody = "foo=bar&hello=world" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/application-json.cr b/src/targets/crystal/native/fixtures/application-json.cr new file mode 100644 index 000000000..1389c2f94 --- /dev/null +++ b/src/targets/crystal/native/fixtures/application-json.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "application/json" +} +reqBody = "{\"number\":1,\"string\":\"f\\\"oo\",\"arr\":[1,2,3],\"nested\":{\"a\":\"b\"},\"arr_mix\":[1,\"a\",{\"arr_mix_nested\":{}}],\"boolean\":false}" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/cookies.cr b/src/targets/crystal/native/fixtures/cookies.cr new file mode 100644 index 000000000..70d45c129 --- /dev/null +++ b/src/targets/crystal/native/fixtures/cookies.cr @@ -0,0 +1,9 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "cookie" => "foo=bar; bar=baz" +} + +response = HTTP::Client.post url, headers: headers +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/custom-method.cr b/src/targets/crystal/native/fixtures/custom-method.cr new file mode 100644 index 000000000..ee1852bf0 --- /dev/null +++ b/src/targets/crystal/native/fixtures/custom-method.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "http://mockbin.com/har" + +response = HTTP::Client.exec "PROPFIND", url +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/full.cr b/src/targets/crystal/native/fixtures/full.cr new file mode 100644 index 000000000..edd8f4ce9 --- /dev/null +++ b/src/targets/crystal/native/fixtures/full.cr @@ -0,0 +1,12 @@ +require "http/client" + +url = "http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value" +headers = HTTP::Headers{ + "cookie" => "foo=bar; bar=baz" + "accept" => "application/json" + "content-type" => "application/x-www-form-urlencoded" +} +reqBody = "foo=bar" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/headers.cr b/src/targets/crystal/native/fixtures/headers.cr new file mode 100644 index 000000000..1061d33b3 --- /dev/null +++ b/src/targets/crystal/native/fixtures/headers.cr @@ -0,0 +1,11 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "accept" => "application/json" + "x-foo" => "Bar" + "quoted-value" => "\"quoted\" 'string'" +} + +response = HTTP::Client.get url, headers: headers +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/https.cr b/src/targets/crystal/native/fixtures/https.cr new file mode 100644 index 000000000..c9fa4fd60 --- /dev/null +++ b/src/targets/crystal/native/fixtures/https.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "https://mockbin.com/har" + +response = HTTP::Client.get url +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/insecure-skip-verify.cr b/src/targets/crystal/native/fixtures/insecure-skip-verify.cr new file mode 100644 index 000000000..3349fc844 --- /dev/null +++ b/src/targets/crystal/native/fixtures/insecure-skip-verify.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "https://mockbin.com/har" + +response = HTTP::Client.get url, tls: OpenSSL::SSL::Context::Client.insecure +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/jsonObj-multiline.cr b/src/targets/crystal/native/fixtures/jsonObj-multiline.cr new file mode 100644 index 000000000..12ce7198f --- /dev/null +++ b/src/targets/crystal/native/fixtures/jsonObj-multiline.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "application/json" +} +reqBody = "{\n \"foo\": \"bar\"\n}" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/jsonObj-null-value.cr b/src/targets/crystal/native/fixtures/jsonObj-null-value.cr new file mode 100644 index 000000000..053961c1c --- /dev/null +++ b/src/targets/crystal/native/fixtures/jsonObj-null-value.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "application/json" +} +reqBody = "{\"foo\":null}" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/multipart-data.cr b/src/targets/crystal/native/fixtures/multipart-data.cr new file mode 100644 index 000000000..72ace104d --- /dev/null +++ b/src/targets/crystal/native/fixtures/multipart-data.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "multipart/form-data; boundary=---011000010111000001101001" +} +reqBody = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\nHello World\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bar\"\r\n\r\nBonjour le monde\r\n-----011000010111000001101001--\r\n" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/multipart-file.cr b/src/targets/crystal/native/fixtures/multipart-file.cr new file mode 100644 index 000000000..1555da835 --- /dev/null +++ b/src/targets/crystal/native/fixtures/multipart-file.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "multipart/form-data; boundary=---011000010111000001101001" +} +reqBody = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\n\r\n-----011000010111000001101001--\r\n" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/multipart-form-data-no-params.cr b/src/targets/crystal/native/fixtures/multipart-form-data-no-params.cr new file mode 100644 index 000000000..3cbcc9c55 --- /dev/null +++ b/src/targets/crystal/native/fixtures/multipart-form-data-no-params.cr @@ -0,0 +1,9 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "Content-Type" => "multipart/form-data" +} + +response = HTTP::Client.post url, headers: headers +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/multipart-form-data.cr b/src/targets/crystal/native/fixtures/multipart-form-data.cr new file mode 100644 index 000000000..d5216d7d1 --- /dev/null +++ b/src/targets/crystal/native/fixtures/multipart-form-data.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "Content-Type" => "multipart/form-data; boundary=---011000010111000001101001" +} +reqBody = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n-----011000010111000001101001--\r\n" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/nested.cr b/src/targets/crystal/native/fixtures/nested.cr new file mode 100644 index 000000000..f6fbf4b39 --- /dev/null +++ b/src/targets/crystal/native/fixtures/nested.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "http://mockbin.com/har?foo%5Bbar%5D=baz%2Czap&fiz=buz&key=value" + +response = HTTP::Client.get url +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/query.cr b/src/targets/crystal/native/fixtures/query.cr new file mode 100644 index 000000000..cacc2b3db --- /dev/null +++ b/src/targets/crystal/native/fixtures/query.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value" + +response = HTTP::Client.get url +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/short.cr b/src/targets/crystal/native/fixtures/short.cr new file mode 100644 index 000000000..0715616d2 --- /dev/null +++ b/src/targets/crystal/native/fixtures/short.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "http://mockbin.com/har" + +response = HTTP::Client.get url +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/native/fixtures/text-plain.cr b/src/targets/crystal/native/fixtures/text-plain.cr new file mode 100644 index 000000000..8890116be --- /dev/null +++ b/src/targets/crystal/native/fixtures/text-plain.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "text/plain" +} +reqBody = "Hello World" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/src/targets/crystal/target.ts b/src/targets/crystal/target.ts new file mode 100644 index 000000000..f3714af57 --- /dev/null +++ b/src/targets/crystal/target.ts @@ -0,0 +1,14 @@ +import { Target } from '../targets'; +import { native } from './native/client'; + +export const crystal: Target = { + info: { + key: 'crystal', + title: 'Crystal', + extname: '.cr', + default: 'native', + }, + clientsById: { + native, + }, +}; diff --git a/src/targets/targets.test.ts b/src/targets/targets.test.ts index befb3c68c..48a969de4 100644 --- a/src/targets/targets.test.ts +++ b/src/targets/targets.test.ts @@ -84,6 +84,7 @@ availableTargets() expect(result).toStrictEqual(expected); }); } catch (error) { + console.error(error); throw new Error( `Missing a test file for ${targetId}:${clientId} for the ${fixture} fixture.\nExpected to find the output fixture: \`/src/targets/${targetId}/${clientId}/fixtures/${fixture}${fixtureExtension}\``, ); diff --git a/src/targets/targets.ts b/src/targets/targets.ts index bba9eccd1..7f9362d47 100644 --- a/src/targets/targets.ts +++ b/src/targets/targets.ts @@ -4,6 +4,7 @@ import { CodeBuilderOptions } from '../helpers/code-builder'; import { Request } from '../httpsnippet'; import { c } from './c/target'; import { clojure } from './clojure/target'; +import { crystal } from './crystal/target'; import { csharp } from './csharp/target'; import { go } from './go/target'; import { http } from './http/target'; @@ -60,6 +61,7 @@ export interface Target { export const targets = { c, clojure, + crystal, csharp, go, http, From e99422a58ea2d46024197c95cc61530d8e84fc2b Mon Sep 17 00:00:00 2001 From: Navdeep Singh Rathore <57226514+nsrCodes@users.noreply.github.com> Date: Fri, 12 Jul 2024 23:14:06 +0530 Subject: [PATCH 22/35] Fix setting default value of request.PostData of HarEntry (#323) * fix: prevent override of default value of request.postData when postData might be undefined * chore: optional chaining safety check for when request.PostData can be undefined --- src/httpsnippet.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/httpsnippet.ts b/src/httpsnippet.ts index 8d315a5cf..53171f136 100644 --- a/src/httpsnippet.ts +++ b/src/httpsnippet.ts @@ -100,10 +100,10 @@ export class HTTPSnippet { cookies: [], httpVersion: 'HTTP/1.1', queryString: [], - postData: { + ...request, + postData: request?.postData || { mimeType: request.postData?.mimeType || 'application/octet-stream', }, - ...request, }; if (validateHarRequest(req)) { @@ -164,7 +164,7 @@ export class HTTPSnippet { request.allHeaders.cookie = cookies.join('; '); } - switch (request.postData.mimeType) { + switch (request?.postData.mimeType) { case 'multipart/mixed': case 'multipart/related': case 'multipart/form-data': From 29947cc13b6f700949e18046ce31ccaf95a0dcc9 Mon Sep 17 00:00:00 2001 From: Boris Verkhovskiy Date: Fri, 12 Jul 2024 11:46:57 -0600 Subject: [PATCH 23/35] Support any method for PowerShell (#320) * Support any method for PowerShell * fix test --------- Co-authored-by: Filipe Freire --- src/targets/powershell/common.ts | 20 +++++++++++++------ .../restmethod/fixtures/custom-method.ps1 | 2 +- .../webrequest/fixtures/custom-method.ps1 | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/targets/powershell/common.ts b/src/targets/powershell/common.ts index 9cf395def..cca01e366 100644 --- a/src/targets/powershell/common.ts +++ b/src/targets/powershell/common.ts @@ -16,11 +16,19 @@ export const generatePowershellConvert = (command: PowershellCommand) => { allHeaders, }) => { const { push, join } = new CodeBuilder(); - const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']; - - if (!methods.includes(method.toUpperCase())) { - return 'Method not supported'; - } + const methods = [ + 'DEFAULT', + 'DELETE', + 'GET', + 'HEAD', + 'MERGE', + 'OPTIONS', + 'PATCH', + 'POST', + 'PUT', + 'TRACE' + ]; + const methodArg = methods.includes(method.toUpperCase()) ? '-Method' : '-CustomMethod'; const commandOptions = []; @@ -65,7 +73,7 @@ export const generatePowershellConvert = (command: PowershellCommand) => { commandOptions.push(`-Body '${postData.text}'`); } - push(`$response = ${command} -Uri '${fullUrl}' -Method ${method} ${commandOptions.join(' ')}`); + push(`$response = ${command} -Uri '${fullUrl}' ${methodArg} ${method} ${commandOptions.join(' ')}`); return join(); }; return convert; diff --git a/src/targets/powershell/restmethod/fixtures/custom-method.ps1 b/src/targets/powershell/restmethod/fixtures/custom-method.ps1 index 8eb41a680..114e893a4 100644 --- a/src/targets/powershell/restmethod/fixtures/custom-method.ps1 +++ b/src/targets/powershell/restmethod/fixtures/custom-method.ps1 @@ -1 +1 @@ -Method not supported \ No newline at end of file +$response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -CustomMethod PROPFIND \ No newline at end of file diff --git a/src/targets/powershell/webrequest/fixtures/custom-method.ps1 b/src/targets/powershell/webrequest/fixtures/custom-method.ps1 index 8eb41a680..5f587e405 100644 --- a/src/targets/powershell/webrequest/fixtures/custom-method.ps1 +++ b/src/targets/powershell/webrequest/fixtures/custom-method.ps1 @@ -1 +1 @@ -Method not supported \ No newline at end of file +$response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -CustomMethod PROPFIND \ No newline at end of file From 147eb9815b951686f6190b637458c217c843ad8b Mon Sep 17 00:00:00 2001 From: Brian Goad Date: Fri, 12 Jul 2024 13:49:37 -0400 Subject: [PATCH 24/35] chore: add nvmrc and set it to 20 (#262) * Add nvmrc and set it to 14.9 as per https://github.com/Kong/httpsnippet/pull/248 * Use node 18 * bump to node 20 on nvmrc file --------- Co-authored-by: Filipe Freire --- .nvmrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 .nvmrc diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..209e3ef4b --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20 From 8739d73b3c3f8112aebfa54c55caa8355b1d1abd Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 12 Jul 2024 18:50:15 +0100 Subject: [PATCH 25/35] Add generator for Ruby's Faraday client (#362) Co-authored-by: Lukas_Skywalker --- src/helpers/__snapshots__/utils.test.ts.snap | 6 + src/targets/ruby/faraday/client.ts | 107 ++++++++++++++++++ .../fixtures/application-form-encoded.rb | 18 +++ .../ruby/faraday/fixtures/application-json.rb | 13 +++ src/targets/ruby/faraday/fixtures/cookies.rb | 12 ++ .../ruby/faraday/fixtures/custom-method.rb | 1 + src/targets/ruby/faraday/fixtures/full.rb | 22 ++++ src/targets/ruby/faraday/fixtures/headers.rb | 14 +++ src/targets/ruby/faraday/fixtures/https.rb | 11 ++ .../faraday/fixtures/jsonObj-multiline.rb | 13 +++ .../faraday/fixtures/jsonObj-null-value.rb | 13 +++ .../ruby/faraday/fixtures/multipart-data.rb | 13 +++ .../ruby/faraday/fixtures/multipart-file.rb | 13 +++ .../fixtures/multipart-form-data-no-params.rb | 12 ++ .../faraday/fixtures/multipart-form-data.rb | 13 +++ src/targets/ruby/faraday/fixtures/nested.rb | 14 +++ src/targets/ruby/faraday/fixtures/query.rb | 14 +++ src/targets/ruby/faraday/fixtures/short.rb | 11 ++ .../ruby/faraday/fixtures/text-plain.rb | 13 +++ src/targets/ruby/target.ts | 2 + 20 files changed, 335 insertions(+) create mode 100644 src/targets/ruby/faraday/client.ts create mode 100644 src/targets/ruby/faraday/fixtures/application-form-encoded.rb create mode 100644 src/targets/ruby/faraday/fixtures/application-json.rb create mode 100644 src/targets/ruby/faraday/fixtures/cookies.rb create mode 100644 src/targets/ruby/faraday/fixtures/custom-method.rb create mode 100644 src/targets/ruby/faraday/fixtures/full.rb create mode 100644 src/targets/ruby/faraday/fixtures/headers.rb create mode 100644 src/targets/ruby/faraday/fixtures/https.rb create mode 100644 src/targets/ruby/faraday/fixtures/jsonObj-multiline.rb create mode 100644 src/targets/ruby/faraday/fixtures/jsonObj-null-value.rb create mode 100644 src/targets/ruby/faraday/fixtures/multipart-data.rb create mode 100644 src/targets/ruby/faraday/fixtures/multipart-file.rb create mode 100644 src/targets/ruby/faraday/fixtures/multipart-form-data-no-params.rb create mode 100644 src/targets/ruby/faraday/fixtures/multipart-form-data.rb create mode 100644 src/targets/ruby/faraday/fixtures/nested.rb create mode 100644 src/targets/ruby/faraday/fixtures/query.rb create mode 100644 src/targets/ruby/faraday/fixtures/short.rb create mode 100644 src/targets/ruby/faraday/fixtures/text-plain.rb diff --git a/src/helpers/__snapshots__/utils.test.ts.snap b/src/helpers/__snapshots__/utils.test.ts.snap index 8464d7bd4..6ba3a2d28 100644 --- a/src/helpers/__snapshots__/utils.test.ts.snap +++ b/src/helpers/__snapshots__/utils.test.ts.snap @@ -330,6 +330,12 @@ Array [ "link": "http://ruby-doc.org/stdlib-2.2.1/libdoc/net/http/rdoc/Net/HTTP.html", "title": "net::http", }, + Object { + "description": "Faraday HTTP client", + "key": "faraday", + "link": "https://github.com/lostisland/faraday", + "title": "faraday", + }, ], "default": "native", "extname": ".rb", diff --git a/src/targets/ruby/faraday/client.ts b/src/targets/ruby/faraday/client.ts new file mode 100644 index 000000000..e8e259a4e --- /dev/null +++ b/src/targets/ruby/faraday/client.ts @@ -0,0 +1,107 @@ +import { CodeBuilder } from '../../../helpers/code-builder'; +import { escapeForSingleQuotes } from '../../../helpers/escape'; +import { Client } from '../../targets'; + +export const faraday: Client = { + info: { + key: 'faraday', + title: 'faraday', + link: 'https://github.com/lostisland/faraday', + description: 'Faraday HTTP client', + }, + convert: ({ uriObj, queryObj, method: rawMethod, fullUrl, postData, allHeaders }, options = {}) => { + const { push, blank, join } = new CodeBuilder(); + + // To support custom methods we check for the supported methods + // and if doesn't exist then we build a custom class for it + const method = rawMethod.toUpperCase(); + const methods = [ + 'GET', + 'POST', + 'HEAD', + 'DELETE', + 'PATCH', + 'PUT', + 'OPTIONS', + 'COPY', + 'LOCK', + 'UNLOCK', + 'MOVE', + 'TRACE', + ]; + + if(!methods.includes(method)) { + push(`# Faraday cannot currently run ${method} requests. Please use another client.`) + return join(); + } + + push("require 'faraday'"); + blank(); + + // Write body to beginning of script + if(postData.mimeType === 'application/x-www-form-urlencoded') { + if (postData.params) { + push(`data = {`); + postData.params.forEach(param => { + push(` :${param.name} => ${JSON.stringify(param.value)},`); + }); + push(`}`); + blank(); + } + } + + push(`conn = Faraday.new(`); + push(` url: '${uriObj.protocol}//${uriObj.host}',`); + if(allHeaders['content-type'] || allHeaders['Content-Type']) { + push(` headers: {'Content-Type' => '${allHeaders['content-type'] || allHeaders['Content-Type']}'}`); + } + push(`)`); + + blank(); + push(`response = conn.${method.toLowerCase()}('${uriObj.pathname}') do |req|`); + + const headers = Object.keys(allHeaders); + if (headers.length) { + headers.forEach(key => { + if(key.toLowerCase() !== 'content-type') { + push(` req.headers['${key}'] = '${escapeForSingleQuotes(allHeaders[key])}'`); + } + }); + } + + Object.keys(queryObj).forEach(name => { + const value = queryObj[name]; + if (Array.isArray(value)) { + push(` req.params['${name}'] = ${JSON.stringify(value)}`) + } else { + push(` req.params['${name}'] = '${value}'`) + } + }); + + switch (postData.mimeType) { + case 'application/x-www-form-urlencoded': + if (postData.params) { + push(` req.body = URI.encode_www_form(data)`); + } + break; + + case 'application/json': + if (postData.jsonObj) { + push(` req.body = ${JSON.stringify(postData.text)}`); + } + break; + + default: + if (postData.text) { + push(` req.body = ${JSON.stringify(postData.text)}`); + } + } + + push('end'); + blank() + push('puts response.status'); + push('puts response.body'); + + return join(); + }, +}; diff --git a/src/targets/ruby/faraday/fixtures/application-form-encoded.rb b/src/targets/ruby/faraday/fixtures/application-form-encoded.rb new file mode 100644 index 000000000..9f15c8afa --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/application-form-encoded.rb @@ -0,0 +1,18 @@ +require 'faraday' + +data = { + :foo => "bar", + :hello => "world", +} + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'application/x-www-form-urlencoded'} +) + +response = conn.post('/har') do |req| + req.body = URI.encode_www_form(data) +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/application-json.rb b/src/targets/ruby/faraday/fixtures/application-json.rb new file mode 100644 index 000000000..2c22a0eb2 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/application-json.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'application/json'} +) + +response = conn.post('/har') do |req| + req.body = "{\"number\":1,\"string\":\"f\\\"oo\",\"arr\":[1,2,3],\"nested\":{\"a\":\"b\"},\"arr_mix\":[1,\"a\",{\"arr_mix_nested\":{}}],\"boolean\":false}" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/cookies.rb b/src/targets/ruby/faraday/fixtures/cookies.rb new file mode 100644 index 000000000..5c884d73f --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/cookies.rb @@ -0,0 +1,12 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.post('/har') do |req| + req.headers['cookie'] = 'foo=bar; bar=baz' +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/custom-method.rb b/src/targets/ruby/faraday/fixtures/custom-method.rb new file mode 100644 index 000000000..213ada538 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/custom-method.rb @@ -0,0 +1 @@ +# Faraday cannot currently run PROPFIND requests. Please use another client. \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/full.rb b/src/targets/ruby/faraday/fixtures/full.rb new file mode 100644 index 000000000..00cf3c6a4 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/full.rb @@ -0,0 +1,22 @@ +require 'faraday' + +data = { + :foo => "bar", +} + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'application/x-www-form-urlencoded'} +) + +response = conn.post('/har') do |req| + req.headers['cookie'] = 'foo=bar; bar=baz' + req.headers['accept'] = 'application/json' + req.params['foo'] = ["bar","baz"] + req.params['baz'] = 'abc' + req.params['key'] = 'value' + req.body = URI.encode_www_form(data) +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/headers.rb b/src/targets/ruby/faraday/fixtures/headers.rb new file mode 100644 index 000000000..efaaa37a7 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/headers.rb @@ -0,0 +1,14 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.get('/har') do |req| + req.headers['accept'] = 'application/json' + req.headers['x-foo'] = 'Bar' + req.headers['quoted-value'] = '"quoted" \'string\'' +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/https.rb b/src/targets/ruby/faraday/fixtures/https.rb new file mode 100644 index 000000000..841613679 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/https.rb @@ -0,0 +1,11 @@ +require 'faraday' + +conn = Faraday.new( + url: 'https://mockbin.com', +) + +response = conn.get('/har') do |req| +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/jsonObj-multiline.rb b/src/targets/ruby/faraday/fixtures/jsonObj-multiline.rb new file mode 100644 index 000000000..e6e66b0da --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/jsonObj-multiline.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'application/json'} +) + +response = conn.post('/har') do |req| + req.body = "{\n \"foo\": \"bar\"\n}" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/jsonObj-null-value.rb b/src/targets/ruby/faraday/fixtures/jsonObj-null-value.rb new file mode 100644 index 000000000..d2ecc57a0 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/jsonObj-null-value.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'application/json'} +) + +response = conn.post('/har') do |req| + req.body = "{\"foo\":null}" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/multipart-data.rb b/src/targets/ruby/faraday/fixtures/multipart-data.rb new file mode 100644 index 000000000..5dd46a568 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/multipart-data.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'multipart/form-data; boundary=---011000010111000001101001'} +) + +response = conn.post('/har') do |req| + req.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\nHello World\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bar\"\r\n\r\nBonjour le monde\r\n-----011000010111000001101001--\r\n" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/multipart-file.rb b/src/targets/ruby/faraday/fixtures/multipart-file.rb new file mode 100644 index 000000000..4d7168969 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/multipart-file.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'multipart/form-data; boundary=---011000010111000001101001'} +) + +response = conn.post('/har') do |req| + req.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\n\r\n-----011000010111000001101001--\r\n" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/multipart-form-data-no-params.rb b/src/targets/ruby/faraday/fixtures/multipart-form-data-no-params.rb new file mode 100644 index 000000000..fc40bcef7 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/multipart-form-data-no-params.rb @@ -0,0 +1,12 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'multipart/form-data'} +) + +response = conn.post('/har') do |req| +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/multipart-form-data.rb b/src/targets/ruby/faraday/fixtures/multipart-form-data.rb new file mode 100644 index 000000000..fe3e14467 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/multipart-form-data.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'multipart/form-data; boundary=---011000010111000001101001'} +) + +response = conn.post('/har') do |req| + req.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n-----011000010111000001101001--\r\n" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/nested.rb b/src/targets/ruby/faraday/fixtures/nested.rb new file mode 100644 index 000000000..1a6966d20 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/nested.rb @@ -0,0 +1,14 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.get('/har') do |req| + req.params['foo[bar]'] = 'baz,zap' + req.params['fiz'] = 'buz' + req.params['key'] = 'value' +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/query.rb b/src/targets/ruby/faraday/fixtures/query.rb new file mode 100644 index 000000000..c418c5542 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/query.rb @@ -0,0 +1,14 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.get('/har') do |req| + req.params['foo'] = ["bar","baz"] + req.params['baz'] = 'abc' + req.params['key'] = 'value' +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/short.rb b/src/targets/ruby/faraday/fixtures/short.rb new file mode 100644 index 000000000..8ce34f785 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/short.rb @@ -0,0 +1,11 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.get('/har') do |req| +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/faraday/fixtures/text-plain.rb b/src/targets/ruby/faraday/fixtures/text-plain.rb new file mode 100644 index 000000000..b253cc378 --- /dev/null +++ b/src/targets/ruby/faraday/fixtures/text-plain.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'text/plain'} +) + +response = conn.post('/har') do |req| + req.body = "Hello World" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/src/targets/ruby/target.ts b/src/targets/ruby/target.ts index 7d2e51411..7550bc650 100644 --- a/src/targets/ruby/target.ts +++ b/src/targets/ruby/target.ts @@ -1,5 +1,6 @@ import { Target } from '../targets'; import { native } from './native/client'; +import { faraday } from './faraday/client'; export const ruby: Target = { info: { @@ -10,5 +11,6 @@ export const ruby: Target = { }, clientsById: { native, + faraday }, }; From fbd23b56d9065d88476c9585dc4a7fd77ab59edd Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 12 Jul 2024 18:03:15 +0000 Subject: [PATCH 26/35] 3.0.5 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6f47a2a4c..b9192be2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "httpsnippet", - "version": "3.0.4", + "version": "3.0.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "httpsnippet", - "version": "3.0.4", + "version": "3.0.5", "license": "MIT", "dependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index 37fcc158f..1d728fee9 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "3.0.4", + "version": "3.0.5", "name": "httpsnippet", "description": "HTTP Request snippet generator for *most* languages", "author": "Kong ", From 6a758d64cb3e4b9c7d2e4382817ccffc5d3f099a Mon Sep 17 00:00:00 2001 From: Dimitri Mitropoulos Date: Fri, 12 Jul 2024 14:10:02 -0400 Subject: [PATCH 27/35] Prep for Release: source maps, types, prettier (#301) * updates library exports * fixes lint configuration so that it actually fails now, as intended * tidy up --------- Co-authored-by: Filipe Freire --- package.json | 12 ++++++++---- src/httpsnippet.ts | 4 ++-- src/index.ts | 28 ++++++++++++++++++++++++++++ src/targets/powershell/common.ts | 6 ++++-- src/targets/ruby/faraday/client.ts | 24 ++++++++++++++---------- src/targets/ruby/target.ts | 4 ++-- tsconfig.build.json | 15 ++++++++------- 7 files changed, 66 insertions(+), 27 deletions(-) create mode 100644 src/index.ts diff --git a/package.json b/package.json index 1d728fee9..e395e6f22 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "author": "Kong ", "homepage": "https://github.com/Kong/httpsnippet", "license": "MIT", - "main": "dist/httpsnippet.js", - "types": "dist/httpsnippet.d.ts", + "main": "dist/index.js", + "types": "dist/index.d.ts", "bin": "bin/httpsnippet", "keywords": [ "api", @@ -51,9 +51,13 @@ "clean": "tsc --build tsconfig.build.json --clean", "prebuild": "npm run clean", "lint": "npm run lint:prettify && npm run lint:code && npm run lint:markdown", - "lint:prettify": "prettier --write .", - "lint:code": "eslint . --ext ts,d.ts,test.ts --fix", + "lint:prettify": "prettier --check .", + "lint:code": "eslint . --ext ts,d.ts,test.ts", "lint:markdown": "markdownlint-cli2 \"**/*.md\" \"#**/node_modules\"", + "lint:fix": "npm run lint:prettify:fix && npm run lint:code:fix && npm run lint:markdown:fix", + "lint:prettify:fix": "prettier --write .", + "lint:code:fix": "eslint . --ext ts,d.ts,test.ts --fix", + "lint:markdown:fix": "markdownlint-cli2-fix \"**/*.md\" \"#**/node_modules\"", "build": "tsc --build tsconfig.build.json", "build:types": "tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly", "test": "jest" diff --git a/src/httpsnippet.ts b/src/httpsnippet.ts index 53171f136..8cb5ccd75 100644 --- a/src/httpsnippet.ts +++ b/src/httpsnippet.ts @@ -53,7 +53,7 @@ interface Entry { request: Partial; } -interface HarEntry { +export interface HarEntry { log: { version: string; creator: { @@ -64,7 +64,7 @@ interface HarEntry { }; } -const isHarEntry = (value: any): value is HarEntry => +export const isHarEntry = (value: any): value is HarEntry => typeof value === 'object' && 'log' in value && typeof value.log === 'object' && diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 000000000..3a865a770 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,28 @@ +export { CodeBuilder, CodeBuilderOptions, PostProcessor } from './helpers/code-builder'; +export { EscapeOptions, escapeString } from './helpers/escape'; +export { HARError, validateHarRequest } from './helpers/har-validator'; +export { getHeader, getHeaderName } from './helpers/headers'; +export { AvailableTarget, availableTargets, extname } from './helpers/utils'; +export { + HarEntry, + HarRequest, + HTTPSnippet, + isHarEntry, + Request, + RequestExtras, +} from './httpsnippet'; +export { + addTarget, + addTargetClient, + Client, + ClientId, + ClientInfo, + Converter, + Extension, + isClient, + isTarget, + Target, + TargetId, + TargetInfo, + targets, +} from './targets/targets'; diff --git a/src/targets/powershell/common.ts b/src/targets/powershell/common.ts index cca01e366..4c3b923a2 100644 --- a/src/targets/powershell/common.ts +++ b/src/targets/powershell/common.ts @@ -26,7 +26,7 @@ export const generatePowershellConvert = (command: PowershellCommand) => { 'PATCH', 'POST', 'PUT', - 'TRACE' + 'TRACE', ]; const methodArg = methods.includes(method.toUpperCase()) ? '-Method' : '-CustomMethod'; @@ -73,7 +73,9 @@ export const generatePowershellConvert = (command: PowershellCommand) => { commandOptions.push(`-Body '${postData.text}'`); } - push(`$response = ${command} -Uri '${fullUrl}' ${methodArg} ${method} ${commandOptions.join(' ')}`); + push( + `$response = ${command} -Uri '${fullUrl}' ${methodArg} ${method} ${commandOptions.join(' ')}`, + ); return join(); }; return convert; diff --git a/src/targets/ruby/faraday/client.ts b/src/targets/ruby/faraday/client.ts index e8e259a4e..493a2d3fc 100644 --- a/src/targets/ruby/faraday/client.ts +++ b/src/targets/ruby/faraday/client.ts @@ -9,7 +9,7 @@ export const faraday: Client = { link: 'https://github.com/lostisland/faraday', description: 'Faraday HTTP client', }, - convert: ({ uriObj, queryObj, method: rawMethod, fullUrl, postData, allHeaders }, options = {}) => { + convert: ({ uriObj, queryObj, method: rawMethod, postData, allHeaders }) => { const { push, blank, join } = new CodeBuilder(); // To support custom methods we check for the supported methods @@ -30,8 +30,8 @@ export const faraday: Client = { 'TRACE', ]; - if(!methods.includes(method)) { - push(`# Faraday cannot currently run ${method} requests. Please use another client.`) + if (!methods.includes(method)) { + push(`# Faraday cannot currently run ${method} requests. Please use another client.`); return join(); } @@ -39,7 +39,7 @@ export const faraday: Client = { blank(); // Write body to beginning of script - if(postData.mimeType === 'application/x-www-form-urlencoded') { + if (postData.mimeType === 'application/x-www-form-urlencoded') { if (postData.params) { push(`data = {`); postData.params.forEach(param => { @@ -52,8 +52,12 @@ export const faraday: Client = { push(`conn = Faraday.new(`); push(` url: '${uriObj.protocol}//${uriObj.host}',`); - if(allHeaders['content-type'] || allHeaders['Content-Type']) { - push(` headers: {'Content-Type' => '${allHeaders['content-type'] || allHeaders['Content-Type']}'}`); + if (allHeaders['content-type'] || allHeaders['Content-Type']) { + push( + ` headers: {'Content-Type' => '${ + allHeaders['content-type'] || allHeaders['Content-Type'] + }'}`, + ); } push(`)`); @@ -63,7 +67,7 @@ export const faraday: Client = { const headers = Object.keys(allHeaders); if (headers.length) { headers.forEach(key => { - if(key.toLowerCase() !== 'content-type') { + if (key.toLowerCase() !== 'content-type') { push(` req.headers['${key}'] = '${escapeForSingleQuotes(allHeaders[key])}'`); } }); @@ -72,9 +76,9 @@ export const faraday: Client = { Object.keys(queryObj).forEach(name => { const value = queryObj[name]; if (Array.isArray(value)) { - push(` req.params['${name}'] = ${JSON.stringify(value)}`) + push(` req.params['${name}'] = ${JSON.stringify(value)}`); } else { - push(` req.params['${name}'] = '${value}'`) + push(` req.params['${name}'] = '${value}'`); } }); @@ -98,7 +102,7 @@ export const faraday: Client = { } push('end'); - blank() + blank(); push('puts response.status'); push('puts response.body'); diff --git a/src/targets/ruby/target.ts b/src/targets/ruby/target.ts index 7550bc650..247c75720 100644 --- a/src/targets/ruby/target.ts +++ b/src/targets/ruby/target.ts @@ -1,6 +1,6 @@ import { Target } from '../targets'; -import { native } from './native/client'; import { faraday } from './faraday/client'; +import { native } from './native/client'; export const ruby: Target = { info: { @@ -11,6 +11,6 @@ export const ruby: Target = { }, clientsById: { native, - faraday + faraday, }, }; diff --git a/tsconfig.build.json b/tsconfig.build.json index 052744692..a25f17e4f 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,15 +1,16 @@ { "compilerOptions": { - "outDir": "dist", - "rootDir": "src", "allowJs": true, - "resolveJsonModule": true, - "strict": true, - "esModuleInterop": true, + "declaration": true, + "declarationMap": true, "downlevelIteration": true, "lib": ["ESNext"], - "declaration": true, - "declarationMap": true + "esModuleInterop": true, + "outDir": "dist", + "resolveJsonModule": true, + "rootDir": "src", + "sourceMap": true, + "strict": true }, "include": ["src"], "exclude": ["dist", "**/*.test.ts"] From 723581e1daeb94c5d2f59044ee6d26ab2fbb8435 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Fri, 12 Jul 2024 18:11:19 +0000 Subject: [PATCH 28/35] 3.0.6 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b9192be2b..63aab7397 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "httpsnippet", - "version": "3.0.5", + "version": "3.0.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "httpsnippet", - "version": "3.0.5", + "version": "3.0.6", "license": "MIT", "dependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index e395e6f22..f433d8226 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "3.0.5", + "version": "3.0.6", "name": "httpsnippet", "description": "HTTP Request snippet generator for *most* languages", "author": "Kong ", From 08aec7bbd10f64a469f31b0d0b7ad121cedd8d04 Mon Sep 17 00:00:00 2001 From: Vaibhav Raj Singh Date: Tue, 1 Oct 2024 00:27:53 +0530 Subject: [PATCH 29/35] feat: replace ajv usage [INS-145] (#371) * Feat: replace custom har-validator with hard-validator-compiled package * test(http-snippet): update casing * fix: linting --- package-lock.json | 19 ++++++++++--------- package.json | 2 +- src/helpers/har-validator.ts | 31 ------------------------------- src/httpsnippet.test.ts | 2 +- src/httpsnippet.ts | 4 ++-- src/index.ts | 1 - src/targets/har-schema.d.ts | 4 ---- 7 files changed, 14 insertions(+), 49 deletions(-) delete mode 100644 src/helpers/har-validator.ts delete mode 100644 src/targets/har-schema.d.ts diff --git a/package-lock.json b/package-lock.json index 63aab7397..a0ac4be52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "chalk": "^4.1.2", "event-stream": "4.0.1", "form-data": "4.0.0", - "har-schema": "^2.0.0", + "har-validator-compiled": "^1.0.0", "stringify-object": "3.3.0", "yargs": "^17.4.0" }, @@ -2721,12 +2721,11 @@ "dev": true, "license": "ISC" }, - "node_modules/har-schema": { - "version": "2.0.0", - "license": "ISC", - "engines": { - "node": ">=4" - } + "node_modules/har-validator-compiled": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/har-validator-compiled/-/har-validator-compiled-1.0.0.tgz", + "integrity": "sha512-dher7nFSx+Ef6OoqVveLClh8itAR3vd8Qx70Lh/hEgP1iGeARAolbci7Y8JBrHIYgFCT6xRdvvL16AR9Zh07Dw==", + "license": "MIT" }, "node_modules/has": { "version": "1.0.3", @@ -7100,8 +7099,10 @@ "version": "4.2.9", "dev": true }, - "har-schema": { - "version": "2.0.0" + "har-validator-compiled": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/har-validator-compiled/-/har-validator-compiled-1.0.0.tgz", + "integrity": "sha512-dher7nFSx+Ef6OoqVveLClh8itAR3vd8Qx70Lh/hEgP1iGeARAolbci7Y8JBrHIYgFCT6xRdvvL16AR9Zh07Dw==" }, "has": { "version": "1.0.3", diff --git a/package.json b/package.json index f433d8226..6bbf6a750 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "chalk": "^4.1.2", "event-stream": "4.0.1", "form-data": "4.0.0", - "har-schema": "^2.0.0", + "har-validator-compiled": "^1.0.0", "stringify-object": "3.3.0", "yargs": "^17.4.0" } diff --git a/src/helpers/har-validator.ts b/src/helpers/har-validator.ts deleted file mode 100644 index 45d802717..000000000 --- a/src/helpers/har-validator.ts +++ /dev/null @@ -1,31 +0,0 @@ -import Ajv, { ErrorObject } from 'ajv'; -import { Request } from 'har-format'; -import * as schema from 'har-schema'; - -export class HARError extends Error { - name = 'HARError'; - message = 'validation failed'; - errors: ErrorObject[] = []; - constructor(errors: ErrorObject[]) { - super(); - this.errors = errors; - Error.captureStackTrace(this, this.constructor); - } -} - -const ajv = new Ajv({ - allErrors: true, -}); -ajv.addSchema(schema); - -export const validateHarRequest = (request: any): request is Request => { - const validate = ajv.getSchema('request.json'); - if (!validate) { - throw new Error('failed to find HAR request schema'); - } - const valid = validate(request); - if (!valid && validate.errors) { - throw new HARError(validate.errors); - } - return true; -}; diff --git a/src/httpsnippet.test.ts b/src/httpsnippet.test.ts index c945d6cd7..5eab435f5 100644 --- a/src/httpsnippet.test.ts +++ b/src/httpsnippet.test.ts @@ -19,7 +19,7 @@ describe('hTTPSnippet', () => { // @ts-expect-error intentionally incorrect const attempt = () => new HTTPSnippet({ ziltoid: 'the omniscient' }); - expect(attempt).toThrow('validation failed'); + expect(attempt).toThrow('Validation Failed'); }); it('should parse HAR file with multiple entries', () => { diff --git a/src/httpsnippet.ts b/src/httpsnippet.ts index 8cb5ccd75..0722c8842 100644 --- a/src/httpsnippet.ts +++ b/src/httpsnippet.ts @@ -1,11 +1,11 @@ import { map as eventStreamMap } from 'event-stream'; import FormData from 'form-data'; import { Param, PostDataCommon, Request as NpmHarRequest } from 'har-format'; +import { validateRequest } from 'har-validator-compiled'; import { stringify as queryStringify } from 'querystring'; import { format as urlFormat, parse as urlParse, UrlWithParsedQuery } from 'url'; import { formDataIterator, isBlob } from './helpers/form-data'; -import { validateHarRequest } from './helpers/har-validator'; import { getHeaderName } from './helpers/headers'; import { ReducedHelperObject, reducer } from './helpers/reducer'; import { ClientId, TargetId, targets } from './targets/targets'; @@ -106,7 +106,7 @@ export class HTTPSnippet { }, }; - if (validateHarRequest(req)) { + if (validateRequest(req)) { this.requests.push(this.prepare(req)); } }); diff --git a/src/index.ts b/src/index.ts index 3a865a770..9b3bf4544 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,5 @@ export { CodeBuilder, CodeBuilderOptions, PostProcessor } from './helpers/code-builder'; export { EscapeOptions, escapeString } from './helpers/escape'; -export { HARError, validateHarRequest } from './helpers/har-validator'; export { getHeader, getHeaderName } from './helpers/headers'; export { AvailableTarget, availableTargets, extname } from './helpers/utils'; export { diff --git a/src/targets/har-schema.d.ts b/src/targets/har-schema.d.ts deleted file mode 100644 index 1df95659e..000000000 --- a/src/targets/har-schema.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module 'har-schema' { - const schema: object; - export default schema; -} From 889ef62970046ff22597607bf05f5b919cce302c Mon Sep 17 00:00:00 2001 From: Filipe Freire <11976836+filfreire@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:19:57 +0000 Subject: [PATCH 30/35] 3.0.7 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a0ac4be52..bba29bdc7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "httpsnippet", - "version": "3.0.6", + "version": "3.0.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "httpsnippet", - "version": "3.0.6", + "version": "3.0.7", "license": "MIT", "dependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index 6bbf6a750..647b2195b 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "3.0.6", + "version": "3.0.7", "name": "httpsnippet", "description": "HTTP Request snippet generator for *most* languages", "author": "Kong ", From d10747920576122da0adcd27251d856a437b67ed Mon Sep 17 00:00:00 2001 From: Michael Welch Date: Tue, 1 Oct 2024 09:31:55 +0000 Subject: [PATCH 31/35] correct the casing of Method enums in RestSharp snippets (#366) Ensure that code snippets use enum members that are pascal cased and not upper cased. For example use `Method.Get` instead of `Method.GET` to ensure the snippets can compile. fixes #365 use `var` for return "type" of RestSharp request response The type `IRestResponse` doesn't exist in latest client (version 112) fixes #367 --- src/targets/csharp/restsharp/client.ts | 11 +++++++++-- .../restsharp/fixtures/application-form-encoded.cs | 4 ++-- .../csharp/restsharp/fixtures/application-json.cs | 4 ++-- src/targets/csharp/restsharp/fixtures/cookies.cs | 4 ++-- src/targets/csharp/restsharp/fixtures/full.cs | 4 ++-- src/targets/csharp/restsharp/fixtures/headers.cs | 4 ++-- src/targets/csharp/restsharp/fixtures/https.cs | 4 ++-- .../csharp/restsharp/fixtures/jsonObj-multiline.cs | 4 ++-- .../csharp/restsharp/fixtures/jsonObj-null-value.cs | 4 ++-- .../csharp/restsharp/fixtures/multipart-data.cs | 4 ++-- .../csharp/restsharp/fixtures/multipart-file.cs | 4 ++-- .../fixtures/multipart-form-data-no-params.cs | 4 ++-- .../csharp/restsharp/fixtures/multipart-form-data.cs | 4 ++-- src/targets/csharp/restsharp/fixtures/nested.cs | 4 ++-- src/targets/csharp/restsharp/fixtures/query.cs | 4 ++-- src/targets/csharp/restsharp/fixtures/short.cs | 4 ++-- src/targets/csharp/restsharp/fixtures/text-plain.cs | 4 ++-- 17 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/targets/csharp/restsharp/client.ts b/src/targets/csharp/restsharp/client.ts index 15f2a6e83..c37df19cb 100644 --- a/src/targets/csharp/restsharp/client.ts +++ b/src/targets/csharp/restsharp/client.ts @@ -20,8 +20,15 @@ export const restsharp: Client = { return 'Method not supported'; } + function toPascalCase(str: string): string { + return str.replace( + /\w+/g, + word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(), + ); + } + push(`var client = new RestClient("${fullUrl}");`); - push(`var request = new RestRequest(Method.${method.toUpperCase()});`); + push(`var request = new RestRequest("", Method.${toPascalCase(method)});`); // Add headers, including the cookies @@ -39,7 +46,7 @@ export const restsharp: Client = { push(`request.AddParameter("${header}", ${text}, ParameterType.RequestBody);`); } - push('IRestResponse response = client.Execute(request);'); + push('var response = client.Execute(request);'); return join(); }, }; diff --git a/src/targets/csharp/restsharp/fixtures/application-form-encoded.cs b/src/targets/csharp/restsharp/fixtures/application-form-encoded.cs index 4e4744d01..50f004de6 100644 --- a/src/targets/csharp/restsharp/fixtures/application-form-encoded.cs +++ b/src/targets/csharp/restsharp/fixtures/application-form-encoded.cs @@ -1,5 +1,5 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddHeader("content-type", "application/x-www-form-urlencoded"); request.AddParameter("application/x-www-form-urlencoded", "foo=bar&hello=world", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/application-json.cs b/src/targets/csharp/restsharp/fixtures/application-json.cs index 2ee8c46f1..c766a25bf 100644 --- a/src/targets/csharp/restsharp/fixtures/application-json.cs +++ b/src/targets/csharp/restsharp/fixtures/application-json.cs @@ -1,5 +1,5 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddHeader("content-type", "application/json"); request.AddParameter("application/json", "{\"number\":1,\"string\":\"f\\\"oo\",\"arr\":[1,2,3],\"nested\":{\"a\":\"b\"},\"arr_mix\":[1,\"a\",{\"arr_mix_nested\":{}}],\"boolean\":false}", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/cookies.cs b/src/targets/csharp/restsharp/fixtures/cookies.cs index f0489b650..c4de96e38 100644 --- a/src/targets/csharp/restsharp/fixtures/cookies.cs +++ b/src/targets/csharp/restsharp/fixtures/cookies.cs @@ -1,5 +1,5 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddCookie("foo", "bar"); request.AddCookie("bar", "baz"); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/full.cs b/src/targets/csharp/restsharp/fixtures/full.cs index 14b52d976..d4f618902 100644 --- a/src/targets/csharp/restsharp/fixtures/full.cs +++ b/src/targets/csharp/restsharp/fixtures/full.cs @@ -1,8 +1,8 @@ var client = new RestClient("http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddHeader("accept", "application/json"); request.AddHeader("content-type", "application/x-www-form-urlencoded"); request.AddCookie("foo", "bar"); request.AddCookie("bar", "baz"); request.AddParameter("application/x-www-form-urlencoded", "foo=bar", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/headers.cs b/src/targets/csharp/restsharp/fixtures/headers.cs index 9a02c6db5..3368e9549 100644 --- a/src/targets/csharp/restsharp/fixtures/headers.cs +++ b/src/targets/csharp/restsharp/fixtures/headers.cs @@ -1,6 +1,6 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.GET); +var request = new RestRequest("", Method.Get); request.AddHeader("accept", "application/json"); request.AddHeader("x-foo", "Bar"); request.AddHeader("quoted-value", "\"quoted\" 'string'"); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/https.cs b/src/targets/csharp/restsharp/fixtures/https.cs index 05a369073..1c284c6e3 100644 --- a/src/targets/csharp/restsharp/fixtures/https.cs +++ b/src/targets/csharp/restsharp/fixtures/https.cs @@ -1,3 +1,3 @@ var client = new RestClient("https://mockbin.com/har"); -var request = new RestRequest(Method.GET); -IRestResponse response = client.Execute(request); \ No newline at end of file +var request = new RestRequest("", Method.Get); +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/jsonObj-multiline.cs b/src/targets/csharp/restsharp/fixtures/jsonObj-multiline.cs index 14fbe7778..aefed7789 100644 --- a/src/targets/csharp/restsharp/fixtures/jsonObj-multiline.cs +++ b/src/targets/csharp/restsharp/fixtures/jsonObj-multiline.cs @@ -1,5 +1,5 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddHeader("content-type", "application/json"); request.AddParameter("application/json", "{\n \"foo\": \"bar\"\n}", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/jsonObj-null-value.cs b/src/targets/csharp/restsharp/fixtures/jsonObj-null-value.cs index 36b092c94..8ec7f936b 100644 --- a/src/targets/csharp/restsharp/fixtures/jsonObj-null-value.cs +++ b/src/targets/csharp/restsharp/fixtures/jsonObj-null-value.cs @@ -1,5 +1,5 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddHeader("content-type", "application/json"); request.AddParameter("application/json", "{\"foo\":null}", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/multipart-data.cs b/src/targets/csharp/restsharp/fixtures/multipart-data.cs index 7c95fe632..f769b7104 100644 --- a/src/targets/csharp/restsharp/fixtures/multipart-data.cs +++ b/src/targets/csharp/restsharp/fixtures/multipart-data.cs @@ -1,5 +1,5 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddHeader("content-type", "multipart/form-data; boundary=---011000010111000001101001"); request.AddParameter("multipart/form-data; boundary=---011000010111000001101001", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\nHello World\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bar\"\r\n\r\nBonjour le monde\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/multipart-file.cs b/src/targets/csharp/restsharp/fixtures/multipart-file.cs index 47758542c..ad5ee10f4 100644 --- a/src/targets/csharp/restsharp/fixtures/multipart-file.cs +++ b/src/targets/csharp/restsharp/fixtures/multipart-file.cs @@ -1,5 +1,5 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddHeader("content-type", "multipart/form-data; boundary=---011000010111000001101001"); request.AddParameter("multipart/form-data; boundary=---011000010111000001101001", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/multipart-form-data-no-params.cs b/src/targets/csharp/restsharp/fixtures/multipart-form-data-no-params.cs index be2fcac1f..2dda3e2a5 100644 --- a/src/targets/csharp/restsharp/fixtures/multipart-form-data-no-params.cs +++ b/src/targets/csharp/restsharp/fixtures/multipart-form-data-no-params.cs @@ -1,4 +1,4 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddHeader("Content-Type", "multipart/form-data"); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/multipart-form-data.cs b/src/targets/csharp/restsharp/fixtures/multipart-form-data.cs index 9eb6893b6..5fa2dabf8 100644 --- a/src/targets/csharp/restsharp/fixtures/multipart-form-data.cs +++ b/src/targets/csharp/restsharp/fixtures/multipart-form-data.cs @@ -1,5 +1,5 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddHeader("Content-Type", "multipart/form-data; boundary=---011000010111000001101001"); request.AddParameter("multipart/form-data; boundary=---011000010111000001101001", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/nested.cs b/src/targets/csharp/restsharp/fixtures/nested.cs index e28bf3190..33af293f3 100644 --- a/src/targets/csharp/restsharp/fixtures/nested.cs +++ b/src/targets/csharp/restsharp/fixtures/nested.cs @@ -1,3 +1,3 @@ var client = new RestClient("http://mockbin.com/har?foo%5Bbar%5D=baz%2Czap&fiz=buz&key=value"); -var request = new RestRequest(Method.GET); -IRestResponse response = client.Execute(request); \ No newline at end of file +var request = new RestRequest("", Method.Get); +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/query.cs b/src/targets/csharp/restsharp/fixtures/query.cs index 3e3112c02..82d87b1f5 100644 --- a/src/targets/csharp/restsharp/fixtures/query.cs +++ b/src/targets/csharp/restsharp/fixtures/query.cs @@ -1,3 +1,3 @@ var client = new RestClient("http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value"); -var request = new RestRequest(Method.GET); -IRestResponse response = client.Execute(request); \ No newline at end of file +var request = new RestRequest("", Method.Get); +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/short.cs b/src/targets/csharp/restsharp/fixtures/short.cs index b644539c4..b62d43441 100644 --- a/src/targets/csharp/restsharp/fixtures/short.cs +++ b/src/targets/csharp/restsharp/fixtures/short.cs @@ -1,3 +1,3 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.GET); -IRestResponse response = client.Execute(request); \ No newline at end of file +var request = new RestRequest("", Method.Get); +var response = client.Execute(request); \ No newline at end of file diff --git a/src/targets/csharp/restsharp/fixtures/text-plain.cs b/src/targets/csharp/restsharp/fixtures/text-plain.cs index a0a672de6..cd180a8f7 100644 --- a/src/targets/csharp/restsharp/fixtures/text-plain.cs +++ b/src/targets/csharp/restsharp/fixtures/text-plain.cs @@ -1,5 +1,5 @@ var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var request = new RestRequest("", Method.Post); request.AddHeader("content-type", "text/plain"); request.AddParameter("text/plain", "Hello World", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); \ No newline at end of file +var response = client.Execute(request); \ No newline at end of file From 8a1bc90fdcacf9a2ba9e0dde3f75df7765b218c1 Mon Sep 17 00:00:00 2001 From: Filipe Freire <11976836+filfreire@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:00:46 +0000 Subject: [PATCH 32/35] 3.0.8 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index bba29bdc7..b32f9f2c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "httpsnippet", - "version": "3.0.7", + "version": "3.0.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "httpsnippet", - "version": "3.0.7", + "version": "3.0.8", "license": "MIT", "dependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index 647b2195b..03c880fb2 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "3.0.7", + "version": "3.0.8", "name": "httpsnippet", "description": "HTTP Request snippet generator for *most* languages", "author": "Kong ", From 66b587b815f64a6a51a880381df321ef48b25e9d Mon Sep 17 00:00:00 2001 From: Vaibhav Raj Singh Date: Wed, 16 Oct 2024 14:11:36 +0530 Subject: [PATCH 33/35] fix(form-data): fix ssr error due to window object access (#373) * fix(form-data): override import from package root * fix(httpsnippet): linting errors --- src/httpsnippet.ts | 16 +++++++++------- src/types/form-data.d.ts | 4 ++++ 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 src/types/form-data.d.ts diff --git a/src/httpsnippet.ts b/src/httpsnippet.ts index 0722c8842..c46157b3d 100644 --- a/src/httpsnippet.ts +++ b/src/httpsnippet.ts @@ -1,5 +1,5 @@ import { map as eventStreamMap } from 'event-stream'; -import FormData from 'form-data'; +import FormData from 'form-data/lib/form_data'; import { Param, PostDataCommon, Request as NpmHarRequest } from 'har-format'; import { validateRequest } from 'har-validator-compiled'; import { stringify as queryStringify } from 'querystring'; @@ -13,6 +13,13 @@ import { ClientId, TargetId, targets } from './targets/targets'; export { availableTargets, extname } from './helpers/utils'; export { addTarget, addTargetClient } from './targets/targets'; +// We're implementing the logic for which FormData object to use, ourselves. +// This allows us to use the native FormData object in the browser and the `form-data` module in Node, +// instead of relying on the package entrypoint to handle that. +const resolveFormData = + // @ts-expect-error — we're only using window.FormData if it exists + typeof window !== 'undefined' && window.FormData ? window.FormData : FormData; + const DEBUG_MODE = false; const debug = { @@ -174,7 +181,7 @@ export class HTTPSnippet { request.postData.mimeType = 'multipart/form-data'; if (request.postData?.params) { - const form = new FormData(); + const form = new resolveFormData(); // The `form-data` module returns one of two things: a native FormData object, or its own polyfill // Since the polyfill does not support the full API of the native FormData object, when this library is running in a browser environment it'll fail on two things: @@ -186,7 +193,6 @@ export class HTTPSnippet { // Since the native FormData object is iterable, we easily detect what version of `form-data` we're working with here to allow `multipart/form-data` requests to be compiled under both browser and Node environments. // // This hack is pretty awful but it's the only way we can use this library in the browser as if we code this against just the native FormData object, we can't polyfill that back into Node because Blob and File objects, which something like `formdata-polyfill` requires, don't exist there. - // @ts-expect-error TODO const isNativeFormData = typeof form[Symbol.iterator] === 'function'; // TODO: THIS ABSOLUTELY MUST BE REMOVED. @@ -194,7 +200,6 @@ export class HTTPSnippet { // easter egg const boundary = '---011000010111000001101001'; // this is binary for "api". yep. if (!isNativeFormData) { - // @ts-expect-error THIS IS WRONG. VERY WRONG. form._boundary = boundary; } @@ -205,16 +210,13 @@ export class HTTPSnippet { if (isNativeFormData) { if (isBlob(value)) { - // @ts-expect-error TODO form.append(name, value, filename); } else { form.append(name, value); } } else { form.append(name, value, { - // @ts-expect-error TODO filename, - // @ts-expect-error TODO contentType: param.contentType || null, }); } diff --git a/src/types/form-data.d.ts b/src/types/form-data.d.ts new file mode 100644 index 000000000..0f43ed74b --- /dev/null +++ b/src/types/form-data.d.ts @@ -0,0 +1,4 @@ +declare module 'form-data/lib/form_data' { + import FormData from 'form-data'; + export default FormData; +} From 5b4474df44564aae889423ab26e80d41f99034df Mon Sep 17 00:00:00 2001 From: Filipe Freire <11976836+filfreire@users.noreply.github.com> Date: Wed, 16 Oct 2024 08:43:16 +0000 Subject: [PATCH 34/35] 3.0.9 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b32f9f2c4..5d4e0bf4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "httpsnippet", - "version": "3.0.8", + "version": "3.0.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "httpsnippet", - "version": "3.0.8", + "version": "3.0.9", "license": "MIT", "dependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index 03c880fb2..633a44149 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "3.0.8", + "version": "3.0.9", "name": "httpsnippet", "description": "HTTP Request snippet generator for *most* languages", "author": "Kong ", From 73c327c49716c66441a97be67a99c8ff2959e2ad Mon Sep 17 00:00:00 2001 From: Balu George Date: Mon, 24 Mar 2025 15:20:56 +0530 Subject: [PATCH 35/35] fix: Pin all external github actions to their corresponding commit SHAs (#378) * Pin all external github actions to their corresponding commit SHAs * Update security actions to use the latest commit --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/sast.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ab177cee8..cc46c1c5d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ jobs: # Produces SBOM and CVE report # Helps understand vulnerabilities / license compliance across third party dependencies - id: sca-project - uses: Kong/public-shared-actions/security-actions/sca@2f02738ecb1670f01391162e43fe3f5d4e7942a1 # v2.2.2 + uses: Kong/public-shared-actions/security-actions/sca@a18abf762d6e2444bcbfd20de70451ea1e3bc1b1 with: dir: ${{ github.repository }} upload-sbom-release-assets: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 20d87aedc..8e357624a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,7 +22,7 @@ jobs: token: ${{ secrets.PAT_INSOMNIA_INFRA }} - name: Configure Git user - uses: Homebrew/actions/git-user-config@master + uses: Homebrew/actions/git-user-config@266845213695c3047d210b2e8fbc42ecdaf45802 # master with: username: ${{ (github.event_name == 'workflow_dispatch' && github.actor) || 'insomnia-infra' }} @@ -48,7 +48,7 @@ jobs: git push origin master - name: Create Tag and Release - uses: ncipollo/release-action@v1 + uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1 id: core_tag_and_release with: tag: v${{ env.TAG }} diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index 92cfb5440..0236f5170 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -22,4 +22,4 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: Kong/public-shared-actions/security-actions/semgrep@bd3d75259607dd015bea3b3313123f53b80e9d7f + - uses: Kong/public-shared-actions/security-actions/semgrep@a18abf762d6e2444bcbfd20de70451ea1e3bc1b1