-
Notifications
You must be signed in to change notification settings - Fork 612
[rustformation] support parsing body as json or string #12950
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
base: main
Are you sure you want to change the base?
Conversation
…nja custom functions Signed-off-by: Andy Fong <[email protected]> - switch to go-httpbin for transformation e2e tests - modify the test to cache the response body and restore it when returning the http.Response object - create jinja env once; check globals for undeclared_variables Signed-off-by: Andy Fong <[email protected]>
|
Certain area definitely doesn't look DRY enough, especially the transform_request() and transform_response() function. Normally, I would create a common function and pass in the corresponding function pointers (in C++ term) to do the work. However, it's easy to do that in rust if you only have one function pointer in the struct that you need to pass. Passing multiple function pointers in the same struct causes some violation I was not able to solve easily because that would cause multiple mutatable reference of the struct to be created. While I know they won't be called at the same time, the rust compiler does not trust nobody for that. There should be a way but for now, I want to get this out first. |
Signed-off-by: Andy Fong <[email protected]>
Signed-off-by: Andy Fong <[email protected]>
Signed-off-by: Andy Fong <[email protected]>
| TODO: look into enabling this to avoid accidental use of unwrap() and | ||
| crash the process. However, there are many tests using unwrap() that | ||
| will make the linter unhappy. | ||
| #![deny(clippy::unwrap_used, clippy::expect_used)] |
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.
hmm, it seems like the linter should understand a test module vs non-test. Maybe people are normally explicitly allowing the test modules
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.
Let me look into that but probably will do that in my next PR.
| if buffers.is_empty() { | ||
| return Ok(JsonValue::Null); | ||
| } | ||
| // TODO: implement Reader for EnvoyBuffer and use serde_json::from_reader to avoid making copy first? |
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'm pretty sure I saw this in some example repo
| envoy_filter.send_response(400, Vec::default(), None); | ||
| return false; | ||
| } else { | ||
| envoy_log_warn!("{:#}", err); |
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.
Why do we not 400 on other error types?
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.
in my early testing, the c++ transformation doesn't return error, so this is just trying to be the same behavior but I should add more negative test cases in a separate commit to be sure.
Signed-off-by: Andy Fong <[email protected]>
Implausiblyfun
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 pretty cool havent tested in practice but it seems like a good step.
Ill be out of pocket soon but will check cncf slack if any questions come up. That being said it I think others are currently closer to this and definitely others have a better handle on rust so I defer to their wisdom in the meantime.
| for v in &undeclared_variables { | ||
| // Unfortunately, custom function is also reported as undeclared variables | ||
| // by minijinja, so only return error if the undeclared variables are not | ||
| // customer functions. GLOBALS_LOCKUP is lazily constructed once and is |
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.
| // customer functions. GLOBALS_LOCKUP is lazily constructed once and is | |
| // custom functions. GLOBALS_LOCKUP is lazily constructed once and is |
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 another PR that will probably merge to this one because upstream introduced an API breakage on a point release. I will fix this in there.
| ops.append_request_body(rendered_body); | ||
| } else { | ||
| ops.set_request_header("content-length", b"0"); | ||
| // In classic transformation, we remove content-type only when "passthrough_body" |
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.
Are we intending to change the c++ impl too to smooth transitions?
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's probably hard to modify the classic transformation behavior but I think this is very minor as there is no body bytes, should not cause any issue with or without content-type.
nfuden
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 pretty cool havent tested in practice but it seems like a good step.
Ill be out of pocket soon but will check cncf slack if any questions come up. That being said it I think others are currently closer to this and definitely others have a better handle on rust so I defer to their wisdom in the meantime.
Sorry about the confusion I reviewed first with my other account will update now
| return | ||
| } | ||
|
|
||
| fmt.Printf("testName: %s applying %v\n", testName, testCase) |
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.
| WithContext(ctx). | ||
| Should(Succeed(), "failed to get expected response") | ||
|
|
||
| if len(cachedBodyBytes) > 0 { |
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.
why is this only in this case? is there a version where we have this in a defer or something early?
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.
no, just if the body is empty to begin with, no need to create an NopCloser.
No problem. Appreciate taking a look. Have a Great Thanksgiving! |
Description
This is the continuing effort of implementing all the documented feature in rustformation so we can remove the dependency of envoy-gloo.
Change Type
/kind feature
Changelog
Additional Notes
There are some differences between minijinja in rust vs the inja lib we use in C++:
// Determines how the body will be parsed. enum RequestBodyParse { // Will attempt to parse the request/response body as JSON ParseAsJson = 0; // The request/response body will be treated as plain text DontParse = 1; } RequestBodyParse parse_body_behavior = 7;ParseAsJson is 0, so that’s the default. But in the new TrafficPolicyAPI in kgateway:``` // +kubebuilder:default=AsString ParseAs BodyParseBehavior `json:"parseAs"````We set the default with kubebuilder directly to AsString