bruno icon indicating copy to clipboard operation
bruno copied to clipboard

Option to save response in utf-8 instead of Unicode #1765

Open ialloyd opened this issue 11 months ago • 4 comments

This PR introduces a new feature that allows users to save response data in UTF-8 format. Previously, the response data was saved in Unicode format by default. With this update, users working with non-English character sets, like Japanese, will have their data saved correctly in UTF-8 format. This enhances Bruno’s usability and accessibility for a wider range of users.

ialloyd avatar Mar 14 '24 06:03 ialloyd

This resolves #1765

jwetzell avatar Jul 31 '24 01:07 jwetzell

Hey @ialloyd, we tested this PR, but it breaks when the response is an image.

sanjai0py avatar Aug 02 '24 14:08 sanjai0py

Maybe headers could be used to drive how the data is processed for saving? or maybe some sort of "response type" setting associated with the requests.

jwetzell avatar Aug 02 '24 16:08 jwetzell

Good point @jwetzell !

@sanjai0py Here is some pseudo code. Can you try this and create a new PR No changes are needed in UI layer. bruno/packages/bruno-electron/src/ipc/network/index.js

// save response to file
  ipcMain.handle('renderer:save-response-to-file', async (event, response, url) => {
    try {
      const getHeaderValue = (headerName) => {
        const headersArray = typeof response.headers === 'object' ? Object.entries(response.headers) : [];

        if (headersArray.length > 0) {
          const header = headersArray.find((header) => header[0] === headerName);
          if (header && header.length > 1) {
            return header[1];
          }
        }
      };

      const getFileNameFromContentDispositionHeader = () => {
        const contentDisposition = getHeaderValue('content-disposition');
        try {
          const disposition = contentDispositionParser.parse(contentDisposition);
          return disposition && disposition.parameters['filename'];
        } catch (error) {}
      };

      const getFileNameFromUrlPath = () => {
        const lastPathLevel = new URL(url).pathname.split('/').pop();
        if (lastPathLevel && /\..+/.exec(lastPathLevel)) {
          return lastPathLevel;
        }
      };

      const getFileNameBasedOnContentTypeHeader = () => {
        const contentType = getHeaderValue('content-type');
        const extension = (contentType && mime.extension(contentType)) || 'txt';
        return `response.${extension}`;
      };

      const getEncodingFormat = () => {
        const contentType = getHeaderValue('content-type');
        const extension = (contentType && mime.extension(contentType)) || 'txt';

        if (extension && ['json', 'xml', 'html', 'yml', 'yaml', 'text'].includes(extension)) {
          return 'utf-8';
        }

        return 'base64';
      }

      const fileName =
        getFileNameFromContentDispositionHeader() || getFileNameFromUrlPath() || getFileNameBasedOnContentTypeHeader();

      const filePath = await chooseFileToSave(mainWindow, fileName);
      if (filePath) {
        await writeBinaryFile(filePath, Buffer.from(response.dataBuffer, getEncodingFormat()));
      }
    } catch (error) {
      return Promise.reject(error);
    }
  });

helloanoop avatar Aug 07 '24 12:08 helloanoop

Closing this PR as another PR with expected changes has been merged. The v1.25.0 version of Bruno contains the fix.

sanjai0py avatar Aug 16 '24 06:08 sanjai0py