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

async respond_with / Respond #84

Open
johannescpk opened this issue Jan 7, 2022 · 7 comments
Open

async respond_with / Respond #84

johannescpk opened this issue Jan 7, 2022 · 7 comments

Comments

@johannescpk
Copy link

johannescpk commented Jan 7, 2022

Thanks for wiremock! It seems that it's currently not possible to execute async code in the respond method or respond trait. It'd be useful to have it natively supported by wiremock.

Wasn't able to find a workaround, tried

.respond_with(move |req: &Request| {
        let handle = tokio::runtime::Handle::current();
	std::thread::spawn(move || {
		handle.block_on(async {
			// Some async call
		});
	})
	.join()
	.unwrap();

	ResponseTemplate::new(200)
})

but that's blocking the tokio runtime since the test runs as #[tokio::test].

@LukeMathWalker
Copy link
Owner

What kind of async tasks are you trying to perform in response_with?

@johannescpk
Copy link
Author

johannescpk commented Jan 10, 2022

It's some business logic, in this case it's tower::util::Oneshot calls.

@LukeMathWalker
Copy link
Owner

I'll need an example a bit more concrete to understand if it makes sense to extend the library or not 😄

@johannescpk
Copy link
Author

johannescpk commented Jan 10, 2022

Personally I'd say it'd make sense to have callbacks be async in general unless there's a good reason to not do it. Reason being that it's easy to have a sync wrapper in an async context but it's hard the other way around.

In this specific case I'm testing the correct setup of a FHIR Subscription. The HTTP request flow looks like this. The relevant part is 9. and 10. where a handshake takes place.

Basically:

Client --[ HTTP POST Create Subscription ]--> Server
Server --[ HTTP POST Handshake ] --> Client

The library exposing the functionality has an async method create_subscription which should only return once the subscription was created in full, with a successful handshake. To test this I have two MockServer instances, one being the client and one being the server. The test then calls create_subscription and only after the subscription mock finished (the server mock returning the ResponseTemplate) it should do a mocked handshake call to the client so create_subscription returns. The communication inside the client to signal that the handshake arrived is made with tokio::Notify. In the tests I'm now also using Notify as a workaround (requires me to juggle a tokio::join! later in the test), but I'd like to directly use https://github.com/tokio-rs/axum/blob/main/examples/testing/src/main.rs#L64-L67 which is async.

@rminderhoud
Copy link

rminderhoud commented Mar 16, 2023

Hey there, thanks for this great library! I recently ran into the same issue. Trying to call some async code from a custom responder. Basically, I am trying to create a mock to validate an HTTP payload and one of the libraries to parse multipart data is async. e.g.

struct CustomResponder;

impl wiremock::Respond for CustomResponder {
    fn respond(&self, req: &wiremock::Request) -> wiremock::ResponseTemplate {
        // ... some logic ...
        
        // This is an async function so can't be used here
        let multipart = multer::Multipart::with_reader(req.body.as_slice(), boundary);
        
        // ... validate multipart data ...
    }

A lot of http libraries have gone async so it would be useful to be able to use them

@moh-eulith
Copy link

Just another example in case it helps:
In the response method, I have to call another service (another mock which implements json rpc), which is async.

sjoerdsimons added a commit to collabora/gitlab-runner-rs that referenced this issue Feb 18, 2024
The multipart crate has been unmaintained for a while, replace with
multer which e.g. also used by axum. Unfortunately multer is async only,
while the wiremock Response trait is sync[0]. So that does require some
hoops to jump through for now.

0: LukeMathWalker/wiremock-rs#84

Signed-off-by: Sjoerd Simons <[email protected]>
sjoerdsimons added a commit to collabora/gitlab-runner-rs that referenced this issue Feb 18, 2024
The multipart crate has been unmaintained for a while, replace with
multer which e.g. also used by axum. Unfortunately multer is async only,
while the wiremock Response trait is sync[0]. So that does require some
hoops to jump through for now.

0: LukeMathWalker/wiremock-rs#84

Signed-off-by: Sjoerd Simons <[email protected]>
sjoerdsimons added a commit to collabora/gitlab-runner-rs that referenced this issue Feb 28, 2024
The multipart crate has been unmaintained for a while, replace with
multer which e.g. also used by axum. Unfortunately multer is async only,
while the wiremock Response trait is sync[0]. So that does require some
hoops to jump through for now.

0: LukeMathWalker/wiremock-rs#84

Signed-off-by: Sjoerd Simons <[email protected]>
sjoerdsimons added a commit to collabora/gitlab-runner-rs that referenced this issue Feb 28, 2024
The multipart crate has been unmaintained for a while, replace with
multer which e.g. also used by axum. Unfortunately multer is async only,
while the wiremock Response trait is sync[0]. So that does require some
hoops to jump through for now.

0: LukeMathWalker/wiremock-rs#84

Signed-off-by: Sjoerd Simons <[email protected]>
@bnjbvr
Copy link

bnjbvr commented Nov 5, 2024

Wanted to share my 2c and use case, that I posted on the wrong repo initially lol.

First of all, thanks for this project, it's quite useful for us over at the Matrix Rust SDK project.

There's one thing that I miss and would like to see: the ability to set async custom responders. Right now, it's possible to respond_with a static ResponseTemplate, or a sync closure Fn(&Request) -> ResponseTemplate. I'd like to be able to also use something that returns a future there, and for wiremock to handle it for me.

This would allow for new functionality that I'd also like to be able to use, and that as far as I can't tell doesn't exist (but that would be great to prove me wrong :))

  • have perfect control on the timing of a request, by using some kind of signal/oneshot handler, that's waiting from something from the main task before responding in the mocked endpoint. With this, I can simulate all sorts of race conditions, and the way I do it right now is… not great.
  • more generally, use tokio synchronization primitives in the response templates :-) Using a sync std Mutex shared by the test task and the custom responder wouldn't work. (I seem to vaguely recall that wiremock uses some locks under the hood too, before responding to a request, and that was an issue for me, but I don't exactly recall how, unfortunately.)

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

No branches or pull requests

5 participants