Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change request body in pre-request script #4808

Closed
coder-free opened this issue Jul 11, 2018 · 53 comments
Closed

Change request body in pre-request script #4808

coder-free opened this issue Jul 11, 2018 · 53 comments

Comments

@coder-free
Copy link

I want crypt the request body.
For example,
request body set to this:
image

and pre-request script set to this:
image

and logged the "encryptData" value is encrypted. But the server received data is not encrypt, still is '{"a":"b"}'

@numaanashraf numaanashraf changed the title how to set request body in pre-request script Change request body in pre-request script Jul 11, 2018
@numaanashraf
Copy link
Member

@zfavourite99 We do not support changing request.body through scripts at the moment. A possible workaround for your use case is to use environments, and keep unencrypted request body in the script.

screen shot 2018-07-11 at 12 55 36 pm

screen shot 2018-07-11 at 12 55 40 pm

@numaanashraf
Copy link
Member

Related to #4631

@coder-free
Copy link
Author

I have many request all is this function to encrypt. So, I created a collection for these requests. I hope the encrypt and decrypt scripts in the collection. Like this:
image
If use this "possible workaround", then I need modify every request pre-request and test scripts, that is tedious.
So, I hope postman has this feature in the future. Thanks.
And #4809 feature is twinning.

@feizeikesi
Copy link

+1

@madmax911
Copy link

@zfavourite99 We do not support changing request.body through scripts at the moment. A possible workaround for your use case is to use environments, and keep unencrypted request body in the script.

screen shot 2018-07-11 at 12 55 36 pm screen shot 2018-07-11 at 12 55 40 pm

That gave me an idea to solve my CRLF issue - thanks man!

image

@mkulgeorge
Copy link

Hi numaanashraf,

Storing the value in the environment variable and manipulating that in pre-request Script and assigning that environment variable to the body.
Very good workaround for changing the POST body parameters dynamically.
This was very useful.

Thanks.

@shamasis
Copy link
Member

We added mutating URLs and headers for requests from within pre-request script ... mutating other parts like auth and body (to some extent) would follow in short to mid term. :-) Meanwhile, in UI we need to have ways to see what exactly was sent (since programmatic changes are hard to spot.)

@kibalion2427
Copy link

kibalion2427 commented Aug 10, 2019

@madmax911 Your solution was very helpfull for me. Thanks

@micmania1
Copy link

micmania1 commented Oct 2, 2019

I've just hit this problem too. It would be great if there were hooks for after the environment variables had been set and the request was ready to send. I had to generate a signature based on the request body and while the environment variable solution {{encrypted_body}} would have worked, it makes things very hard to follow.

I need to apply a signature to every request in my collection which is why the {{encrypted_body}} wasn't my preferred solution.

I ended up taking the body and doing a manual string replace to generate the signature and let the environment variable do its thing later in the postman request cycle.

eg.

// The session ID can't be re-used so we need to create one on the fly
const sessionId = 'session-' + Date.now();
pm.environment.set('REQUEST_SESSION', sessionId);

// Hacky but works for my case
// Note: this does not modify the body
const body = pm.request.body.raw.replace(/{{REQUEST_SESSION}}/g, sessionId);

// Do whatever you need to generate the signature
const secret = pm.environment.get('API_SECRET');
const signature = customGenerateSignatureStuff(body, secret);
pm.environment.set('REQUEST_SIGNATURE', signature);

In my case, even a function to parse the body and place the environment variables would be handy, even if it didn't mutate the actual body. That would mean I get consistent variable replacement and don't have to use my own hacky string replace. There may be a function which does this, but i'm not too familiar with postman and couldn't find one.

@greensunrise
Copy link

greensunrise commented Mar 15, 2020

Not sure if this is related but I am running into same problem. I need a way to paste a raw http request string like below and generate postman request.

