usebruno / bruno

Opensource IDE For Exploring and Testing Api's (lightweight alternative to postman/insomnia)
https://www.usebruno.com/
MIT License
25.72k stars 1.17k forks source link

feat: save request/response history (including between launches) #411

Open cvmocanu opened 12 months ago

cvmocanu commented 12 months ago

Insomnia saves all the requests that were done. This history persists even if we restart Insomnia. This is a very useful feature when you want to have a quick look at how a response body looks.

One feature that Insomnia doesn't have (but which Postman has), and is very useful, is the ability to give a name to the request/response history entry.

Also, since the requests and responses may contain sensitive data, they shouldn't be saved in the collection directory, but outside of it, only on the local machine, just as Bruno handles secret environment variables.

carlonoelle commented 11 months ago

i need this for my current project so bad, that i gave in and signed up for insomnia. I have long running tasks that take up over 100 seconds and with bruno on error i only get a pop up that shows for 2 seconds without any real information and thats it. If i want to see it again i have to redo the request and wait again, what a bummer.

helloanoop commented 11 months ago

@carlonoelle

We'll support History very soon. Meanwhile I can suggest a workaround. In the v0.22.0 release, we have released support for collection level scripting. And you can log you response in the collection post script for debugging purpose. Here is our scripting docs: https://docs.usebruno.com/scripting/javascript-reference.html

Can you check and see if this is of any help?

image

carlonoelle commented 11 months ago

Thanks @helloanoop, for now that helps. That it is on the roadmap is good to know though since console is not persistent,

helloanoop commented 11 months ago

since console is not persistent

@carlonoelle here is one neat hack of using post response scripting in the collection level. You just need to create a logs directory inside your collection root folder and every request-response will get saved here.

const fs = require('fs');
const path = require('path');
const moment = require('moment');

const safeStringify = function (obj) {
  try {
    return JSON.stringify(obj, null, 2);
  } catch (err) {
    return obj
  }
};

const request = {
  url: req.getUrl(),
  headers: req.getHeaders(),
  method: req.getMethod(),
  body: req.getBody()
};

const response = {
  status: res.getStatus(),
  headers: res.getHeaders(),
  body: res.getBody()
};

const now = moment();
const formattedDate = now.format('YYYYMMDD-HHmmss');
const filename = path.join(bru.cwd(), 'logs', `${formattedDate}.json`);
const content = safeStringify({request, response}, null, 2);

fs.writeFileSync(filename, content);

You also need to add the scripts field in your bruno.json at the root of collection to allow fs access

{
   "scripts": {
    "filesystemAccess": {
      "allow": true
    }
  }
}
izturn commented 9 months ago

any progress?

testmonger commented 8 months ago

I like the suggested work around @helloanoop but I am getting an error (on Windows) Error invoking remote method 'send-http-request': VMError: Module 'C:\Users\xxx\AppData\Local\Programs\bruno\fs' is not allowed to be required. The path is outside the border!

Nevermind, I found this info about setting bruno to allow file system access: https://github.com/usebruno/bruno/discussions/385#discussioncomment-7246390 Logging is working now :)

helloanoop commented 8 months ago

@testmonger Please also add the scripts field in your bruno.json at the root of collection to fix the filesystem issue

{
   "scripts": {
    "filesystemAccess": {
      "allow": true
    }
  }
}
oklaiss commented 5 months ago

Any progress here? Persistent request history would be very useful.

lanthoor commented 4 months ago

@helloanoop @sanjai0py Is anyone working on this issue from your side? If not, could you assign this to me. I can start working on it.

Its-treason commented 4 months ago

@helloanoop @sanjai0py Is anyone working on this issue from your side? If not, could you assign this to me. I can start working on it.

This feature is already implemented in the Golden Edition

JaimeSerrano15 commented 2 weeks ago

Any updates on the history feature?

man1989 commented 2 weeks ago

If anyone still looking for postman like history can use the below script (this answer is an addition of what @helloanoop has mentioned here https://github.com/usebruno/bruno/issues/411#issuecomment-1756322017), Also follow bruno documentation to include fs in module whitelisting

function saveHistory(){
  const url = req.getUrl();
  const headers = req.getHeaders();
  const method = req.getMethod().toLowerCase();
  const reqBody = req.getBody();
  let bodyStr = ""
  if(reqBody){
    bodyStr += `body {\n${JSON.stringify(reqBody, null, 2).replace(/({|})/g, "  $1")}\n}`;
  }

  const now = moment();
  const formattedDate = now.format('YYYYMMDD-HHmmss');
  const filename = path.join(bru.cwd(), 'history', `${formattedDate}.bru`);

  const regex = /^(https?):\/\/([^\/\?]+)(?:[\/\?][^\?]*)?(?:\?(.+))?$/;
  const match = url.match(regex);
  const protocol = match[1];
  let queryParams = match[3];
  let queryStr = '';

  if(queryParams){
    queryStr += `query {`
    queryParams = queryParams.split("&").reduce((acc, q)=>{
        const [k, v] = q.split("=");
        acc[k] = v;
      return acc;
    }, {}); 

    for(const [k, v] of Object.entries(queryParams)){
        queryStr = queryStr+`\n  ${k}: ${v}`
    }
    queryStr += "\n}"
  }

  let headersStr = 'headers {';

  for (const [key, value] of Object.entries(headers)) {
    headersStr += `\n  ${key}: ${value}`;
  }
  headersStr += "\n}";

  const metaStr = `meta {\n  name: ${formattedDate}\n  type: ${protocol}  seq: 1\n}`;
  const reqStr = `${method} {\n  url: ${url}\n  auth: ${ req.auth || 'none'}\n}`;

  const template = `${metaStr}\n\n${reqStr}\n\n${headersStr}\n\n${bodyStr}`;

  fs.writeFileSync(filename, template);
}