Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed url conversion when exporting to Postman #2885

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 49 additions & 12 deletions packages/bruno-app/src/utils/exporters/postman-collection.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import map from 'lodash/map';
import * as FileSaver from 'file-saver';
import { deleteSecretsInEnvs, deleteUidsInEnvs, deleteUidsInItems } from 'utils/collections/export';
import { deleteSecretsInEnvs, deleteUidsInEnvs, deleteUidsInItems } from '../../utils/collections/export';

export const exportCollection = (collection) => {
export const convertCollection = (collection) => {
delete collection.uid;
delete collection.processEnvVariables;
deleteUidsInItems(collection.items);
Expand Down Expand Up @@ -171,18 +171,47 @@ export const exportCollection = (collection) => {
}
};

const generateHost = (url) => {
const generateProtocol = (url) => {
if (url.startsWith('https://')) {
return 'https';
} else if (url.startsWith('http://')) {
return 'http';
}
return null;
};

const generateAuthFromUrl = (url) => {
try {
const { hostname } = new URL(url);
return hostname.split('.');
} catch (error) {
console.error(`Invalid URL: ${url}`, error);
return [];
const { username, password } = new URL(url);
if (username === '' && password === '') return null;
return {
user: username,
password: password
}
} catch (e) {
return null;
}
};

const fixHostForParsing = (url) => {
let updatedUrl = url;
if (url.startsWith('/')) {
updatedUrl = 'https://placeholder/' + url;
} else if (!url.startsWith('http://') && !url.startsWith('https://')) {
updatedUrl = 'https://' + url;
}
return updatedUrl;
}

const generateHost = (url) => {
if (url.startsWith('/')) return null;
const { hostname } = new URL(fixHostForParsing(url));
return hostname.split('.');
};

const generatePathParams = (params) => {
return params.filter((param) => param.type === 'path').map((param) => `:${param.name}`);
const generatePathParams = (url) => {
const { pathname } = new URL(fixHostForParsing(url));
return pathname.split('/').filter(param => param !== '');
};

const generateQueryParams = (params) => {
Expand All @@ -203,15 +232,17 @@ export const exportCollection = (collection) => {
header: generateHeaders(itemRequest.headers),
url: {
raw: itemRequest.url,
auth: generateAuthFromUrl(itemRequest.url),
Copy link
Member

@sanjai0py sanjai0py Aug 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure Postman supports this schema?

Postman Schema
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "If object, contains the complete broken-down URL for this request. If string, contains the literal request URL.",
  "$id": "#/definitions/url",
  "title": "Url",
  "oneOf": [
    {
      "type": "object",
      "properties": {
        "raw": {
          "type": "string",
          "description": "The string representation of the request URL, including the protocol, host, path, hash, query parameter(s) and path variable(s)."
        },
        "protocol": {
          "type": "string",
          "description": "The protocol associated with the request, E.g: 'http'"
        },
        "host": {
          "title": "Host",
          "description": "The host for the URL, E.g: api.yourdomain.com. Can be stored as a string or as an array of strings.",
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "The host, split into subdomain strings."
            }
          ]
        },
        "path": {
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "array",
              "description": "The complete path of the current url, broken down into segments. A segment could be a string, or a path variable.",
              "items": {
                "oneOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string"
                      },
                      "value": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            }
          ]
        },
        "port": {
          "type": "string",
          "description": "The port number present in this URL. An empty value implies 80/443 depending on whether the protocol field contains http/https."
        },
        "query": {
          "type": "array",
          "description": "An array of QueryParams, which is basically the query string part of the URL, parsed into separate variables",
          "items": {
            "type": "object",
            "title": "QueryParam",
            "properties": {
              "key": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "value": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "disabled": {
                "type": "boolean",
                "default": false,
                "description": "If set to true, the current query parameter will not be sent with the request."
              },
              "description": {
                "$ref": "#/definitions/description"
              }
            }
          }
        },
        "hash": {
          "description": "Contains the URL fragment (if any). Usually this is not transmitted over the network, but it could be useful to store this in some cases.",
          "type": "string"
        },
        "variable": {
          "type": "array",
          "description": "Postman supports path variables with the syntax `/path/:variableName/to/somewhere`. These variables are stored in this field.",
          "items": {
            "$ref": "#/definitions/variable"
          }
        }
      }
    },
    {
      "type": "string"
    }
  ]
}

https://schema.postman.com/collection/json/v2.1.0/draft-07/docs/index.html

protocol: generateProtocol(itemRequest.url),
host: generateHost(itemRequest.url),
path: generatePathParams(itemRequest.params),
path: generatePathParams(itemRequest.url),
query: generateQueryParams(itemRequest.params),
variable: generateVariables(itemRequest.params)
},
auth: generateAuth(itemRequest.auth)
};

if (itemRequest.body.mode != 'none') {
if (itemRequest.body.mode !== 'none') {
requestObject.body = generateBody(itemRequest.body);
}
return requestObject;
Expand All @@ -238,6 +269,12 @@ export const exportCollection = (collection) => {
collectionToExport.item = generateItemSection(collection.items);
collectionToExport.variable = generateCollectionVars(collection);

return collectionToExport;
};

export const exportCollection = (collection) => {
const collectionToExport = convertCollection(collection);

const fileName = `${collection.name}.json`;
const fileBlob = new Blob([JSON.stringify(collectionToExport, null, 2)], { type: 'application/json' });

Expand Down
Loading