POST /search?q=test HTTP/2
Host: www.bing.com
User-Agent: curl/7.54.0
Accept: */*

{"key":"value"}

What I do currently is paste this whole HTTP request as request body and using JS I parse the HTTP request and completely reconstruct the request and send it. It works but it's all too magical as I can not see the request in the UI. Would appreciate if anyone have solved this?

@lvl99
Copy link

lvl99 commented Dec 9, 2020

@arlemi is there anywhere where we can vote up this feature so it can have higher priority?

@arlemi
Copy link
Collaborator

arlemi commented Dec 9, 2020

@lvl99 You can upvote by adding a 👍 on the first comment in this issue.

@solirpa
Copy link

solirpa commented Dec 29, 2020

priority 👍👍👍
our program always needs to change a obj to form-data.
Such as:

{
 product: {
 prefix:xxx,
 name: xxx,
 desc: xxx,
 ...
}

# form-data
dproduct: 1,
dproduct_prefix: xxxx,
dproduct_name: xxxx,
dproduct_descx: xxxx,
...

@baohouse
Copy link

My use case is injecting an "extensions" key into a GraphQL query request (yes, I realize that is not mentioned in the GraphQL spec; "extensions" is part of response, but not request). If we want to use Postman's GraphQL editor, then the workaround mentioned above will not allow us to do so. For now, my workaround is running a local Express.js proxy server that transforms request bodies before sending it off to the actual server.

@chris-rl
Copy link

chris-rl commented Feb 5, 2021

this would be very helpfull. I would like to use this to remove comments from the json request body. (because this isn't possible as well, see #3358 )

But I really don't like the workaround to put all the request data in the pre-request-script and just set the body from a variable. It is good to have this workaround, but it still is just a workaround.

@StrohmyerTR
Copy link

Linking this here, because it is a better description of the actual bug/enhancement (I do not agree with it being closed as a duplicate). #8466. Can someone please provide an update on this ticket. Thanks.

@jordanbisato
Copy link

2 years after the creation of issue and i'm here searching for the same thing.
Any updates on this?

@StrohmyerTR
Copy link

IMO, this bug should be closed, and #8466 reopened. This thread does not give a concise description of what many of us are looking for. @codenirvana

@codenirvana
Copy link
Member

codenirvana commented Apr 26, 2021

Hello everyone 👋
Postman v8.3.0 added support for mutating the request body in the pre-request scripts.

Example to set different body modes:

// Raw
pm.request.body.update('Hello World!');

// Form Data
pm.request.body.update({
    mode: 'formdata',
    formdata: [{
        key: 'foo',
        value: 'bar'
    }]
});

// URL Encoded
pm.request.body.update({
    mode: 'urlencoded',
    urlencoded: [{
        key: 'foo',
        value: 'bar'
    }]
});

// GraphQL
pm.request.body.update({
    mode: 'graphql',
    graphql: {
        query: `
            query Square($ten: Int!) {
                square(n: $ten)
            }
        `,
        variables: { ten: 10 }
    }
});

Example to mutate existing request body:

// Send Base64 encoded body
const rawBody = pm.request.body.toString();
const base64Body = btoa(rawBody);

pm.request.body.update(base64Body);
// Add a new param
pm.request.body.formdata.add({
    key: 'foo',
    value: 'bar'
});
// Strip JSON Comments
const rawData = pm.request.body.toString();
const strippedData = rawData.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g) => g ? "" : m)

pm.request.body.update(strippedData);

Please try it out and let us know if you face any issues.

Runtime Triage and Development automation moved this from Later to Ready Apr 26, 2021
@lvl99
Copy link

lvl99 commented Apr 26, 2021

Damn, need a micdrop emoji with that closed issue message 🎤 💥

@StrohmyerTR
Copy link

Hell yes. Thank you!!!

@jordanbisato
Copy link

jordanbisato commented Apr 26, 2021

A example to add json parameter on raw body:

 var data = JSON.parse(pm.request.body.raw);
 data.key = key;
 let body = {
     mode: 'raw',
     raw: JSON.stringify(data),
     options: {
         raw: {
             language: 'json'
         }
     }
 }
 pm.request.body.update(body);

@tibi-extera
Copy link

Just yesterday I was looking into how to update the body in pre-request scripts. My example is getting data no older than 30 days. This would have to update every day, hence the need to update the request body.

Thank you for adding this feature. Works great. 😁👍🍾🥂

@vdespa
Copy link

vdespa commented May 6, 2021

A example to add json parameter on raw body:

 var data = JSON.parse(pm.request.body.raw);
    data.key = key;

    let body = {
        mode: 'raw',
        raw: JSON.stringify(data),
        options: {
            raw: {
                language: 'json'
            }
        }
    }
    pm.request.body.update(body);

For creating a request body from scratch, it makes sense to take this approach.

I think this can be simplified while updating existing JSON. Not sure if this is the intended usage, but the output seems to be the same.

const body = JSON.parse(pm.request.body.raw);
body.foo = 'bar';
pm.request.body.raw = body;

Correct me if I am wrong @codenirvana

@flovogt
Copy link

flovogt commented Jan 3, 2022

Following code did it for me:

const rawData = pm.request.body.toString();
const changedData = rawData.replace("a", "b");
pm.request.body.update(changedData);

@coder-free
Copy link
Author

@codenirvana Hi, is it possible to add a method to change the response too?
like this:

pm.response.body.update(changedData);

@shubhbhargav
Copy link

@coder-free Can you please provide a use-case where you need to update the response?

@coder-free
Copy link
Author

coder-free commented Feb 2, 2022

@shubhbhargav
like the request.
My server response data is encrypted:

{
    "status": 1,
    "msg": "success",
    "data": "g/sUMvvlDVyStLAE5B9KlGRP+m9EVbMfZb9fhTPNf8Ja ...... WmR8LaKQRM/OHF6vUbs+QDQCnpgIi"
}

Now my Tests script is:

var jsonBody = JSON.parse(responseBody);

if (jsonBody.data !== null && jsonBody.data !== undefined && jsonBody.data !== "null") {
    var decryptedData = MyDecryptFunc(jsonBody.data);
    jsonBody.data=decryptedData;
    console.log("jsonBody:"+ jsonBody);
    // responseBody = JSON.stringify(jsonBody);
    pm.response.body.update(JSON.stringify(jsonBody));
}

image

I just want to see the decrypted result conveniently.

This need is not strong. Because I can also see the result from the console log. It's just not that convenient.

Thanks.

@shubhbhargav
Copy link

This is interesting. Thanks for sharing it @coder-free. I would like to recommend an alternate to console (I know it's not ideal).
Have you tried the visualizer feature: https://learning.postman.com/docs/sending-requests/visualizer/? You can decrypt the response like the above and use pm.visualizer.set(...) to render it in the response tab under Visualize.

The idea of visualizer is to render customized responses, similar to this use-case. Let me know if that serves your use-case. :)

@StrohmyerTR
Copy link

StrohmyerTR commented Feb 3, 2022

You have two options - one, shubhbhargav, describes above. Your second option is to send your request in a pre-request script, parse the response, decrypt your string, and call pm.request.body.update() to be sent to the https://postman-echo.com/post API. I have an example of each, let me know if you would like to see an example of the second option I just described.

Here is an example of the first option, which will automatically copy your string to clipboard as well..:

var isJson = pm.response.headers.all().some(header => { return header.value.includes('application/json'); });

var data = isJson ? MyDecryptFunc(pm.response.json().data) : null;

function MyDecryptFunc(string) { return atob(string); // whatever resides in your decrypt function.. }

`let template =
{{insert backtick here}}

<textarea id='copy' style='width:100%;height:98%;'></textarea> <script> pm.getData(function (error, data) { var node = document.getElementById('copy'); if (data.response === null) { node.textContent = 'Response was not in JSON format'; } else { node.textContent = data.response; var selection = document.getSelection(); selection.removeAllRanges(); node.select(); document.execCommand('copy'); selection.removeAllRanges(); document.getElementById('copy').textContent = "Data copied to clipboard:\\n\\n" + data.response; } }); </script>

{{insert backtick here}};`

pm.visualizer.set(template, { response: data });

(Sorry for all the post edits.. Not sure how to write nested backticks in markup...)

@coder-free
Copy link
Author

@shubhbhargav @StrohmyerTR Thanks. Visualizer is a great solution. Using it not only gives me the results I want. More additional features can be implemented if more time is invested.

@chris-rl
Copy link

chris-rl commented Apr 5, 2022

@codenirvana

Hello everyone wave Postman v8.3.0 added support for mutating the request body in the pre-request scripts.

(...)

// Form Data
pm.request.body.update({
    mode: 'formdata',
    formdata: [{
        key: 'foo',
        value: 'bar'
    }]
});

(...)

Please try it out and let us know if you face any issues.

Hey!
Thanks for adding support to update the request body.

I'm struggling with setting the file in the form-data request.

My request looks like this:

pm.sendRequest("https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Neckertal_20150527-6384.jpg/640px-Neckertal_20150527-6384.jpg", function (err, response) {
    const stream = response.stream;
    // const data = response.dataURI();
    
    // set Form Data request body
    pm.request.body.update({
        mode: 'formdata',
        formdata: [
            {
                key: 'id',
                value: pm.variables.replaceIn('{{$randomUUID}}')
            },
            {
                key: 'file',
                type: 'file',
                value: stream  // this is not working: "Not a valid image file"
                // value: data  // this is not working: "Not a valid image file"
            }
        ]
    });

});

How is it possible to set the file of a formdata using pre-request scripts?

@vdespa
Copy link

vdespa commented Apr 7, 2022

@chris-rl I guess the question here is how to submit a form-data request to upload a file without providing a file. AFAIK, this is not possible, not even from a regular Postman request.

I don't know a way to upload a file by directly providing the content. Correct me if I am wrong.

@chris-rl
Copy link

chris-rl commented Apr 8, 2022

@vdespa Yes, that's probably true. I'm not too much into the technical details on how form-data requests are working internally. But I guess at some point the file will be loaded and sent to the endpoint, right? There should be a way of doing this manually.
Any ideas are appreciated.

Maybe another idea would be to save the downloaded file temporarily and then use the path to the temp file 🤔
Would this be possible in a pre-request script?

@vdespa
Copy link

vdespa commented Apr 8, 2022

@chris-rl I think the expectation is that the file exists somewhere on the disk. However, you can't write files from Postman, unless you rely on an externals script that does that for you.

@chris-rl
Copy link

chris-rl commented Apr 8, 2022

@vdespa Hm, how would using an external script work?

Another idea: Would it be possible to point to a file that is not located on a local disk, but in a remote location? Maybe just provide the URL where it could be downloaded?

Anyways, thanks for your input @vdespa!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests