OpenApi Export and Swagger UI Binding#1671
Conversation
|
The Changes Requested Done
Minor Unresolved
Major Unresolved
|
|
@afsalthaj this is the explanation. I have addressed almost all comments from old PR, with the major exception of content-type in response. Content-Type and StatusRibOutputTypeInfo only contains the AnalysedType, and not the actual value of status and header (Content-Type). The exact values are calculated at runtime. Both are valid, working rib-script. In first we can set status at runtime, and in second we can set content-type during runtime. let input = request.body.input;
let worker = instance("worker");
let result = worker.echo("Test");
{status: input: u64, body: result}let input: string = request.body.input;
let worker = instance("worker-static");
let result = worker.echo("Test", 3);
{headers: {Content-Type: input, userid: "foo"}, status: 200: u64, body: result}For the Status Case -I determine the status by using method (POST -> 201, GET-> 200, and so on) and for all other cases (Where rib may output multiple types /v0.0.1/test1:
post:
responses:
default:
description: Created
content:
application/json:
schema:
type: string
'201':
description: Created
content:
application/json:
schema:
type: stringFor the Content-Type Case -Current Golem-Rib behavior for String and other Primitive types, if you try application/text or application/octet-stream or any valid name. It will try to output it in that form, including image/png. For application/json which is the default, it outputs json. If the AnalysedType is Complex, for all other content-type it will output a messaging "So and so analaysed-type could not be translated to content-type". for application/json it will output the json In the first-case currently in api-oas-convert we pass application-json, if swagger ui receives application-text it handles it gracefully. |
|
Thanks @Nanashi-lab for raising the PR again
Could you please explain this in detail? All information should still be available in the rib output type info. Also I hope this PR addresses the concerns raised I in this PR. #1454 |
|
More thoughts on RibOutputTypeInfo on figuring exact values of status and content-type {headers: {Content-Type: \"application/text\", userid: \"foo\"}, status: 200: u64, body: \"Success\"}RibOutputTypeInfo "analysedType": {
"fields": [
{
"name": "headers",
"typ": {
"fields": [
{
"name": "Content-Type",
"typ": {
"type": "Str"
}
},
{
"name": "userid",
"typ": {
"type": "Str"
}
}
],
"type": "Record"
}
},
{
"name": "status",
"typ": {
"type": "U64"
}
},
{
"name": "body",
"typ": {
"type": "Str"
}
}
],
"type": "Record"
}This is the RibOutputTypeInfo Structure, the actual values for status, body and header are in the rib-expression and the exact value is calculated when the api is called. RibOutputTypeInfo contains NameTypePair and not ValueAndType We cannot extract content-type, status etc from rib-expression, because it can be set by the user at runtime, also string scanning might lead to false information from comments example |
|
Another way to handle this would be, since application/text or application/xml both only handle primitive types like string If the body is primitive, we can add all possible outcome I am going to move forward with the solution @jdegoes & @afsalthaj if you have any comments on status and content-type issue, and how I am handling it, please tell me. (Look at comment above for more information) responses:
'200':
description: Success
content:
application/json:
type: string
application/xml:
type: string
text/plain:
type: string
application/text:
type: string |
* 1.2.2 RC1 * Following oss changes
|
@afsalthaj Perhaps Rib can return "singleton types" when possible. It's not likely the content type or status code is a variable: it's likely it's a literal, embedded into the Rib script. If Rib had any kind of support for singleton types, e.g. |
|
Content-Type will be mostly literal. Status can have a few possible Literal values, for result and variant. In OpenAPI v3, responses:
'200':
description: Success
content:
application/json:
type: string
'*/*':
type: string This works also for complex types, because for complex type in application/text or others, output string error |
|
Most of the code is done. Once the merge between cloud and oss happens, I will rebase, and fix any leftover issues. |
|
On the core issue of "Content-Type" is not known statically can be solved to some extent with the following idea. This may not be perfect (meaning, I am still thinking), but this is my initial thought We can inspect the original rib program's last expression (the return value) assuming its always a Record type. This implies we mandate the idea that last expression in a Rib in the context of api gateway should be a Record with optional status code and headers. Currently (in the main brain) the last expression can be "anything" (example: it can be a And thi flexibility that we currently have exists more of a confusion than a feature. Example: What happens if I want to return a http body which itself contains a Hence we mandate statically that the last expression should be a Record - always. Yes, it reduces some flexibility but it doesn't limit the user from doing anything The last expression in a Rib in an API gateway http definition is always or or Here we reliably we inspect the values in headers and pick the Content-Type which is probably an Expr::string(..) An intentionally complex example: let x = request.body.user;
let worker = instance();
let result = worker.foo(x);
let status_and_body = match result {
ok(value) => {status: 200, body: "${value}"},
err(value) => {status: 400, body : "failed"}
}
{status: status_and_body.status, body: status_and_body.body, headers: {ContentType:...}} |
|
@Nanashi-lab if we need to track down the types of response for each type of status (which is something I overlooked in terms of the details when the problem was originally described) then I believe John's suggestion of singleton types is the way out. |
|
@afsalthaj I like your suggestion, of rib output always having Example 1 - I should be able to extract 200 from the rib script, and use it in openapi as Example 2 - I should be able to figure out that status does not have an exact match, and I can use, , this is in addition to a default likely 200, and that should cover all the other outputs. Example 3 - |
125c3f5 to
6df8940
Compare
|
I am finished with the merge, and I have also completed the golem-cli changes Testing - You can use the single binary golem, from golem-cli to end to end test swagger ui, export API in openapispec
Clone Test components You can access the Swagger UI for each app at the endpoints listed below. Shopping Cart Todo List LLM Setup for LLM
|
|
More Notes - responses:
'200':
description: Success
content:
application/json:
type: u32
'*/*':
type: string
default:
description: Success
content:
application/json:
type: u32
'*/*':
type: string |
a987b86 to
9c25b39
Compare
7e292d4 to
d93ee40
Compare
|
@afsalthaj whenever you are free, let's get this PR reviewed |
| DeleteApiDefinition = 14, | ||
| DeleteProject = 15, | ||
| ViewProject = 161, | ||
| ViewProject = 16, |
golem-worker-service/src/gateway_api_definition/http/api_oas_convert.rs
Outdated
Show resolved
Hide resolved
| return (schema, "application/json".to_string()); | ||
| } | ||
| } | ||
| (None, "application/json".to_string()) |
There was a problem hiding this comment.
I understand this logic is due to the complexity that we discussed previously. I am ok for this for now.
| }; | ||
|
|
||
| // Only add content if we have a response schema and it's not a 204 response | ||
| if status_code != 204 { |
There was a problem hiding this comment.
What happens if user specifies a status code 204, and then also some content. Needn't handle it in this PR. But I think proper solution requires literal types. We will deal it later
There was a problem hiding this comment.
Because of how we currently determine status code, 204 happens only when the method is DELETE.
| if let Some(worker_name) = data.worker_name { | ||
| binding_info.insert( | ||
| "worker-name".to_string(), | ||
| serde_json::Value::String(worker_name.worker_name.to_string()), |
There was a problem hiding this comment.
this should hardly occur as worker name is none with first class worker support. I know for one of the bindings it will happen. Just typing this here, just so that if you agree or not.
There was a problem hiding this comment.
This is only for file-server and http-handler, both of the can accept workername. we must do this, because original ticket's requirement was roundtrip (httpapi -> openapi -> httpapi via import).
̶I̶n̶ ̶d̶e̶f̶a̶u̶l̶t̶ ̶b̶i̶n̶d̶i̶n̶g̶-̶t̶y̶p̶e̶ ̶t̶h̶i̶s̶ ̶s̶h̶o̶u̶l̶d̶ ̶r̶a̶r̶e̶l̶y̶ ̶o̶c̶c̶u̶r̶,̶ ̶g̶i̶v̶e̶n̶ ̶t̶h̶e̶ ̶f̶i̶r̶s̶t̶ ̶c̶l̶a̶s̶s̶ ̶w̶o̶r̶k̶e̶r̶ ̶s̶u̶p̶p̶o̶r̶t̶.̶ ̶
Edit - in default binding-type this will never happen, as WorkerBindingCompiled doesn't have workername, If someone uses workername in default, there is information loss, and roundtrip will fail. (Rare case, since we have moved to first class worker)
component_id: Some(&w.component_id),
worker_name: None, // WorkerBindingCompiled doesn't have worker_name_compiled
response: Some(&w.response_compiled),
afsalthaj
left a comment
There was a problem hiding this comment.
Looks much better than previous PR.
I think this is a decent version to be merged, with possibilities of improvement as we go.
This work is valuable already to get merged.
Thanks @Nanashi-lab
|
@Nanashi-lab Please resolve conflicts as soon as possible, and @vigoo can merge. |
|
@vigoo I have resolved all the conflicts and rebased to latest. I am unsure about atomic deployment, so currently there is no stub for export api in registry service Also code which were part of converting bindingtype to grpc types, is no longer there, so changes to those parts have been left out in this rebase. |
/closes #1178
/claim #1178
Docs is still left to do.
Golem-Cli also has been updated.
I am ready for a review @afsalthaj I have added the explanation comment on content-type and status. Do tell if I have that right ? and if so is the current way of handling it is robust ?
Link to Videos and Files -
Video One - Link
This covers the Export Endpoint, and the Export CLI Command, and Round-Trip Test
Video Two - Link
This covers the Swagger CLI Command, and Swagger UI Binding
If you want to check the actual conversion between AnalysedType and OpenApi Spec, you can either