diff --git a/package-lock.json b/package-lock.json
index ba6e6c5e5..be14d77a7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5600,6 +5600,14 @@
"node": ">=4"
}
},
+ "node_modules/chai-string": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/chai-string/-/chai-string-1.5.0.tgz",
+ "integrity": "sha512-sydDC3S3pNAQMYwJrs6dQX0oBQ6KfIPuOZ78n7rocW0eJJlsHPh2t3kwW7xfwYA/1Bf6/arGtSUo16rxR2JFlw==",
+ "peerDependencies": {
+ "chai": "^4.1.2"
+ }
+ },
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -16691,7 +16699,7 @@
"license": "MIT",
"dependencies": {
"@usebruno/js": "0.8.0",
- "@usebruno/lang": "0.7.0",
+ "@usebruno/lang": "0.8.0",
"axios": "^1.5.1",
"chai": "^4.3.7",
"chalk": "^3.0.0",
@@ -16771,14 +16779,15 @@
},
"packages/bruno-electron": {
"name": "bruno",
- "version": "v0.22.0",
+ "version": "v0.22.1",
"dependencies": {
"@usebruno/js": "0.8.0",
- "@usebruno/lang": "0.7.0",
+ "@usebruno/lang": "0.8.0",
"@usebruno/schema": "0.5.0",
"about-window": "^1.15.2",
"axios": "^1.5.1",
"chai": "^4.3.7",
+ "chai-string": "^1.5.0",
"chokidar": "^3.5.3",
"decomment": "^0.9.5",
"dotenv": "^16.0.3",
@@ -17021,7 +17030,7 @@
},
"packages/bruno-lang": {
"name": "@usebruno/lang",
- "version": "0.7.0",
+ "version": "0.8.0",
"license": "MIT",
"dependencies": {
"arcsecond": "^5.0.0",
@@ -20023,7 +20032,7 @@
"version": "file:packages/bruno-cli",
"requires": {
"@usebruno/js": "0.8.0",
- "@usebruno/lang": "0.7.0",
+ "@usebruno/lang": "0.8.0",
"axios": "^1.5.1",
"chai": "^4.3.7",
"chalk": "^3.0.0",
@@ -21155,11 +21164,12 @@
"version": "file:packages/bruno-electron",
"requires": {
"@usebruno/js": "0.8.0",
- "@usebruno/lang": "0.7.0",
+ "@usebruno/lang": "0.8.0",
"@usebruno/schema": "0.5.0",
"about-window": "^1.15.2",
"axios": "^1.5.1",
"chai": "^4.3.7",
+ "chai-string": "^1.5.0",
"chokidar": "^3.5.3",
"decomment": "^0.9.5",
"dmg-license": "^1.0.11",
@@ -21547,6 +21557,12 @@
"type-detect": "^4.0.5"
}
},
+ "chai-string": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/chai-string/-/chai-string-1.5.0.tgz",
+ "integrity": "sha512-sydDC3S3pNAQMYwJrs6dQX0oBQ6KfIPuOZ78n7rocW0eJJlsHPh2t3kwW7xfwYA/1Bf6/arGtSUo16rxR2JFlw==",
+ "requires": {}
+ },
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
diff --git a/packages/bruno-app/src/components/ResponsePane/Placeholder/index.js b/packages/bruno-app/src/components/ResponsePane/Placeholder/index.js
index 2e7cd8621..bca9e138a 100644
--- a/packages/bruno-app/src/components/ResponsePane/Placeholder/index.js
+++ b/packages/bruno-app/src/components/ResponsePane/Placeholder/index.js
@@ -1,8 +1,14 @@
import React from 'react';
import { IconSend } from '@tabler/icons';
import StyledWrapper from './StyledWrapper';
+import { isMacOS } from 'utils/common/platform';
const Placeholder = () => {
+ const isMac = isMacOS();
+ const sendRequestShortcut = isMac ? 'Cmd + Enter' : 'Ctrl + Enter';
+ const newRequestShortcut = isMac ? 'Cmd + B' : 'Ctrl + B';
+ const editEnvironmentShortcut = isMac ? 'Cmd + E' : 'Ctrl + E';
+
return (
@@ -15,9 +21,9 @@ const Placeholder = () => {
Edit Environments
-
Cmd + Enter
-
Cmd + B
-
Cmd + E
+
{sendRequestShortcut}
+
{newRequestShortcut}
+
{editEnvironmentShortcut}
diff --git a/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js b/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js
index d77d09951..142c604c9 100644
--- a/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js
+++ b/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js
@@ -45,6 +45,10 @@ const QueryResult = ({ item, collection, data, width, disableRunEventListener, h
return safeStringifyJSON(data);
}
+ if (mode.includes('image')) {
+ return item.requestSent.url;
+ }
+
// final fallback
if (typeof data === 'string') {
return data;
@@ -103,6 +107,8 @@ const QueryResult = ({ item, collection, data, width, disableRunEventListener, h
className="h-full bg-white"
/>
);
+ } else if (mode.includes('image')) {
+ return
;
}
return ;
diff --git a/packages/bruno-app/src/components/Sidebar/index.js b/packages/bruno-app/src/components/Sidebar/index.js
index 4cc682a5b..2e233bf0c 100644
--- a/packages/bruno-app/src/components/Sidebar/index.js
+++ b/packages/bruno-app/src/components/Sidebar/index.js
@@ -105,7 +105,7 @@ const Sidebar = () => {
Star
-
v0.22.1
+ v0.23.0
diff --git a/packages/bruno-app/src/utils/common/codemirror.js b/packages/bruno-app/src/utils/common/codemirror.js
index ce2f8be17..78016de6f 100644
--- a/packages/bruno-app/src/utils/common/codemirror.js
+++ b/packages/bruno-app/src/utils/common/codemirror.js
@@ -60,6 +60,8 @@ export const getCodeMirrorModeBasedOnContentType = (contentType) => {
return 'application/xml';
} else if (contentType.includes('yaml')) {
return 'application/yaml';
+ } else if (contentType.includes('image')) {
+ return 'application/image';
} else {
return 'application/text';
}
diff --git a/packages/bruno-app/src/utils/network/index.js b/packages/bruno-app/src/utils/network/index.js
index a498a722c..8952e1986 100644
--- a/packages/bruno-app/src/utils/network/index.js
+++ b/packages/bruno-app/src/utils/network/index.js
@@ -1,3 +1,5 @@
+import { safeStringifyJSON } from 'utils/common';
+
export const sendNetworkRequest = async (item, collection, environment, collectionVariables) => {
return new Promise((resolve, reject) => {
if (['http-request', 'graphql-request'].includes(item.type)) {
@@ -7,7 +9,7 @@ export const sendNetworkRequest = async (item, collection, environment, collecti
state: 'success',
data: response.data,
headers: Object.entries(response.headers),
- size: response.headers['content-length'] || 0,
+ size: getResponseSize(response),
status: response.status,
statusText: response.statusText,
duration: response.duration
@@ -29,6 +31,10 @@ const sendHttpRequest = async (item, collection, environment, collectionVariable
});
};
+const getResponseSize = (response) => {
+ return response.headers['content-length'] || Buffer.byteLength(safeStringifyJSON(response.data)) || 0;
+};
+
export const fetchGqlSchema = async (endpoint, environment, request, collection) => {
return new Promise((resolve, reject) => {
const { ipcRenderer } = window;
diff --git a/packages/bruno-cli/package.json b/packages/bruno-cli/package.json
index cdabd32a3..f36459c78 100644
--- a/packages/bruno-cli/package.json
+++ b/packages/bruno-cli/package.json
@@ -25,7 +25,7 @@
],
"dependencies": {
"@usebruno/js": "0.8.0",
- "@usebruno/lang": "0.7.0",
+ "@usebruno/lang": "0.8.0",
"axios": "^1.5.1",
"chai": "^4.3.7",
"chalk": "^3.0.0",
diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json
index 340fccee8..95c1086fa 100644
--- a/packages/bruno-electron/package.json
+++ b/packages/bruno-electron/package.json
@@ -1,5 +1,5 @@
{
- "version": "v0.22.1",
+ "version": "v0.23.0",
"name": "bruno",
"description": "Opensource API Client for Exploring and Testing APIs",
"homepage": "https://www.usebruno.com",
@@ -15,11 +15,12 @@
},
"dependencies": {
"@usebruno/js": "0.8.0",
- "@usebruno/lang": "0.7.0",
+ "@usebruno/lang": "0.8.0",
"@usebruno/schema": "0.5.0",
"about-window": "^1.15.2",
"axios": "^1.5.1",
"chai": "^4.3.7",
+ "chai-string": "^1.5.0",
"chokidar": "^3.5.3",
"decomment": "^0.9.5",
"dotenv": "^16.0.3",
diff --git a/packages/bruno-electron/resources/icons/mac/icon.icns b/packages/bruno-electron/resources/icons/mac/icon.icns
index 85d1c1e63..5e01d5bdf 100644
Binary files a/packages/bruno-electron/resources/icons/mac/icon.icns and b/packages/bruno-electron/resources/icons/mac/icon.icns differ
diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js
index f95340229..da7c14e64 100644
--- a/packages/bruno-electron/src/ipc/network/index.js
+++ b/packages/bruno-electron/src/ipc/network/index.js
@@ -75,7 +75,7 @@ const getSize = (data) => {
}
if (typeof data === 'object') {
- return Buffer.byteLength(JSON.stringify(data), 'utf8');
+ return Buffer.byteLength(safeStringifyJSON(data), 'utf8');
}
return 0;
@@ -493,7 +493,8 @@ const registerNetworkIpc = (mainWindow) => {
ipcMain.handle('fetch-gql-schema', async (event, endpoint, environment, request, collection) => {
try {
const envVars = getEnvVars(environment);
- const preparedRequest = prepareGqlIntrospectionRequest(endpoint, envVars, request);
+ const collectionRoot = get(collection, 'root', {});
+ const preparedRequest = prepareGqlIntrospectionRequest(endpoint, envVars, request, collectionRoot);
const preferences = getPreferences();
const sslVerification = get(preferences, 'request.sslVerification', true);
@@ -711,14 +712,14 @@ const registerNetworkIpc = (mainWindow) => {
if (socksEnabled) {
const socksProxyAgent = new SocksProxyAgent(proxyUri);
-
+
request.httpsAgent = socksProxyAgent;
request.httpAgent = socksProxyAgent;
} else {
request.httpsAgent = new HttpsProxyAgent(proxyUri, {
rejectUnauthorized: sslVerification
});
-
+
request.httpAgent = new HttpProxyAgent(proxyUri);
}
} else if (!sslVerification) {
diff --git a/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js b/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js
index 4a1e41c88..a448d9106 100644
--- a/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js
+++ b/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js
@@ -1,15 +1,14 @@
const Handlebars = require('handlebars');
const { getIntrospectionQuery } = require('graphql');
-const { get } = require('lodash');
+const { setAuthHeaders } = require('./prepare-request');
-const prepareGqlIntrospectionRequest = (endpoint, envVars, request) => {
+const prepareGqlIntrospectionRequest = (endpoint, envVars, request, collectionRoot) => {
if (endpoint && endpoint.length) {
endpoint = Handlebars.compile(endpoint, { noEscape: true })(envVars);
}
- const introspectionQuery = getIntrospectionQuery();
const queryParams = {
- query: introspectionQuery
+ query: getIntrospectionQuery()
};
let axiosRequest = {
@@ -23,20 +22,7 @@ const prepareGqlIntrospectionRequest = (endpoint, envVars, request) => {
data: JSON.stringify(queryParams)
};
- if (request.auth) {
- if (request.auth.mode === 'basic') {
- axiosRequest.auth = {
- username: get(request, 'auth.basic.username'),
- password: get(request, 'auth.basic.password')
- };
- }
-
- if (request.auth.mode === 'bearer') {
- axiosRequest.headers.authorization = `Bearer ${get(request, 'auth.bearer.token')}`;
- }
- }
-
- return axiosRequest;
+ return setAuthHeaders(axiosRequest, request, collectionRoot);
};
const mapHeaders = (headers) => {
diff --git a/packages/bruno-electron/src/ipc/network/prepare-request.js b/packages/bruno-electron/src/ipc/network/prepare-request.js
index bff574bb3..44f408ca9 100644
--- a/packages/bruno-electron/src/ipc/network/prepare-request.js
+++ b/packages/bruno-electron/src/ipc/network/prepare-request.js
@@ -1,6 +1,41 @@
const { get, each, filter } = require('lodash');
const decomment = require('decomment');
+// Authentication
+// A request can override the collection auth with another auth
+// But it cannot override the collection auth with no auth
+// We will provide support for disabling the auth via scripting in the future
+const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
+ const collectionAuth = get(collectionRoot, 'request.auth');
+ if (collectionAuth) {
+ if (collectionAuth.mode === 'basic') {
+ axiosRequest.auth = {
+ username: get(collectionAuth, 'basic.username'),
+ password: get(collectionAuth, 'basic.password')
+ };
+ }
+
+ if (collectionAuth.mode === 'bearer') {
+ axiosRequest.headers['authorization'] = `Bearer ${get(collectionAuth, 'bearer.token')}`;
+ }
+ }
+
+ if (request.auth) {
+ if (request.auth.mode === 'basic') {
+ axiosRequest.auth = {
+ username: get(request, 'auth.basic.username'),
+ password: get(request, 'auth.basic.password')
+ };
+ }
+
+ if (request.auth.mode === 'bearer') {
+ axiosRequest.headers['authorization'] = `Bearer ${get(request, 'auth.bearer.token')}`;
+ }
+ }
+
+ return axiosRequest;
+};
+
const prepareRequest = (request, collectionRoot) => {
const headers = {};
let contentTypeDefined = false;
@@ -30,36 +65,7 @@ const prepareRequest = (request, collectionRoot) => {
headers: headers
};
- // Authentication
- // A request can override the collection auth with another auth
- // But it cannot override the collection auth with no auth
- // We will provide support for disabling the auth via scripting in the future
- const collectionAuth = get(collectionRoot, 'request.auth');
- if (collectionAuth) {
- if (collectionAuth.mode === 'basic') {
- axiosRequest.auth = {
- username: get(collectionAuth, 'basic.username'),
- password: get(collectionAuth, 'basic.password')
- };
- }
-
- if (collectionAuth.mode === 'bearer') {
- axiosRequest.headers['authorization'] = `Bearer ${get(collectionAuth, 'bearer.token')}`;
- }
- }
-
- if (request.auth) {
- if (request.auth.mode === 'basic') {
- axiosRequest.auth = {
- username: get(request, 'auth.basic.username'),
- password: get(request, 'auth.basic.password')
- };
- }
-
- if (request.auth.mode === 'bearer') {
- axiosRequest.headers['authorization'] = `Bearer ${get(request, 'auth.bearer.token')}`;
- }
- }
+ axiosRequest = setAuthHeaders(axiosRequest, request, collectionRoot);
if (request.body.mode === 'json') {
if (!contentTypeDefined) {
@@ -132,3 +138,4 @@ const prepareRequest = (request, collectionRoot) => {
};
module.exports = prepareRequest;
+module.exports.setAuthHeaders = setAuthHeaders;
diff --git a/packages/bruno-js/src/runtime/assert-runtime.js b/packages/bruno-js/src/runtime/assert-runtime.js
index a9588263a..06f6adab4 100644
--- a/packages/bruno-js/src/runtime/assert-runtime.js
+++ b/packages/bruno-js/src/runtime/assert-runtime.js
@@ -6,6 +6,7 @@ const BrunoRequest = require('../bruno-request');
const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils');
const { expect } = chai;
+chai.use(require('chai-string'));
chai.use(function (chai, utils) {
// Custom assertion for checking if a variable is JSON
chai.Assertion.addProperty('json', function () {
diff --git a/packages/bruno-lang/package.json b/packages/bruno-lang/package.json
index 4081479d0..2e4b3df03 100644
--- a/packages/bruno-lang/package.json
+++ b/packages/bruno-lang/package.json
@@ -1,6 +1,6 @@
{
"name": "@usebruno/lang",
- "version": "0.7.0",
+ "version": "0.8.0",
"license": "MIT",
"main": "src/index.js",
"files": [