diff --git a/packages/insomnia-app/app/models/__tests__/request.test.js b/packages/insomnia-app/app/models/__tests__/request.test.js index 5b234ea5d0..17bbb2677a 100644 --- a/packages/insomnia-app/app/models/__tests__/request.test.js +++ b/packages/insomnia-app/app/models/__tests__/request.test.js @@ -120,6 +120,34 @@ describe('updateMimeType()', async () => { expect(newRequest.body).toEqual({}); expect(newRequest.headers).toEqual([{name: 'content-tYPE', value: 'application/json'}]); }); + + it('uses saved body when provided', async () => { + const request = await models.request.create({ + name: 'My Request', + parentId: 'fld_1', + body: { + text: 'My Data' + } + }); + expect(request).not.toBeNull(); + + const newRequest = await models.request.updateMimeType(request, 'application/json', false, {text: 'Saved Data'}); + expect(newRequest.body.text).toEqual('Saved Data'); + }); + + it('uses existing body when saved body not provided', async () => { + const request = await models.request.create({ + name: 'My Request', + parentId: 'fld_1', + body: { + text: 'My Data' + } + }); + expect(request).not.toBeNull(); + + const newRequest = await models.request.updateMimeType(request, 'application/json', false, {}); + expect(newRequest.body.text).toEqual('My Data'); + }); }); describe('migrate()', () => { diff --git a/packages/insomnia-app/app/models/request-meta.js b/packages/insomnia-app/app/models/request-meta.js index 3544fb020b..87ff125a12 100644 --- a/packages/insomnia-app/app/models/request-meta.js +++ b/packages/insomnia-app/app/models/request-meta.js @@ -12,7 +12,8 @@ export function init () { previewMode: PREVIEW_MODE_FRIENDLY, responseFilter: '', responseFilterHistory: [], - activeResponseId: null + activeResponseId: null, + savedRequestBody: {} }; } diff --git a/packages/insomnia-app/app/models/request.js b/packages/insomnia-app/app/models/request.js index 8a81d76a18..401cc23b72 100644 --- a/packages/insomnia-app/app/models/request.js +++ b/packages/insomnia-app/app/models/request.js @@ -243,7 +243,8 @@ export function update (request: Request, patch: Object): Promise { export function updateMimeType ( request: Request, mimeType: string, - doCreate: boolean = false + doCreate: boolean = false, + savedBody: RequestBody = {} ): Promise { let headers = request.headers ? [...request.headers] : []; const contentTypeHeader = getContentTypeHeader(headers); @@ -288,16 +289,20 @@ export function updateMimeType ( let body; + const oldBody = Object.keys(savedBody).length === 0 + ? request.body + : savedBody; + if (mimeType === CONTENT_TYPE_FORM_URLENCODED) { // Urlencoded - body = request.body.params - ? newBodyFormUrlEncoded(request.body.params) - : newBodyFormUrlEncoded(deconstructQueryStringToParams(request.body.text)); + body = oldBody.params + ? newBodyFormUrlEncoded(oldBody.params) + : newBodyFormUrlEncoded(deconstructQueryStringToParams(oldBody.text)); } else if (mimeType === CONTENT_TYPE_FORM_DATA) { // Form Data - body = request.body.params - ? newBodyForm(request.body.params) - : newBodyForm(deconstructQueryStringToParams(request.body.text)); + body = oldBody.params + ? newBodyForm(oldBody.params) + : newBodyForm(deconstructQueryStringToParams(oldBody.text)); } else if (mimeType === CONTENT_TYPE_FILE) { // File body = newBodyFile(''); @@ -305,15 +310,15 @@ export function updateMimeType ( if (contentTypeHeader) { contentTypeHeader.value = CONTENT_TYPE_JSON; } - body = newBodyRaw(request.body.text || '', CONTENT_TYPE_GRAPHQL); + body = newBodyRaw(oldBody.text || '', CONTENT_TYPE_GRAPHQL); } else if (typeof mimeType !== 'string') { // No body body = newBodyNone(); } else { // Raw Content-Type (ex: application/json) - body = request.body.params - ? newBodyRaw(buildQueryStringFromParams(request.body.params, false), mimeType) - : newBodyRaw(request.body.text || '', mimeType); + body = oldBody.params + ? newBodyRaw(buildQueryStringFromParams(oldBody.params, false), mimeType) + : newBodyRaw(oldBody.text || '', mimeType); } // ~~~~~~~~~~~~~~~~~~~~~~~~ // diff --git a/packages/insomnia-app/app/ui/components/dropdowns/content-type-dropdown.js b/packages/insomnia-app/app/ui/components/dropdowns/content-type-dropdown.js index e19ea95b6c..88975a7417 100644 --- a/packages/insomnia-app/app/ui/components/dropdowns/content-type-dropdown.js +++ b/packages/insomnia-app/app/ui/components/dropdowns/content-type-dropdown.js @@ -40,10 +40,9 @@ class ContentTypeDropdown extends React.PureComponent { const willBeFile = mimeType === CONTENT_TYPE_FILE; const willBeMultipart = mimeType === CONTENT_TYPE_FORM_DATA; - const willBeEmpty = typeof mimeType !== 'string'; const willBeGraphQL = mimeType === CONTENT_TYPE_GRAPHQL; - const willConvertToText = !willBeGraphQL && !willBeFile && !willBeMultipart && !willBeEmpty; + const willConvertToText = !willBeGraphQL && !willBeFile && !willBeMultipart; const willPreserveText = willConvertToText && isText; const willPreserveForm = isFormUrlEncoded && willBeMultipart; diff --git a/packages/insomnia-app/app/ui/components/wrapper.js b/packages/insomnia-app/app/ui/components/wrapper.js index a1b520926b..319bee004b 100644 --- a/packages/insomnia-app/app/ui/components/wrapper.js +++ b/packages/insomnia-app/app/ui/components/wrapper.js @@ -4,7 +4,6 @@ import type {Response} from '../../models/response'; import type {OAuth2Token} from '../../models/o-auth-2-token'; import type {Workspace} from '../../models/workspace'; import type {Request, RequestAuthentication, RequestBody, RequestHeader, RequestParameter} from '../../models/request'; -import {updateMimeType} from '../../models/request'; import * as React from 'react'; import autobind from 'autobind-decorator'; @@ -82,6 +81,7 @@ type Props = { handleSetRequestGroupCollapsed: Function, handleSendRequestWithEnvironment: Function, handleSendAndDownloadRequestWithEnvironment: Function, + handleUpdateRequestMimeType: Function, // Properties loadStartTime: number, @@ -175,21 +175,6 @@ class Wrapper extends React.PureComponent { } // Special request updaters - async _handleUpdateRequestMimeType (mimeType: string): Promise { - if (!this.props.activeRequest) { - console.warn('Tried to update request mime-type when no active request'); - return null; - } - - const newRequest = await updateMimeType(this.props.activeRequest, mimeType); - - // Force it to update, because other editor components (header editor) - // needs to change. Need to wait a delay so the next render can finish - setTimeout(this._forceRequestPaneRefresh, 300); - - return newRequest; - } - _handleStartDragSidebar (e: Event): void { e.preventDefault(); this.props.handleStartDragSidebar(); @@ -375,6 +360,7 @@ class Wrapper extends React.PureComponent { handleGenerateCodeForActiveRequest, handleGenerateCode, handleCopyAsCurl, + handleUpdateRequestMimeType, isLoading, loadStartTime, paneWidth, @@ -599,7 +585,7 @@ class Wrapper extends React.PureComponent { updateRequestParameters={this._handleUpdateRequestParameters} updateRequestAuthentication={this._handleUpdateRequestAuthentication} updateRequestHeaders={this._handleUpdateRequestHeaders} - updateRequestMimeType={this._handleUpdateRequestMimeType} + updateRequestMimeType={handleUpdateRequestMimeType} updateSettingsShowPasswords={this._handleUpdateSettingsShowPasswords} updateSettingsUseBulkHeaderEditor={this._handleUpdateSettingsUseBulkHeaderEditor} forceRefreshCounter={this.state.forceRefreshKey} diff --git a/packages/insomnia-app/app/ui/containers/app.js b/packages/insomnia-app/app/ui/containers/app.js index 112caa302e..722ba00c87 100644 --- a/packages/insomnia-app/app/ui/containers/app.js +++ b/packages/insomnia-app/app/ui/containers/app.js @@ -39,6 +39,7 @@ import ErrorBoundary from '../components/error-boundary'; import * as plugins from '../../plugins'; import * as templating from '../../templating/index'; import AskModal from '../components/modals/ask-modal'; +import {updateMimeType} from '../../models/request'; @autobind class App extends PureComponent { @@ -356,6 +357,30 @@ class App extends PureComponent { }, 2000); } + async _handleUpdateRequestMimeType (mimeType) { + if (!this.props.activeRequest) { + console.warn('Tried to update request mime-type when no active request'); + return null; + } + + const requestMeta = await models.requestMeta.getByParentId(this.props.activeRequest._id); + const savedBody = requestMeta.savedRequestBody; + + const saveValue = (typeof mimeType !== 'string') // Switched to No body + ? this.props.activeRequest.body + : {}; // Clear saved value in requestMeta + + await models.requestMeta.update(requestMeta, {savedRequestBody: saveValue}); + + const newRequest = await updateMimeType(this.props.activeRequest, mimeType, false, savedBody); + + // Force it to update, because other editor components (header editor) + // needs to change. Need to wait a delay so the next render can finish + setTimeout(this._forceRequestPaneRefresh, 300); + + return newRequest; + } + async _handleSendAndDownloadRequestWithEnvironment (requestId, environmentId, dir) { const request = await models.request.getById(requestId); if (!request) { @@ -856,6 +881,7 @@ class App extends PureComponent { handleSetActiveEnvironment={this._handleSetActiveEnvironment} handleSetSidebarFilter={this._handleSetSidebarFilter} handleToggleMenuBar={this._handleToggleMenuBar} + handleUpdateRequestMimeType={this._handleUpdateRequestMimeType} />