Improve the OpenAPI generated client's method signature to match the HTTP client's method signature
Closed this issue · 0 comments
TharmiganK commented
Description:
Improve the signature of the OpenAPI generated client's method to have clear parameter separation with headers, queries and payload. The HTTP client methods have such separation:
map<string|string[]>
parameter to represents theheaders
- included record parameter to represents the
queries
- anydata parameter to represent the payload
Describe your problem(s)
Consider the following OAS:
openapi: 3.0.1
info:
title: Api
version: 0.1.0
servers:
- url: "{server}:{port}/api"
variables:
server:
default: http://localhost
port:
default: "9090"
paths:
/albums:
get:
operationId: getAlbums
parameters:
- name: version
in: header
required: true
schema:
$ref: '#/components/schemas/Version'
- name: user-id
in: header
required: true
schema:
type: string
- name: genre
in: query
schema:
type: string
responses:
"200":
description: Ok
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Album'
post:
operationId: postAlbums
parameters:
- name: version
in: header
required: true
schema:
$ref: '#/components/schemas/Version'
- name: user-id
in: header
required: true
schema:
type: string
- name: directory
in: query
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Album'
required: true
responses:
"201":
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/Album'
components:
schemas:
Album:
required:
- artist
- genre
- name
- year
type: object
properties:
name:
type: string
artist:
type: string
year:
type: integer
format: int64
genre:
type: string
additionalProperties: false
Version:
type: string
enum:
- V2
- V1
The current generated client:
public isolated client class Client {
...
# Get the albums
#
# + genre - The genre
# + return - Ok
resource isolated function get albums(Version version, string user\-id, string? genre = ()) returns Album[]|error {
string resourcePath = string `/albums`;
map<anydata> queryParam = {"genre": genre};
resourcePath = resourcePath + check getPathForQueryParam(queryParam);
map<any> headerValues = {"version": version, "user-id": user\-id};
map<string|string[]> httpHeaders = getMapForHeaders(headerValues);
return self.clientEp->get(resourcePath, httpHeaders);
}
# Post an album
#
# + directory - The directory
# + payload - The album
# + return - Created
resource isolated function post albums(Version version, string user\-id, Album payload, string? directory = ()) returns Album|error {
string resourcePath = string `/albums`;
map<anydata> queryParam = {"directory": directory};
resourcePath = resourcePath + check getPathForQueryParam(queryParam);
map<any> headerValues = {"version": version, "user-id": user\-id};
map<string|string[]> httpHeaders = getMapForHeaders(headerValues);
http:Request request = new;
json jsonBody = payload.toJson();
request.setPayload(jsonBody, "application/json");
return self.clientEp->post(resourcePath, request, httpHeaders);
}
}
Usage compare to the HTTP client:
Album[] _ = check httpClient->/albums({user\-id: "123", version: "V1"}, genre = "pop");
Album[] _ = check generatedClient->/albums(user\-id = "123", version = "V1", genre = "pop");
Describe your solution(s)
The new generated client:
public isolated client class Client {
...
# + headers - Headers to be sent with the request
# + queries - Queries to be sent with the request
# + return - Ok
resource isolated function get albums(GetAlbumsHeaders headers, *GetAlbumsQueries queries) returns Album[]|error {
string resourcePath = string `/albums`;
resourcePath = resourcePath + check getPathForQueryParam(queries);
map<string|string[]> httpHeaders = getMapForHeaders(headers);
return self.clientEp->get(resourcePath, httpHeaders);
}
# + headers - Headers to be sent with the request
# + queries - Queries to be sent with the request
# + return - Created
resource isolated function post albums(PostAlbumsHeaders headers, Album payload, *PostAlbumsQueries queries) returns Album|error {
string resourcePath = string `/albums`;
resourcePath = resourcePath + check getPathForQueryParam(queries);
map<string|string[]> httpHeaders = getMapForHeaders(headers);
http:Request request = new;
json jsonBody = payload.toJson();
request.setPayload(jsonBody, "application/json");
return self.clientEp->post(resourcePath, request, httpHeaders);
}
}
The new header and query records:
# Represents the Headers record for the operation: postAlbums
public type PostAlbumsHeaders record {
string user\-id;
Version version;
};
# Represents the Headers record for the operation: getAlbums
public type GetAlbumsHeaders record {
string user\-id;
Version version;
};
public type Version "V2"|"V1";
# Represents the Queries record for the operation: postAlbums
public type PostAlbumsQueries record {
string? directory?;
};
# Represents the Queries record for the operation: getAlbums
public type GetAlbumsQueries record {
# The genre
string? genre?;
};