resty icon indicating copy to clipboard operation
resty copied to clipboard

WIP: Add user defined OnBeforeRequest middlewares on all response paths, improve documentation

Open lggomez opened this issue 5 years ago • 8 comments

Work for #356

lggomez avatar Sep 08 '20 15:09 lggomez

Codecov Report

Merging #372 into master will decrease coverage by 0.28%. The diff coverage is 69.23%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #372      +/-   ##
==========================================
- Coverage   96.19%   95.90%   -0.29%     
==========================================
  Files          10       10              
  Lines        1235     1246      +11     
==========================================
+ Hits         1188     1195       +7     
- Misses         26       29       +3     
- Partials       21       22       +1     
Impacted Files Coverage Δ
client.go 95.56% <69.23%> (-1.16%) :arrow_down:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update d2ba00f...b5d18e3. Read the comment docs.

codecov[bot] avatar Sep 08 '20 15:09 codecov[bot]

I made the suggested changes

Any reason, why these two (responseLogger, parseResponseBody) response middleware is not called in the proposal? At least I think logger one needs to be executed.

I would like to be able to use a custom logger (at least in my use case), and I can see the default responseLogger mw injected which is debug only as a basis for #345. parseResponseBody, at least, can be disabled via SetDoNotParseResponse, but I can't see a similar experience for this one yet (please correct me if I'm wrong)

For the general case of intercepting all return paths (including errors where responses can be in an invalid state) I'd leave that responsibility up to the user and their middleware implementation (unless otherwise specified in the documentation like the body drain mentions)

lggomez avatar Sep 10 '20 15:09 lggomez

To clarify a bit more about the use case: my application is designed to support debug flows on a per-request basis based on a flag so the current per-client configuration doesn't really fit and a user defined middleware in this setup could allow for per-request behaviors without coupling to the internal middlewares

lggomez avatar Sep 10 '20 16:09 lggomez

@lggomez I see your viewpoint and use case. Let's do the following -

  • With this PR, let's stick to current behavior, .i.e execute responseLogger, parseResponseBody middleware for all paths along with user-defined ones.
  • As part #345 solution exposing all middlewares to resty users via new sub-package 🤔 . This is maybe a breaking change, need to analyze a bit.
  • Also bringing debug setting per request is also an option.

Sounds like a plan?

jeevatkm avatar Sep 11 '20 00:09 jeevatkm

All of them sound fine; for the scope of the PR I'd keep with implementing just the first item for now

Regarding that, one of the issues of moving the internal middleware to all paths is that suddenly the applyResponseMiddlewares has to return an error:

  • For error paths, we don't use the error returned by it (it will break behavior and tests otherwise)
  • For the normal return path, use its error result for the wrapNoRetryErr(err) return value

I pushed the current change, so I'll await your opinion on this

lggomez avatar Sep 14 '20 13:09 lggomez

For error paths, we don't use the error returned by it (it will break behavior and tests otherwise)

@lggomez Do you mean returning an error of response middleware from L852, L866, and L875 it will break the existing behavior?

If it is not returned; then the previous error is getting eaten/suppressed by resty, isn't it?. Typically any libraries shouldn't eat any errors, only the end-user can make a decision on ignoring the error.

jeevatkm avatar Sep 15 '20 04:09 jeevatkm

Yeah, changing

                c.applyResponseMiddlewares(response)
		return response, err

to

		return response, c.applyResponseMiddlewares(response)

breaks the following (only on the first early return on the execute() method):

--- FAIL: TestClientRedirectPolicy (0.03s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x18 pc=0x77746d]

goroutine 84 [running]:
testing.tRunner.func1.1(0x815340, 0xbe0890)
	C:/Go/src/testing/testing.go:988 +0x314
testing.tRunner.func1(0xc0001e8a20)
	C:/Go/src/testing/testing.go:991 +0x400
panic(0x815340, 0xbe0890)
	C:/Go/src/runtime/panic.go:969 +0x174
github.com/go-resty/resty/v2.TestClientRedirectPolicy(0xc0001e8a20)
	C:/Users/a309586/DEV/GITHUB/resty/client_test.go:110 +0x2dd
testing.tRunner(0xc0001e8a20, 0x8a7428)
	C:/Go/src/testing/testing.go:1039 +0xe3
created by testing.(*T).Run
	C:/Go/src/testing/testing.go:1090 +0x379

This issue aside, the applyResponseMiddlewares() error would be shadowing the original execute() error, so doing this right is a bit hairier than I thought initially. We want to be able to cancel the middleware stack but we also want to be able to propagate accordingly the errors (maybe wrap the mw error?)

lggomez avatar Sep 16 '20 22:09 lggomez

@lggomez I'm sorry for the delay in response.

I think wrapping the error will be a good choice. Please go ahead. Thanks.

Also, streamlining this part in the next major version as breaking change will help everyone.

jeevatkm avatar Oct 07 '20 05:10 jeevatkm