Closed
Description
Description
GitHub Issue Description
Title:
API inconsistency: /repos/{owner}/{repo}/contents/{filepath}
returns different types causing JSON deserialization errors in generated SDKs
Problem Description:
The Gitea API endpoint /repos/{owner}/{repo}/contents/{filepath}
has an inconsistent response format that causes JSON deserialization errors in generated SDKs (especially Java):
- When
filepath
is a file: Returns a singleContentsResponse
object{}
- When
filepath
is a directory: Returns an array ofContentsResponse
objects[]
This inconsistency leads to:
- SDK Generation Issues: OpenAPI generators cannot properly handle union types, causing incorrect client code generation
- Runtime Errors: Java SDK throws
JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY
when requesting directory contents - Poor Developer Experience: Developers need to handle two different response formats for the same endpoint
Error log:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:397)
at com.google.gson.Gson.fromJson(Gson.java:1227)
at com.google.gson.Gson.fromJson(Gson.java:1137)
at com.google.gson.Gson.fromJson(Gson.java:1047)
at com.google.gson.Gson.fromJson(Gson.java:1014)
at io.gitea.client.JSON.deserialize(JSON.java:134)
at io.gitea.client.ApiClient.deserialize(ApiClient.java:718)
at io.gitea.client.ApiClient.handleResponse(ApiClient.java:921)
at io.gitea.client.ApiClient.execute(ApiClient.java:848)
at io.gitea.api.RepositoryApi.repoGetContentsWithHttpInfo(RepositoryApi.java:14365)
at io.gitea.api.RepositoryApi.repoGetContents(RepositoryApi.java:14348)
Current Behavior:
# File request - returns object
GET /api/v1/repos/owner/repo/contents/file.txt
{"name": "file.txt", "type": "file", ...}
# Directory request - returns array
GET /api/v1/repos/owner/repo/contents/directory
[{"name": "file1.txt", "type": "file", ...}, {"name": "file2.txt", "type": "file", ...}]
Expected Behavior:
The API should consistently return an array format for both files and directories:
# File request - returns array with single element
GET /api/v1/repos/owner/repo/contents/file.txt
[{"name": "file.txt", "type": "file", ...}]
# Directory request - returns array (unchanged)
GET /api/v1/repos/owner/repo/contents/directory
[{"name": "file1.txt", "type": "file", ...}, {"name": "file2.txt", "type": "file", ...}]
Proposed Solution:
- Modify
GetContentsOrList
function inservices/repository/files/content.go
to always return[]*api.ContentsResponse
instead ofany
- Update Swagger definition in
templates/swagger/v1_json.tmpl
to consistently referenceContentsListResponse
- Update API documentation to reflect the consistent array response format
- Update test cases to expect array format for file requests
Benefits:
- ✅ Consistent API behavior across all request types
- ✅ Better SDK generation for all programming languages
- ✅ Backward compatible - existing clients can simply access
response[0]
for file content - ✅ Follows RESTful conventions - collection endpoints should return arrays
Files to be modified:
services/repository/files/content.go
templates/swagger/v1_json.tmpl
routers/api/v1/repo/file.go
(Swagger comments)services/repository/files/content_test.go
(test cases)
This change would align Gitea's API with GitHub's API behavior and resolve SDK generation issues across multiple programming languages.
Gitea Version
latest
Can you reproduce the bug on the Gitea demo site?
Yes
Log Gist
No response
Screenshots
No response
Git Version
No response
Operating System
No response
How are you running Gitea?
./gitea web
Use auto-generated Java SDK:
wget https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.68/swagger-codegen-cli-3.0.68.jar
java -jar swagger-codegen-cli-3.0.68.jar generate \
-i http://127.0.0.1:8080/swagger.v1.json \
-l java \
-o gitea-java-client \
--api-package io.gitea.api \
--model-package io.gitea.model \
--invoker-package io.gitea.client \
--group-id io.gitea \
--artifact-id gitea-java-client \
--artifact-version 1.0.0
Database
None