mirror of
https://github.com/hoppscotch/hoppscotch.git
synced 2026-04-25 16:55:59 +03:00
[GH-ISSUE #218] Implement pre-request and post-request scripts (and request chaining) #79
Labels
No labels
CodeDay
a11y
browser limited
bug
bug fix
cli
core
critical
design
desktop
discussion
docker
documentation
duplicate
enterprise
feature
feature
fosshack
future
good first issue
hacktoberfest
help wanted
i18n
invalid
major
minor
need information
need testing
not applicable to hoppscotch
not reproducible
pull-request
question
refactor
resolved
sandbox
self-host
spam
stale
testmu
wip
wont fix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/hoppscotch#79
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @NBTX on GitHub (Oct 25, 2019).
Original GitHub issue: https://github.com/hoppscotch/hoppscotch/issues/218
Originally assigned to: @nickpalenchar, @NBTX on GitHub.
Support for pre-request and post-request scripts should be added.
Essentially this means a user should be able to enter some JavaScript code they want executed before a request to generate values - e.g. a random UUID for a request header.
Additionally, a user should be able to enter some JavaScript code they want executed after a request either for the purposes of chaining requests (i.e. automatically setting parameters for a request to data returned from a previous request) or for the purposes of presenting data.
This should work like Postman's Pre-Request Scripts.
@NBTX commented on GitHub (Oct 25, 2019):
This issue has been created to supersede #139 and #196. Ideally it should work in conjunction with #91 and #147.
@jgroom33 commented on GitHub (Oct 25, 2019):
I don't think a scripting language should be implemented. The scripting language is a crutch that ends up as garbage collection.
In place of a scripting language, a templating engine and some key handling should be implemented.
Each request in a collection would have a
whenkey. This should be evaluated as a truthy. And when it evaluated to true, that request will execute.@NBTX commented on GitHub (Oct 25, 2019):
Can you provide some justification as to why you think that?
Also, we don't just want boolean checks, in some cases we want to use data from other fields - or the response payload in the next request. Or we want to rearrange and view data in the response payload.
@jgroom33 commented on GitHub (Oct 25, 2019):
There should be a default behavior where all responses are stored automatically. No scripting should be required for this. The values from all previous calls should be available as {{ foo.response.id }}
This library is a good example
Ansible uses the same concept and the result is a much cleaner implementation.
Postman should not be used as a model for implemention because they are fine with a massively bloated json collection object because they don't care about how that object looks in a git commit. They want to sell their subscription service to a UI tool, not something that is code commit friendly.
Have you ever tried to revision control a postman collection?
@nickpalenchar commented on GitHub (Oct 26, 2019):
Various data should be available from the previous request, yes. But in the case of the first request there is not much data to use. A user might want to set non request related data, or may want to format data from a previous request differently, or conditionally. I don't quite follow the point on postman's json collection. Json representation for requests are more used for imports/exports, not for reading.
Templating can still be used as well, and I agree it will probably be more frequently used than script. These two ideas can be thought of as separate features, and once added both or one could be used, or neither.
@jgroom33 commented on GitHub (Oct 27, 2019):
For the initial call, an execution parameter should be available to load a set of variables. These should be loaded as json, not as key value pairs with only strings.
I do not presume that this project will attempt to make available a global repository for sharing collections. That would require operational costs. As such, the collections would need to be committed to a revision control platform like GitHub. If the postman approach to pre/post request scripts is followed, those commits will become indecipherable and code review on a collection will be a challenge.
The solution to these challenges have already been solved by other projects. Search for the following "ansible loops" "ansible when" "ansible register"
The addition of a register key with a jsonquery capability would probably handle the majority of use cases.
It might look something like this in a UI:
@nickpalenchar commented on GitHub (Oct 27, 2019):
I agree that jsonpath is often faster and cleaner and can be used for most situations. Storing a pre-request script in places like json for history, etc, does look a bit cumbersome, as storing a long string of text always does. Still, I'm tempted to go with a "why not have both" approach here? I'm absolutely biased on this opinion, considering I've already put in some time and found an exciting implementation. But I don't see them solving the same problem exactly, nor do I see how the presence of one of these features impedes the other.
The way I see it, each response should, as you've mentioned, be available via json format. As a smaller detail, I see the ability to interpolate the jsonpath directly:
Both are accessing data on a response object that's made available from previous requests in the case of chaining. This can be the default behavior and anyone could stop with just this functionality, which I believe satisfies the suggestion of templating and key handling.
However, if someone wished to use scripting, the same data would be available in that environment, with the ability to add more data which would be available to the upcoming request.
The data then available for the request would be:
Additionally this feature could be easily enhanced by making API-ey functions available in the environment, like a random UUID creating function. It also lays some groundwork for testing assertions between calls, perhaps halting a chain of requests if a previous one does not respond as expected, etc. Lastly, some people just like scripting over configuration for whatever reason; let the user decide how and which parts of postwoman they want to use.
So why not have both?
@liyasthomas commented on GitHub (Oct 27, 2019):
Processing env variables with scripting language and a template engine together seems like an exclusive feature. While ansible and other projects making use of template engines do have few limitations over manipulating and enforcing customs rules on env vars that could only be satisfied with the support of a scripting language.
This might be an overkill, but that's exactly what I'd expect in a better API testing tool.
@jgroom33 commented on GitHub (Oct 27, 2019):
I think that if a scripting language is implemented before a more structured approach, then the scripting language will become the default usage. Since most people are coming from postman, they would naturally try to find the same behavior instead of attempting the more desired approach.
Template engines provide plugin support for custom methods. So when there are requirements to perform advanced parsing, the template engine plugins could be used. This would place a focus on a more structured approach, but advanced users could still write code. Then, as commonalities present themselves in the template plugins, they can be included as supported features.
@jgroom33 commented on GitHub (Oct 27, 2019):
Regarding the topic of request chaining:
set next requestis terrible IMO.Something similar to the following features in ansible should be implemented:
This allows a multilevel file directory (instead of a massive json collection object like postman) to organize the requests or groups of requests.
As an example:
login/request.json
action/users.json
The above approach would allow reuse of:
@nickpalenchar commented on GitHub (Oct 28, 2019):
We won't know what the default usage would be until we've released something, but users tend to choose what works for them. If templating followed scripting, anyone who was struggling with scripting would explore the new alternative. Even if scripting becomes the default usage, what's the harm exactly? That suggests it satisfies their use cases enough not to switch.
If advanced users could script via plugins that could involve heavy reuse of this feature anyway. It's a small difference of viewpoint, using a "transform"-like extension in a template that is defined in code vs defining the code and interpolating its final value in the request.
@NBTX commented on GitHub (Oct 29, 2019):
Personally I still haven't seen an objective downside to including scripting.
To me scripting is a less cumbersome way of implementing https://github.com/liyasthomas/postwoman/issues/218#issuecomment-546724014 (by using simple JavaScript statements rather than JSON.)
Plus, scripting could theoretically use 'includes' (as shown in that comment) and it would make the requests in Postwoman self-documenting as one can see - at a glance - all of the variables that get assigned programmatically.
@jgroom33 commented on GitHub (Oct 29, 2019):
There may not be a harm in implementing scripting. I think I was most concerned about how postman does not allow a DRY approach. This would lead to duplicated code across requests which became difficult to update.
These features would make the scripting more focused:
includeexecution of single file or directory@NBTX commented on GitHub (Oct 30, 2019):
Re-opening as PR #231 is more of an MVP rather than the full solution to this script.
@liyasthomas commented on GitHub (Nov 23, 2019):
@nickpalenchar would you mind looking into post-request scripts implementation like pre-request scripts..? I know you're busy, but I hope it would be a peace of cake for you since you introduced pre-request scripts.
@nickpalenchar commented on GitHub (Nov 23, 2019):
Sure can.. yes my schedule's really filled up the past couple months, but I’ll have some free time tomorrow 🙌
On Fri, Nov 22, 2019, at 10:44 PM, Liyas Thomas wrote:
@liyasthomas commented on GitHub (Nov 23, 2019):
That's great!
@nickpalenchar commented on GitHub (Nov 25, 2019):
So the post-request step is plausible but not a piece of cake for a few reasons:
The post-request script feature is really only useful when it has data from a previous request. So really, there is no post-request script, only chained requests, each with a pre-request script that has access to data from the request that came before it.
So I think it's important that the request chaining gets implemented first. My idea is that the entire request section to the left of the history is able to get copied and paginated. There could be numbered tabs on top so the user could switch between request numbers, something like the poorly made ascii-UI shows below
For this to happen, the entire request building logic needs to be refactored into its own component. This is a HUGE obstacle that is currently taking lots of time. Many abstractions between methods, data, refs, and the store need to be delicately handled.
The end result is a request-building component that has its own request data, and can expand to multiple instances as needed. The index.vue page then becomes responsible for dispatching each request, getting the response data back, and then dispatching the following request with the data from the previous request (among other functions like storing and saving in the history). The user is free to edit the requests independently, possibly even rearrange them.
I've started with this refactoring idea In this branch I recommend pulling and running it locally to get a better sense of what I mean. Many pieces of functionality have been correctly refactored but other part are regressing (like the saving to collections).
To summarize: Refactoring into a requestBuilding component is needed before we can finish the rest of this elegantly. It's not too hard, but the large refactor needs to happen all at once in order to get merged back in before it diverges from other PR's.
Thoughts? I'll try to explain more tomorrow--I'm out of time tonight!
@liyasthomas commented on GitHub (Nov 25, 2019):
I understand the difficulties, and I'll surely contribute into it. I guess request section component is a great idea so there could be provision for tabbed requests too. I know we've come a long way from initial commit. We can pull this off too.
@nickpalenchar commented on GitHub (Nov 25, 2019):
Awesome! Yes do feel free to add to it. I'll also try to look at it a bit more in another 24 hours, but any other contributions will surely be helpful.
@liyasthomas commented on GitHub (Feb 9, 2020):
This issue is resolved. (decoupling request-chaining feature from this issue).
@1ace commented on GitHub (Mar 11, 2022):
@liyasthomas Hi! you have closed a number of issues about request chaining/dependencies in favour of this one, which you then closed saying it didn't cover that feature anymore. Is there another issue tracking this? Or has this feature been implemented in the mean time?
I'm currently looking for a tool that does have this feature, and for some reason none of them do, so I'm really hoping this one does :)
@liyasthomas commented on GitHub (Mar 11, 2022):
As of now, chaining requests feature is not in our priority list. This particular issue ticket was to track pre-request and post-request script enhancements, which we already implemented and hence closed.
I will create another issue to track request chaining feature as we ship our other priority features.
Feel free to contribute to the source code and I'd appreciate if you can create a discussion thread under this repo on your feature request for future communications.
@1ace commented on GitHub (Mar 11, 2022):
Thanks for the really quick answer!
I have created a discussion about requests chaining/dependency management, and I'll evaluate in the next few weeks using Hoppscotch as a replacement for Postman (that we currently use). If the result is conclusive, I'll dig into the code and see if I can contribute this feature 👍
Please comment on that discussion if there was any attempt at this feature, so that it doesn't get forgotten :)