-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Add support for non-json reponse result to http.send builtin. #1264
Add support for non-json reponse result to http.send builtin. #1264
Conversation
e722ebe
to
dbdb248
Compare
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.
Thanks again for jumping on this so quickly. Getting the raw_body
is great; I just have a thought around the option for controlling whether decoding is attempted in cases where the Content-type isn't claimed to be JSON.
docs/book/language-reference.md
Outdated
|
||
| Built-in | Inputs | Description | | ||
| ------- |--------|-------------| | ||
| <span class="opa-keep-it-together">``http.send(request, output)``</span> | 3+ | ``http.send`` executes a HTTP request and returns the response.``request`` is an object containing keys ``method``, ``url`` and optionally ``body``, ``enable_redirect``, ``disable_json_decode``, ``headers``, ``tls_use_system_certs``, ``tls_ca_cert_file``, ``tls_ca_cert_env_variable``, ``tls_client_cert_env_variable``, ``tls_client_key_env_variable`` or ``tls_client_cert_file``, ``tls_client_key_file`` . For example, ``http.send({"method": "get", "url": "http://www.openpolicyagent.org/", "headers": {"X-Foo":"bar", "X-Opa": "rules"}}, output)``. ``output`` is an object containing keys ``status``, ``status_code``, ``body`` and ``raw_body`` which represent the HTTP status, status code, JSON value from the response body and response body as string respectively. Sample output, ``{"status": "200 OK", "status_code": 200, "body": {"hello": "world"}, "raw_body": "{\"hello\": \"world\ "}"``}. By default, http redirects are not enabled. To enable, set ``enable_redirect`` to ``true``. Also ``disable_json_decode`` is set to ``true`` by default. This means if the HTTP server response does not specify the ``Content-type`` as ``application/json``, the response body will not be JSON decoded ie. output's ``body`` field will be ``nil``. To change this behaviour, set ``disable_json_decode`` to ``false``.| |
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 like the logic of always returning a raw_body
, and if possible returning a JSON body
- that helps with the common existing case of JSON responses, while allowing more straightforward code in other cases (compared to conditionally switching between having either a body
or raw_body
).
The disable_json_decode
flag seems a bit hard to understand. I find disable-if-true to be confusing in general. If we rephrase this as force_json_decode
, which is false by default, then we get the behavior:
- Responses claiming to be
application/json
will always be JSON-decoded intobody
, if possible. - Other responses will not be so decoded, unless
force_json_decode
is set.
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.
@agurney I tend to agree however the only downside is that change would be backwards incompatible (i.e., users that had integrated their policy with an endpoint that doesn't set Content-Type properly would be broken.)
That said, now (if any) is the time to make backwards incompatible changes.
topdown/http.go
Outdated
return nil, err | ||
} | ||
|
||
if isContentTypeJSON(resp.Header) || (!isContentTypeJSON(resp.Header) && !disableJSONDecode) { |
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.
suggest if (isContentTypeJSON(resp.Header) || forceJSONDecode) { ... }
dbdb248
to
c6f12d5
Compare
A new field |
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.
Left a couple minor comments. Also, please add a bullet to the Unreleased section in the change log so that we don't forget to include a release note about this breaking change.
docs/book/language-reference.md
Outdated
| ------- |-------------| | ||
| <span class="opa-keep-it-together">``output := http.send(request)``</span> | ``http.send`` executes a HTTP request and returns the response.``request`` is an object containing keys ``method``, ``url`` and optionally ``body``, ``enable_redirect``, ``headers``, ``tls_use_system_certs``, ``tls_ca_cert_file``, ``tls_ca_cert_env_variable``, ``tls_client_cert_env_variable``, ``tls_client_key_env_variable`` or ``tls_client_cert_file``, ``tls_client_key_file`` . For example, ``http.send({"method": "get", "url": "http://www.openpolicyagent.org/", "headers": {"X-Foo":"bar", "X-Opa": "rules"}}, output)``. ``output`` is an object containing keys ``status``, ``status_code`` and ``body`` which represent the HTTP status, status code and response body respectively. Sample output, ``{"status": "200 OK", "status_code": 200, "body": null``}. By default, http redirects are not enabled. To enable, set ``enable_redirect`` to ``true``.| | ||
|
||
| Built-in | Inputs | Description | |
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.
Nit: It looks like the merge re-added the Inputs column that we got rid of in one of the recent docs improvement PRs. Please scrap this column and fix the built-in call format to match the others.
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.
Done.
docs/book/language-reference.md
Outdated
|
||
| Built-in | Inputs | Description | | ||
| ------- |--------|-------------| | ||
| <span class="opa-keep-it-together">``http.send(request, output)``</span> | 3+ | ``http.send`` executes a HTTP request and returns the response.``request`` is an object containing keys ``method``, ``url`` and optionally ``body``, ``enable_redirect``, ``force_json_decode``, ``headers``, ``tls_use_system_certs``, ``tls_ca_cert_file``, ``tls_ca_cert_env_variable``, ``tls_client_cert_env_variable``, ``tls_client_key_env_variable`` or ``tls_client_cert_file``, ``tls_client_key_file`` . For example, ``http.send({"method": "get", "url": "http://www.openpolicyagent.org/", "headers": {"X-Foo":"bar", "X-Opa": "rules"}}, output)``. ``output`` is an object containing keys ``status``, ``status_code``, ``body`` and ``raw_body`` which represent the HTTP status, status code, JSON value from the response body and response body as string respectively. Sample output, ``{"status": "200 OK", "status_code": 200, "body": {"hello": "world"}, "raw_body": "{\"hello\": \"world\ "}"``}. By default, http redirects are not enabled. To enable, set ``enable_redirect`` to ``true``. Also ``force_json_decode`` is set to ``false`` by default. This means if the HTTP server response does not specify the ``Content-type`` as ``application/json``, the response body will not be JSON decoded ie. output's ``body`` field will be ``nil``. To change this behaviour, set ``force_json_decode`` to ``true``.| |
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.
Nit: By default, [http->HTTP] redirects
.
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.
Done.
} | ||
|
||
if isContentTypeJSON(resp.Header) || forceJSONDecode { | ||
json.NewDecoder(&buf).Decode(&resultBody) |
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 about errors?
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.
Added a note.
|
||
result := make(map[string]interface{}) | ||
result["status"] = resp.Status | ||
result["status_code"] = resp.StatusCode | ||
result["body"] = resultBody | ||
result["raw_body"] = string(resultRawBody) |
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.
Out of curiosity, what happens if the raw body contains binary characters?
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 response body contains binary characters, the raw body will have them too.
Signed-off-by: Ashutosh Narkar <anarkar4387@gmail.com>
b5f33bc
to
e3ad773
Compare
Fixes #1258
Signed-off-by: Ashutosh Narkar anarkar4387@gmail.com