mirror of
https://github.com/usebruno/bruno.git
synced 2024-11-25 09:23:17 +01:00
feat: support for sending url encoded params (resolves #11)
This commit is contained in:
parent
7f0f496bb4
commit
bd153bf849
8
package-lock.json
generated
8
package-lock.json
generated
@ -7190,6 +7190,14 @@
|
|||||||
"postcss-selector-parser": "^6.0.6"
|
"postcss-selector-parser": "^6.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"qs": {
|
||||||
|
"version": "6.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||||
|
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||||
|
"requires": {
|
||||||
|
"side-channel": "^1.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"querystring-es3": {
|
"querystring-es3": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
"mousetrap": "^1.6.5",
|
"mousetrap": "^1.6.5",
|
||||||
"nanoid": "^3.1.30",
|
"nanoid": "^3.1.30",
|
||||||
"next": "12.0.4",
|
"next": "12.0.4",
|
||||||
|
"qs": "^6.11.0",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"react-redux": "^7.2.6",
|
"react-redux": "^7.2.6",
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
thead, td {
|
||||||
|
border: 1px solid #efefef;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead {
|
||||||
|
color: #616161;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
padding: 6px 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-add-param {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
width: 100%;
|
||||||
|
border: solid 1px transparent;
|
||||||
|
outline: none !important;
|
||||||
|
|
||||||
|
&:focus{
|
||||||
|
outline: none !important;
|
||||||
|
border: solid 1px transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default Wrapper;
|
119
renderer/components/RequestPane/FormUrlEncodedParams/index.js
Normal file
119
renderer/components/RequestPane/FormUrlEncodedParams/index.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import get from 'lodash/get';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import { IconTrash } from '@tabler/icons';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { addFormUrlEncodedParam, updateFormUrlEncodedParam, deleteFormUrlEncodedParam } from 'providers/ReduxStore/slices/collections';
|
||||||
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
|
const FormUrlEncodedParams = ({item, collection}) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const params = item.draft ? get(item, 'draft.request.body.formUrlEncoded') : get(item, 'request.body.formUrlEncoded');
|
||||||
|
|
||||||
|
const addParam = () => {
|
||||||
|
dispatch(addFormUrlEncodedParam({
|
||||||
|
itemUid: item.uid,
|
||||||
|
collectionUid: collection.uid,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleParamChange = (e, _param, type) => {
|
||||||
|
const param = cloneDeep(_param);
|
||||||
|
switch(type) {
|
||||||
|
case 'name' : {
|
||||||
|
param.name = e.target.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'value' : {
|
||||||
|
param.value = e.target.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'description' : {
|
||||||
|
param.description = e.target.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'enabled' : {
|
||||||
|
param.enabled = e.target.checked;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dispatch(updateFormUrlEncodedParam({
|
||||||
|
param: param,
|
||||||
|
itemUid: item.uid,
|
||||||
|
collectionUid: collection.uid
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemoveParams = (param) => {
|
||||||
|
dispatch(deleteFormUrlEncodedParam({
|
||||||
|
paramUid: param.uid,
|
||||||
|
itemUid: item.uid,
|
||||||
|
collectionUid: collection.uid
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledWrapper className="w-full">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Key</td>
|
||||||
|
<td>Value</td>
|
||||||
|
<td>Description</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{params && params.length ? params.map((param, index) => {
|
||||||
|
return (
|
||||||
|
<tr key={param.uid}>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
||||||
|
value={param.name}
|
||||||
|
className="mousetrap"
|
||||||
|
onChange={(e) => handleParamChange(e, param, 'name')}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
||||||
|
value={param.value}
|
||||||
|
className="mousetrap"
|
||||||
|
onChange={(e) => handleParamChange(e, param, 'value')}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
||||||
|
value={param.description}
|
||||||
|
className="mousetrap"
|
||||||
|
onChange={(e) => handleParamChange(e, param, 'description')}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={param.enabled}
|
||||||
|
className="mr-3 mousetrap"
|
||||||
|
onChange={(e) => handleParamChange(e, param, 'enabled')}
|
||||||
|
/>
|
||||||
|
<button onClick={() => handleRemoveParams(param)}>
|
||||||
|
<IconTrash strokeWidth={1.5} size={20}/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
}) : null}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<button className="btn-add-param text-link pr-2 py-3 mt-2 select-none" onClick={addParam}>+ Add Param</button>
|
||||||
|
</StyledWrapper>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
export default FormUrlEncodedParams;
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import CodeEditor from 'components/CodeEditor';
|
import CodeEditor from 'components/CodeEditor';
|
||||||
|
import FormUrlEncodedParams from 'components/RequestPane/FormUrlEncodedParams';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { updateRequestBody, sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections';
|
import { updateRequestBody, sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
@ -47,6 +48,10 @@ const RequestBody = ({item, collection}) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(bodyMode === 'formUrlEncoded') {
|
||||||
|
return <FormUrlEncodedParams item={item} collection={collection}/>;
|
||||||
|
}
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<StyledWrapper className="w-full">
|
<StyledWrapper className="w-full">
|
||||||
No Body
|
No Body
|
||||||
|
@ -343,6 +343,61 @@ export const collectionsSlice = createSlice({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
addFormUrlEncodedParam: (state, action) => {
|
||||||
|
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||||
|
|
||||||
|
if(collection) {
|
||||||
|
const item = findItemInCollection(collection, action.payload.itemUid);
|
||||||
|
|
||||||
|
if(item && isItemARequest(item)) {
|
||||||
|
if(!item.draft) {
|
||||||
|
item.draft = cloneDeep(item);
|
||||||
|
}
|
||||||
|
item.draft.request.body.formUrlEncoded = item.draft.request.body.formUrlEncoded || [];
|
||||||
|
item.draft.request.body.formUrlEncoded.push({
|
||||||
|
uid: uuid(),
|
||||||
|
name: '',
|
||||||
|
value: '',
|
||||||
|
description: '',
|
||||||
|
enabled: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateFormUrlEncodedParam: (state, action) => {
|
||||||
|
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||||
|
|
||||||
|
if(collection) {
|
||||||
|
const item = findItemInCollection(collection, action.payload.itemUid);
|
||||||
|
|
||||||
|
if(item && isItemARequest(item)) {
|
||||||
|
if(!item.draft) {
|
||||||
|
item.draft = cloneDeep(item);
|
||||||
|
}
|
||||||
|
const param = find(item.draft.request.body.formUrlEncoded, (p) => p.uid === action.payload.param.uid);
|
||||||
|
if(param) {
|
||||||
|
param.name = action.payload.param.name;
|
||||||
|
param.value = action.payload.param.value;
|
||||||
|
param.description = action.payload.param.description;
|
||||||
|
param.enabled = action.payload.param.enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteFormUrlEncodedParam: (state, action) => {
|
||||||
|
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||||
|
|
||||||
|
if(collection) {
|
||||||
|
const item = findItemInCollection(collection, action.payload.itemUid);
|
||||||
|
|
||||||
|
if(item && isItemARequest(item)) {
|
||||||
|
if(!item.draft) {
|
||||||
|
item.draft = cloneDeep(item);
|
||||||
|
}
|
||||||
|
item.draft.request.body.formUrlEncoded = filter(item.draft.request.body.formUrlEncoded, (p) => p.uid !== action.payload.paramUid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
updateRequestBodyMode: (state, action) => {
|
updateRequestBodyMode: (state, action) => {
|
||||||
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||||
|
|
||||||
@ -429,6 +484,9 @@ export const {
|
|||||||
addRequestHeader,
|
addRequestHeader,
|
||||||
updateRequestHeader,
|
updateRequestHeader,
|
||||||
deleteRequestHeader,
|
deleteRequestHeader,
|
||||||
|
addFormUrlEncodedParam,
|
||||||
|
updateFormUrlEncodedParam,
|
||||||
|
deleteFormUrlEncodedParam,
|
||||||
updateRequestBodyMode,
|
updateRequestBodyMode,
|
||||||
updateRequestBody,
|
updateRequestBody,
|
||||||
updateRequestMethod
|
updateRequestMethod
|
||||||
|
@ -128,6 +128,18 @@ export const transformCollectionToSaveToIdb = (collection, options = {}) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const copyFormUrlEncodedParams = (params = []) => {
|
||||||
|
return map(params, (param) => {
|
||||||
|
return {
|
||||||
|
uid: param.uid,
|
||||||
|
name: param.name,
|
||||||
|
value: param.value,
|
||||||
|
description: param.description,
|
||||||
|
enabled: param.enabled
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const copyItems = (sourceItems, destItems) => {
|
const copyItems = (sourceItems, destItems) => {
|
||||||
each(sourceItems, (si) => {
|
each(sourceItems, (si) => {
|
||||||
const di = {
|
const di = {
|
||||||
@ -151,7 +163,7 @@ export const transformCollectionToSaveToIdb = (collection, options = {}) => {
|
|||||||
text: si.draft.request.body.text,
|
text: si.draft.request.body.text,
|
||||||
xml: si.draft.request.body.xml,
|
xml: si.draft.request.body.xml,
|
||||||
multipartForm: si.draft.request.body.multipartForm,
|
multipartForm: si.draft.request.body.multipartForm,
|
||||||
xmformUrlEncodedl: si.draft.request.body.formUrlEncoded
|
formUrlEncoded: copyFormUrlEncodedParams(si.draft.request.body.formUrlEncoded)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -168,7 +180,7 @@ export const transformCollectionToSaveToIdb = (collection, options = {}) => {
|
|||||||
text: si.request.body.text,
|
text: si.request.body.text,
|
||||||
xml: si.request.body.xml,
|
xml: si.request.body.xml,
|
||||||
multipartForm: si.request.body.multipartForm,
|
multipartForm: si.request.body.multipartForm,
|
||||||
xmformUrlEncodedl: si.request.body.formUrlEncoded
|
formUrlEncoded: copyFormUrlEncodedParams(si.request.body.formUrlEncoded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import each from 'lodash/each';
|
import each from 'lodash/each';
|
||||||
|
import filter from 'lodash/filter';
|
||||||
|
import qs from 'qs';
|
||||||
import { rawRequest, gql } from 'graphql-request';
|
import { rawRequest, gql } from 'graphql-request';
|
||||||
|
|
||||||
const sendNetworkRequest = async (item) => {
|
const sendNetworkRequest = async (item) => {
|
||||||
@ -58,8 +60,16 @@ const sendHttpRequest = async (request) => {
|
|||||||
options.data = request.body.xml;
|
options.data = request.body.xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(request.body.mode === 'formUrlEncoded') {
|
||||||
|
options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||||
|
const params = {};
|
||||||
|
const enabledParams = filter(request.body.formUrlEncoded, p => p.enabled);
|
||||||
|
each(enabledParams, (p) => params[p.name] = p.value);
|
||||||
|
options.data = qs.stringify(params);
|
||||||
|
}
|
||||||
|
|
||||||
console.log('>>> Sending Request');
|
console.log('>>> Sending Request');
|
||||||
console.log(request);
|
console.log(options);
|
||||||
|
|
||||||
ipcRenderer
|
ipcRenderer
|
||||||
.invoke('send-http-request', options)
|
.invoke('send-http-request', options)
|
||||||
|
Loading…
Reference in New Issue
Block a user