Skip to content

Commit 52b5b8f

Browse files
authored
Fix a few issues with the C generator (part 2) (#20227)
* [C] Don't convert post body strings to JSON If the body provided for the api request is a just a string itself, don't try to convert it to JSON, simply submit the string. * [C] Implement BearerToken authentication * [C] Handle nullable fields correctly * [C] Fix implementation of FromString for enums * [C] Update the test schemas to cover the changes * Update samples * Fix the updated samples * [C] Add the new samples folder to the CI workflow
1 parent 387fd99 commit 52b5b8f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+6200
-31
lines changed

.github/workflows/samples-c-libcurl-client.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ on:
55
paths:
66
- 'samples/client/petstore/c/**'
77
- 'samples/client/petstore/c-useJsonUnformatted/**'
8+
- 'samples/client/others/c/bearerAuth/**'
89
pull_request:
910
paths:
1011
- 'samples/client/petstore/c/**'
1112
- 'samples/client/petstore/c-useJsonUnformatted/**'
13+
- 'samples/client/others/c/bearerAuth/**'
1214

1315
jobs:
1416
build:
@@ -20,6 +22,7 @@ jobs:
2022
sample:
2123
- 'samples/client/petstore/c/'
2224
- 'samples/client/petstore/c-useJsonUnformatted/'
25+
- 'samples/client/others/c/bearerAuth/'
2326

2427
steps:
2528
- uses: actions/checkout@v4

bin/configs/c-bearer-auth.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
generatorName: c
2+
outputDir: samples/client/others/c/bearerAuth
3+
inputSpec: modules/openapi-generator/src/test/resources/3_0/c/bearer_auth.yaml
4+
templateDir: modules/openapi-generator/src/main/resources/C-libcurl

modules/openapi-generator/src/main/resources/C-libcurl/api-body.mustache

+7
Original file line numberDiff line numberDiff line change
@@ -324,13 +324,18 @@ end:
324324
}
325325
{{/isArray}}
326326
{{^isArray}}
327+
{{#isString}}
328+
localVarBodyParameters = strdup({{paramName}});
329+
{{/isString}}
330+
{{^isString}}
327331
cJSON *localVarSingleItemJSON_{{paramName}} = NULL;
328332
if ({{paramName}} != NULL)
329333
{
330334
//string
331335
localVarSingleItemJSON_{{paramName}} = {{dataType}}_convertToJSON({{paramName}});
332336
localVarBodyParameters = {{{cJSONPrint}}}(localVarSingleItemJSON_{{paramName}});
333337
}
338+
{{/isString}}
334339
{{/isArray}}
335340
{{/bodyParam}}
336341
{{#produces}}
@@ -458,10 +463,12 @@ end:
458463
free(localVarBodyParameters);
459464
{{/isArray}}
460465
{{^isArray}}
466+
{{^isString}}
461467
if (localVarSingleItemJSON_{{paramName}}) {
462468
cJSON_Delete(localVarSingleItemJSON_{{paramName}});
463469
localVarSingleItemJSON_{{paramName}} = NULL;
464470
}
471+
{{/isString}}
465472
free(localVarBodyParameters);
466473
{{/isArray}}
467474
{{/bodyParams}}

modules/openapi-generator/src/main/resources/C-libcurl/apiClient.c.mustache

+25
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ apiClient_t *apiClient_create() {
2222
apiClient->username = NULL;
2323
apiClient->password = NULL;
2424
{{/isBasicBasic}}
25+
{{#isBasicBearer}}
26+
apiClient->accessToken = NULL;
27+
{{/isBasicBearer}}
2528
{{#isOAuth}}
2629
apiClient->accessToken = NULL;
2730
{{/isOAuth}}
@@ -69,6 +72,9 @@ apiClient_t *apiClient_create_with_base_path(const char *basePath
6972
apiClient->username = NULL;
7073
apiClient->password = NULL;
7174
{{/isBasicBasic}}
75+
{{#isBasicBearer}}
76+
apiClient->accessToken = NULL;
77+
{{/isBasicBearer}}
7278
{{#isOAuth}}
7379
apiClient->accessToken = NULL;
7480
{{/isOAuth}}
@@ -108,6 +114,11 @@ void apiClient_free(apiClient_t *apiClient) {
108114
free(apiClient->password);
109115
}
110116
{{/isBasicBasic}}
117+
{{#isBasicBearer}}
118+
if(apiClient->accessToken) {
119+
free(apiClient->accessToken);
120+
}
121+
{{/isBasicBearer}}
111122
{{#isOAuth}}
112123
if(apiClient->accessToken) {
113124
free(apiClient->accessToken);
@@ -467,6 +478,20 @@ void apiClient_invoke(apiClient_t *apiClient,
467478
}
468479
}
469480
{{/isApiKey}}
481+
{{#isBasicBearer}}
482+
// this would only be generated for bearer token authentication
483+
if(apiClient->accessToken != NULL)
484+
{
485+
int authHeaderSize;
486+
char *authHeader = NULL;
487+
488+
authHeaderSize = snprintf(NULL, 0, "Authorization: Bearer %s", apiClient->accessToken) + 1;
489+
authHeader = malloc(authHeaderSize);
490+
snprintf(authHeader, authHeaderSize, "Authorization: Bearer %s", apiClient->accessToken);
491+
headers = curl_slist_append(headers, authHeader);
492+
free(authHeader);
493+
}
494+
{{/isBasicBearer}}
470495
{{/authMethods}}
471496
{{/hasAuthMethods}}
472497

modules/openapi-generator/src/main/resources/C-libcurl/apiClient.h.mustache

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ typedef struct apiClient_t {
3434
char *username;
3535
char *password;
3636
{{/isBasicBasic}}
37+
{{#isBasicBearer}}
38+
char *accessToken;
39+
{{/isBasicBearer}}
3740
{{#isOAuth}}
3841
char *accessToken;
3942
{{/isOAuth}}

modules/openapi-generator/src/main/resources/C-libcurl/model-body.mustache

+9-13
Original file line numberDiff line numberDiff line change
@@ -49,27 +49,20 @@ fail:
4949
}
5050

5151
{{projectName}}_{{classVarName}}_{{enumName}}_e {{classname}}_parseFromJSON(cJSON *{{classname}}JSON) {
52-
{{projectName}}_{{classVarName}}_{{enumName}}_e *{{classname}} = NULL;
5352
{{#isEnum}}
5453
{{#isNumeric}}
55-
cJSON *{{{classname}}}Var = cJSON_GetObjectItemCaseSensitive({{classname}}JSON, "{{{classname}}}");
56-
if(!cJSON_IsNumber({{{classname}}}Var))
57-
{
58-
goto end;
54+
if(!cJSON_IsNumber({{{classname}}}JSON)) {
55+
return 0;
5956
}
57+
return {{classname}}JSON->valueint;
6058
{{/isNumeric}}
6159
{{#isString}}
62-
{{projectName}}_{{classVarName}}_{{enumName}}_e {{classname}}Variable;
63-
cJSON *{{{classname}}}Var = cJSON_GetObjectItemCaseSensitive({{classname}}JSON, "{{{classname}}}");
64-
if(!cJSON_IsString({{{classname}}}Var) || ({{{classname}}}Var->valuestring == NULL)){
65-
goto end;
60+
if(!cJSON_IsString({{{classname}}}JSON) || ({{{classname}}}JSON->valuestring == NULL)) {
61+
return 0;
6662
}
67-
{{classname}}Variable = {{classFilename}}_{{classname}}_FromString({{{classname}}}Var->valuestring);
63+
return {{classFilename}}_{{classname}}_FromString({{{classname}}}JSON->valuestring);
6864
{{/isString}}
6965
{{/isEnum}}
70-
return {{classname}}Variable;
71-
end:
72-
return 0;
7366
}
7467
{{/isEnum}}
7568
{{^isEnum}}
@@ -623,6 +616,9 @@ fail:
623616
{{#vars}}
624617
// {{{classname}}}->{{{name}}}
625618
cJSON *{{{name}}} = cJSON_GetObjectItemCaseSensitive({{classname}}JSON, "{{{baseName}}}");
619+
if (cJSON_IsNull({{{name}}})) {
620+
{{{name}}} = NULL;
621+
}
626622
{{#required}}
627623
if (!{{{name}}}) {
628624
goto end;

modules/openapi-generator/src/test/resources/2_0/c/petstore.yaml

+51
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,26 @@ paths:
253253
- petstore_auth:
254254
- 'write:pets'
255255
- 'read:pets'
256+
/pet/picture:
257+
post:
258+
tags:
259+
- pet
260+
summary: Send a picture of your happy pet
261+
description: ''
262+
operationId: sharePicture
263+
parameters:
264+
- in: body
265+
name: picture
266+
description: A picture you want to share
267+
required: true
268+
schema:
269+
type: string
270+
responses:
271+
'200':
272+
description: successful operation
273+
schema:
274+
type: string
275+
description: Thank you message
256276
'/pet/{petId}/uploadImage':
257277
post:
258278
tags:
@@ -290,6 +310,31 @@ paths:
290310
- petstore_auth:
291311
- 'write:pets'
292312
- 'read:pets'
313+
'/pet/{petId}/isAvailable':
314+
post:
315+
tags:
316+
- pet
317+
summary: Is this pet still available?
318+
description: ''
319+
operationId: isPetAvailable
320+
produces:
321+
- application/json
322+
parameters:
323+
- name: petId
324+
in: path
325+
description: ID of pet to check
326+
required: true
327+
type: integer
328+
format: int64
329+
responses:
330+
'200':
331+
description: successful operation
332+
schema:
333+
$ref: '#/definitions/Bit'
334+
security:
335+
- petstore_auth:
336+
- 'write:pets'
337+
- 'read:pets'
293338
/store/inventory:
294339
get:
295340
tags:
@@ -775,3 +820,9 @@ definitions:
775820
uniqueItems: true
776821
items:
777822
type: string
823+
Bit:
824+
description: bit value
825+
type: number
826+
enum:
827+
- 0
828+
- 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copied from k6
2+
openapi: 3.0.0
3+
info:
4+
title: Sample API
5+
description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
6+
version: 0.1.9
7+
servers:
8+
- url: http://api.example.com/v1
9+
description: Optional server description, e.g. Main (production) server
10+
- url: http://staging-api.example.com
11+
description: Optional server description, e.g. Internal staging server for testing
12+
security:
13+
- bearerAuth: []
14+
paths:
15+
/users:
16+
get:
17+
summary: Returns a list of users.
18+
description: Optional extended description in CommonMark or HTML.
19+
responses:
20+
"200": # status code
21+
description: A JSON array of user names
22+
content:
23+
application/json:
24+
schema:
25+
type: array
26+
items:
27+
type: string
28+
security:
29+
- bearerAuth: []
30+
/public:
31+
get:
32+
summary: Returns public information.
33+
description: This endpoint does not require authentication.
34+
responses:
35+
"200":
36+
description: A JSON object with public information
37+
content:
38+
application/json:
39+
schema:
40+
type: object
41+
security: []
42+
/private:
43+
get:
44+
summary: Returns private information.
45+
description: This endpoint requires global security settings.
46+
responses:
47+
"200":
48+
description: A JSON object with private information
49+
content:
50+
application/json:
51+
schema:
52+
type: object
53+
components:
54+
securitySchemes:
55+
bearerAuth:
56+
type: http
57+
scheme: bearer
58+
bearerFormat: JWT # Optional: specify the format (e.g., JWT) if applicable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# OpenAPI Generator Ignore
2+
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
3+
4+
# Use this file to prevent files from being overwritten by the generator.
5+
# The patterns follow closely to .gitignore or .dockerignore.
6+
7+
# As an example, the C# client generator defines ApiClient.cs.
8+
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
9+
#ApiClient.cs
10+
11+
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
12+
#foo/*/qux
13+
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
14+
15+
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
16+
#foo/**/qux
17+
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
18+
19+
# You can also negate patterns with an exclamation (!).
20+
# For example, you can ignore all files in a docs folder with the file extension .md:
21+
#docs/*.md
22+
# Then explicitly reverse the ignore rule for a single file:
23+
#!docs/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
CMakeLists.txt
2+
Packing.cmake
3+
README.md
4+
api/DefaultAPI.c
5+
api/DefaultAPI.h
6+
docs/DefaultAPI.md
7+
external/cJSON.c
8+
external/cJSON.h
9+
external/cJSON.licence
10+
include/apiClient.h
11+
include/binary.h
12+
include/keyValuePair.h
13+
include/list.h
14+
libcurl.licence
15+
model/any_type.h
16+
model/object.c
17+
model/object.h
18+
src/apiClient.c
19+
src/apiKey.c
20+
src/binary.c
21+
src/list.c
22+
uncrustify-rules.cfg
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7.11.0-SNAPSHOT

0 commit comments

Comments
 (0)