-
Notifications
You must be signed in to change notification settings - Fork 847
Add set-body-from config item to header_rewrite #11472
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
Conversation
(cherry picked from commit 5bd9999) (cherry picked from commit 08c614ef0089b175a5b6cee205b748416efb87cd)
* Update response body to exclude headers * Update tests to check both response with headers and response body only * Update header_rewrite_custom_body.test.py * Fix tests to check headers and body (cherry picked from commit cb552b6) (cherry picked from commit e12f4798d0d46bd90c810f8f3a7a067ea3b2c76f)
(cherry picked from commit 964b12cc21a9a7c3f9d3fd50286e4cd2d2757bcc)
Remove whitespaces doc formatting fix Doc formatting fix
1b7bf2f to
fbb0537
Compare
|
The AuTest prefetch_overflow failed. The AuTest prefetch_bignum failed: |
| TSContDestroy(cont); | ||
| TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_CONTINUE); | ||
| } break; | ||
| case TS_EVENT_HTTP_SEND_RESPONSE_HDR: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the purpose of executing the continuation on this hook (since nothing is done)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pauses the original transaction to allow time to get the response from the second endpoint. The second endpoint will reenable the first once it has completed. It is written in the code for readability
tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py
Show resolved
Hide resolved
|
The AuTest transaction_data_sink failed. |
tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py
Outdated
Show resolved
Hide resolved
tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py
Show resolved
Hide resolved
tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py
Outdated
Show resolved
Hide resolved
tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py
Outdated
Show resolved
Hide resolved
| cond %{CLIENT-URL:PATH} = "200" | ||
| set-body-from http://www.example.com/404.html | ||
|
|
||
| cond %{READ_RESPONSE_HDR_HOOK} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the set-body-from operator require this hook condition in order to work properly? If so, maybe you should mention that in the documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not. I am using the path to differentiate the tests.
| map http://www.example.com/plugin_fail http://127.0.0.1:{0}/plugin_fail | ||
| map http://www.example.com/404.html http://127.0.0.1:{0}/404.html | ||
| map http://www.example.com/502 http://127.0.0.1:{0}/502 | ||
| """.format(self.server.Variables.Port, Test.RunDirectory)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest you also have a remap for a body URL like this:
Test.GetTcpPort("bad_port")
self.ts.Disk.remap_config.AddLine(f'map http://www.example.com/plugin_no_server http://127.0.0.1::{Test.Variables.bad_port}/plugin_no_server")
in order to verify proper behavior if it's not possible to connect to the server that provided the body that's set by the operator.
|
|
||
| cond %{READ_RESPONSE_HDR_HOOK} | ||
| cond %{CLIENT-URL:PATH} = "remap_fail" | ||
| set-body-from http://www.example.com/fail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, in all the test cases, we still do the original request to upstream, then entirely throw it away. Wouldn't more realistic test cases be with conditions checking response status or response headers?
If the intent is to always discard the original response, wouldn't it be better for the operator to execute in the remap pseudo hook, and set an error status there, to block the original request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
statichit is an example of a plugin that blocks the request to upstream by setting an error status in the DoRemap funciton:
trafficserver/plugins/statichit/statichit.cc
Line 639 in 0d004b3
| TSHttpTxnStatusSet(rh, TS_HTTP_STATUS_NOT_FOUND); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have written the tests to replicate what happens in production. Do you have an example of another test that only checks the response status?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the tests reflect how you would use this operator in production, why wouldn't you want to avoid the initial request to the upstream server, when the data it returns will always be entirely discarded?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The status is set from that initial request.
plugins/header_rewrite/operators.cc
Outdated
| // The transaction is reenabled with the FetchSM transaction | ||
| break; | ||
| default: | ||
| TSError("Warning: handleFetchEvents got unknown event: %d", event); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So in diags.log this will look like:
ERROR: Warning: ...
huh???
| TSCont fetchCont = TSContCreate(handleFetchEvents, TSMutexCreate()); | ||
| TSContDataSet(fetchCont, static_cast<void *>(res.txnp)); | ||
|
|
||
| TSHttpTxnHookAdd(res.txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, fetchCont); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suppose there is another continuation for the transaction, that is either after the continuation calling this exec func on the READ_RESPONSE_HDR_HOOK, or before fetchCont on the SEND_RESPONSE_HDR_HOOK And, suppose this continuation, like fetchEvent for the SEND_RESPONSE_HDR evert, does not call TxnReenable(). Seems like there could be a race condition, where the URL fetch body done event reenables for that other continuation by mistake.
Could you add a return value to the operator exec funtions, which would control whether the continuation running the exec functions called TxnReenable()? That way, no other continuations of transaction hooks would be run until the fetch of the body URL finished.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you are saying but I dont see how the exec func returning something would help. I think a return value would only have impact on header_rewrite rather than all plugins. This would also make changes to all of header_rewrite.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what I'm proposing, for the exec() function to return a flag that controls whether reenable is called: ywkaras@0ef4d24
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. I think it would be better to seperate these changes into 2 PRs because the change you are proposing impacts all of header rewrite.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I can put up a follow-on PR once this is merged.
|
[approve ci autest] |
| tr.Processes.Default.Command = ( | ||
| 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/200"'.format(self.ts.Variables.port)) | ||
| tr.Processes.Default.ReturnCode = 0 | ||
| tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_200.gold" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Testing against Streams.All seems to be making this test flaky/fragile. I think you need your gold file to be matched against Streams.stdout, which I think would just contain the body. You can test the response HTTP headers like this:
| tr.Processes.Default.Streams.stderr.Content = Testers.ContainsExpression("200 OK", "expected 200 response") |
JosiahWI
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Let's fix the AuTest so it isn't flaky.
|
This PR introduces this issue: #11549 |
* Revert "Update set-custom-body response body to exclude headers (apache#780)" This reverts commit cb552b6. * Revert "Add set-body-custom to header_rewrite options" This reverts commit 5bd9999. * Add set-custom-body config item to header_rewrite (apache#11472) * Add set-body-custom to header_rewrite options (cherry picked from commit 5bd9999) (cherry picked from commit 08c614ef0089b175a5b6cee205b748416efb87cd) * Update set-custom-body response body to exclude headers (apache#780) * Update response body to exclude headers * Update tests to check both response with headers and response body only * Update header_rewrite_custom_body.test.py * Fix tests to check headers and body (cherry picked from commit cb552b6) (cherry picked from commit e12f4798d0d46bd90c810f8f3a7a067ea3b2c76f) * Remove debug check due to known issue (cherry picked from commit 964b12cc21a9a7c3f9d3fd50286e4cd2d2757bcc) * Fix formatting Remove whitespaces doc formatting fix Doc formatting fix * Rename to set-body-from * Add test for failed second call * Add more test cases * Clarify test cases * Update tests * Update header_rewrite.en.rst * Fix flakey test --------- Co-authored-by: Jasmine Emanouel <jemanouel@apple.com> (cherry picked from commit 0d8a6ac) * header_rewrite: Allow Txn reenable to be deferred. (apache#11658) The SetBodyFrom operator needs to defer calling Txn reenable until the fetch of the URL providing the response body completes. (cherry picked from commit 50f5f23) * cherry-pick cleanup * cherry-pick cleanup * Cleanup of header_rewrite redirect operator when invoked globally. (apache#11551) Also includes new Au test coverage. (cherry picked from commit 94dfd0e) * fix return value --------- Co-authored-by: Jasmine Emanouel <40879549+jasmine-nahrain@users.noreply.github.com> Co-authored-by: Walt Karas <wkaras@yahooinc.com>
* Add set-custom-body config item to header_rewrite (apache#11472) * Add set-body-custom to header_rewrite options (cherry picked from commit 5bd9999) (cherry picked from commit 08c614ef0089b175a5b6cee205b748416efb87cd) * Update set-custom-body response body to exclude headers (apache#780) * Update response body to exclude headers * Update tests to check both response with headers and response body only * Update header_rewrite_custom_body.test.py * Fix tests to check headers and body (cherry picked from commit cb552b6) (cherry picked from commit e12f4798d0d46bd90c810f8f3a7a067ea3b2c76f) * Remove debug check due to known issue (cherry picked from commit 964b12cc21a9a7c3f9d3fd50286e4cd2d2757bcc) * Fix formatting Remove whitespaces doc formatting fix Doc formatting fix * Rename to set-body-from * Add test for failed second call * Add more test cases * Clarify test cases * Update tests * Update header_rewrite.en.rst * Fix flakey test --------- Co-authored-by: Jasmine Emanouel <jemanouel@apple.com> (cherry picked from commit 0d8a6ac) * Cleanup of header_rewrite redirect operator when invoked globally. (apache#11551) Also includes new Au test coverage. (cherry picked from commit 94dfd0e) * header_rewrite: Allow Txn reenable to be deferred. (apache#11658) The SetBodyFrom operator needs to defer calling Txn reenable until the fetch of the URL providing the response body completes. (cherry picked from commit 50f5f23) --------- Co-authored-by: Jasmine Emanouel <40879549+jasmine-nahrain@users.noreply.github.com> Co-authored-by: Walt Karas <wkaras@yahooinc.com>
Adding config item set-custom-body to header rewrite.
The config takes in a url. When triggered, there will be a secondary call the the specified endpoint to get a response body from. What the client will see is the response body from the second call.
The second call goes through as an internal ATS request and goes gets remapped.
The status of the original transaction will remain in all error status code cases. OK status codes will appear as a 500 error code due to the nature of TSHttpTxnErrorBodySet.
e.g.
set_custom_body.conf
remap.config
With the above configs, when /home returns a 404 status code, a second call will be made to /404 through ATS internal request
The response that is sent to the client is