question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add way to detect and log exceptions in request handlers.

See original GitHub issue

Is your feature request related to a problem? Please describe.

I’m currently using msw for mocking network requests in jest tests. I haven’t found an easy way to detect when exceptions are thrown in my request handlers. For example, the code below will produce an exception due to bug and msw will silently convert the error to a 500 response.

rest.post("/authorize", (req, res, ctx) => {
	// ... some authorization logic ...
	
	// getCurrentUser throws because there is a bug in it
	const user = getCurrentUser();

	// ... more authorization logic ...

	return res(
		ctx.status(200),
		ctx.json({
			redirectUri,
		}),
	);
});

Describe the solution you’d like

None of the lifecycle events are emitted when the exception is thrown. A new lifecycle event like response:error would allow me to write something like

worker.on('response:error', (res, reqId, error) => {
	console.error("Request handler threw error.", error);
});

This would help developers quickly ascertain the source of some test failures without having to follow a chain of symptoms back to a failed msw request handler.

Describe alternatives you’ve considered

Alternative 1

I could use a higher order function wrapper like

rest.post("/authorize", logAndRethrowErrors((req, res, ctx) => {
	// ...
}));
function logAndRethrowErrors(fn) {
	return (...args) => {
		try {
			return fn(...args);
		} catch (e) {
			console.error(e);
			throw e;
		}
	};
}

Pros: This code logs an error which likely includes helpful stack trace.

Cons: This requires all developers on my project to add logAndRethrowErrors which may be easy to forget. I’d instead prefer to fail loudly globally.

Alternative 2

I could do something like this during setup

// Setup
const server = setupServer(...handlers);
const requestsWithoutResponses = new Map();
server.on("request:start", (req) => {
	requestsWithoutResponses.set(req.id, req);
});
server.on("request:end", (req) => {
	requestsWithoutResponses.delete(req.id);
});

and this during teardown

// Teardown
server.close();
for (const [, req] of requestsWithoutResponses) {
	console.error(
		"Request received no response. This likely means the request handler threw an error, the error was swallowed by msw, and silently converted to a 500 response.\nRequest:",
		req,
	);
}

and assuming any request that did not emit "request:end" resulted in an exception.

Pros: This gives me the global ability fail loudly.

Cons: Does not have the error message to emit.

Alternative 3

Combine alternative 1 and 2 above.

Pros: Allows us to emit error trace with logAndRethrowErrors and use the fallback teardown code to hint that a developer forgot logAndRethrowErrors.

Cons: This is quite a few lines of non-standard tooling for something that could be done succinctly if msw offered a simple API for it.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:3
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
MartinJaskullacommented, Apr 10, 2022

What about

  • request:handlerError instead of request:unhandledException (because it is not unhandled)
  • Not changing anything in handleRequest.tsx
  • Wrapping const result = await handler.run(request, resolutionContext) in until and emitting the error + handler there

Users are only interested in errors occurring inside their handlers, but not all errors that could occur in getResponse

1reaction
kettanaitocommented, Apr 6, 2022

Hey, @MartinJaskulla! We’d love to have you involved with this. The issues don’t necessarily have to have a “help wanted” label for anybody to join in! We usually use “help wanted” meaning “we can’t do this on our own”.

What does the tag “needs:tests” mean?

It means that this particular issue needs automated tests to be written to verify it. It also means that we don’t have such tests, or the tests we have are insufficient in covering it.

In this particular case, we don’t have any tests because the solution to the issue is to extend an existing life-cycle events API with a new request:unhandledException event. Tests should be added for that event.

What this task is about

First, we need to extend an existing interface of lifecycle events:

https://github.com/mswjs/msw/blob/6fc89f762681aa7f6f697ea78fa5f7c736b35c5d/src/sharedOptions.ts#L17-L24

I propose to add a new request:unhandledException event.

Then we need to go to the common ground between setupWorker and setupServer that handles request and emit the new event whenever exception occurs during request handler:

https://github.com/mswjs/msw/blob/6fc89f762681aa7f6f697ea78fa5f7c736b35c5d/src/utils/handleRequest.ts#L67-L72

We can wrap getResponse in until and handle the exception like so:

const [handlerException, lookupResult] = await until(() => getResponse(...))

if (handlerException) {
  emitter.emit('request:unhandledException', handlerException, handler)

  // Still throw the error to propagate up the request handling pipeline
  // and be transformed into "500 Internal Server Error".
  throw handlerException
}

And then cover this scenario with tests. We can use existing tests for reference. I can also help you with tests.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Exception Handling and Logging in ASP.NET Core Web API
Learn the proper way of exception handling and logging in ASP.NET Core Web API. Read and follow my step-by-step tutorial.
Read more >
Exceptional Logging of Exceptions in Python - Loggly
The magic here is with exception method. ( logger is your application's logger object—something that was returned from logging.
Read more >
Complete Guide to Exception Handling in Spring Boot
This article showcases various ways to handle exceptions in a Spring Boot Application.
Read more >
Diagnose exceptions in web apps with Application Insights
The simplest way to report is to insert a call to trackException() in an exception handler. JavaScript. Copy. try { // .
Read more >
Exception Handling in Spring MVC
You can add extra ( @ExceptionHandler ) methods to any controller to specifically handle exceptions thrown by request handling ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found