[API] Forgejo API /api/forgejo/v1
(cherry picked from commit 20b56692693e054bb3c04b4ef12b29b0715b4530)forgejo
parent
79de60a5d8
commit
1574643a6a
@ -0,0 +1,40 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Forgejo API
|
||||
description: |-
|
||||
Forgejo REST API
|
||||
|
||||
contact:
|
||||
email: contact@forgejo.org
|
||||
license:
|
||||
name: MIT
|
||||
url: https://codeberg.org/forgejo/forgejo/src/branch/forgejo/LICENSE
|
||||
version: 1.0.0
|
||||
externalDocs:
|
||||
description: Find out more about Forgejo
|
||||
url: http://forgejo.org
|
||||
servers:
|
||||
- url: /api/forgejo/v1
|
||||
paths:
|
||||
/version:
|
||||
get:
|
||||
summary: API version
|
||||
description: Semantic version of the Forgejo API
|
||||
operationId: getVersion
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Version'
|
||||
components:
|
||||
schemas:
|
||||
Version:
|
||||
type: object
|
||||
properties:
|
||||
number:
|
||||
type: string
|
||||
|
@ -0,0 +1,18 @@
|
||||
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
gocontext "context"
|
||||
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
)
|
||||
|
||||
func Routes(ctx gocontext.Context) *web.Route {
|
||||
m := web.NewRoute()
|
||||
forgejo := NewForgejo()
|
||||
m.Get("", Root)
|
||||
m.Get("/version", forgejo.GetVersion)
|
||||
return m
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
)
|
||||
|
||||
type Forgejo struct{}
|
||||
|
||||
var _ ServerInterface = &Forgejo{}
|
||||
|
||||
func NewForgejo() *Forgejo {
|
||||
return &Forgejo{}
|
||||
}
|
||||
|
||||
var ForgejoVersion = "development"
|
||||
|
||||
func (f *Forgejo) GetVersion(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_ = json.NewEncoder(w).Encode(Version{&ForgejoVersion})
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
// Package v1 provides primitives to interact with the openapi HTTP API.
|
||||
//
|
||||
// Code generated by github.com/deepmap/oapi-codegen version v1.12.4 DO NOT EDIT.
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
// Version defines model for Version.
|
||||
type Version struct {
|
||||
Number *string `json:"number,omitempty"`
|
||||
}
|
||||
|
||||
// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
// API version
|
||||
// (GET /version)
|
||||
GetVersion(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
// ServerInterfaceWrapper converts contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
HandlerMiddlewares []MiddlewareFunc
|
||||
ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
type MiddlewareFunc func(http.Handler) http.Handler
|
||||
|
||||
// GetVersion operation middleware
|
||||
func (siw *ServerInterfaceWrapper) GetVersion(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.GetVersion(w, r)
|
||||
})
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r.WithContext(ctx))
|
||||
}
|
||||
|
||||
type UnescapedCookieParamError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *UnescapedCookieParamError) Error() string {
|
||||
return fmt.Sprintf("error unescaping cookie parameter '%s'", e.ParamName)
|
||||
}
|
||||
|
||||
func (e *UnescapedCookieParamError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type UnmarshallingParamError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *UnmarshallingParamError) Error() string {
|
||||
return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error())
|
||||
}
|
||||
|
||||
func (e *UnmarshallingParamError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type RequiredParamError struct {
|
||||
ParamName string
|
||||
}
|
||||
|
||||
func (e *RequiredParamError) Error() string {
|
||||
return fmt.Sprintf("Query argument %s is required, but not found", e.ParamName)
|
||||
}
|
||||
|
||||
type RequiredHeaderError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *RequiredHeaderError) Error() string {
|
||||
return fmt.Sprintf("Header parameter %s is required, but not found", e.ParamName)
|
||||
}
|
||||
|
||||
func (e *RequiredHeaderError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type InvalidParamFormatError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *InvalidParamFormatError) Error() string {
|
||||
return fmt.Sprintf("Invalid format for parameter %s: %s", e.ParamName, e.Err.Error())
|
||||
}
|
||||
|
||||
func (e *InvalidParamFormatError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type TooManyValuesForParamError struct {
|
||||
ParamName string
|
||||
Count int
|
||||
}
|
||||
|
||||
func (e *TooManyValuesForParamError) Error() string {
|
||||
return fmt.Sprintf("Expected one value for %s, got %d", e.ParamName, e.Count)
|
||||
}
|
||||
|
||||
// Handler creates http.Handler with routing matching OpenAPI spec.
|
||||
func Handler(si ServerInterface) http.Handler {
|
||||
return HandlerWithOptions(si, ChiServerOptions{})
|
||||
}
|
||||
|
||||
type ChiServerOptions struct {
|
||||
BaseURL string
|
||||
BaseRouter chi.Router
|
||||
Middlewares []MiddlewareFunc
|
||||
ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
|
||||
func HandlerFromMux(si ServerInterface, r chi.Router) http.Handler {
|
||||
return HandlerWithOptions(si, ChiServerOptions{
|
||||
BaseRouter: r,
|
||||
})
|
||||
}
|
||||
|
||||
func HandlerFromMuxWithBaseURL(si ServerInterface, r chi.Router, baseURL string) http.Handler {
|
||||
return HandlerWithOptions(si, ChiServerOptions{
|
||||
BaseURL: baseURL,
|
||||
BaseRouter: r,
|
||||
})
|
||||
}
|
||||
|
||||
// HandlerWithOptions creates http.Handler with additional options
|
||||
func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handler {
|
||||
r := options.BaseRouter
|
||||
|
||||
if r == nil {
|
||||
r = chi.NewRouter()
|
||||
}
|
||||
if options.ErrorHandlerFunc == nil {
|
||||
options.ErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
HandlerMiddlewares: options.Middlewares,
|
||||
ErrorHandlerFunc: options.ErrorHandlerFunc,
|
||||
}
|
||||
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Get(options.BaseURL+"/version", wrapper.GetVersion)
|
||||
})
|
||||
|
||||
return r
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
// Copyright The Forgejo Authors.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func Root(w http.ResponseWriter, r *http.Request) {
|
||||
// https://www.rfc-editor.org/rfc/rfc8631
|
||||
w.Header().Set("Link", "</assets/forgejo/api.v1.yml>; rel=\"service-desc\"")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package misc
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
)
|
||||
|
||||
// tplSwagger swagger page template
|
||||
const tplForgejoSwagger base.TplName = "swagger/forgejo-ui"
|
||||
|
||||
func SwaggerForgejo(ctx *context.Context) {
|
||||
ctx.Data["APIVersion"] = "v1"
|
||||
ctx.HTML(http.StatusOK, tplForgejoSwagger)
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Forgejo API</title>
|
||||
<link href="{{AssetUrlPrefix}}/css/swagger.css?v={{AssetVersion}}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<a class="swagger-back-link" href="{{AppUrl}}">{{svg "octicon-reply"}}{{.locale.Tr "return_to_gitea"}}</a>
|
||||
<div id="swagger-ui" data-source="{{AssetUrlPrefix}}/forgejo/api.{{.APIVersion}}.yml"></div>
|
||||
<script src="{{AssetUrlPrefix}}/js/forgejoswagger.js?v={{AssetVersion}}"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,21 @@
|
||||
// Copyright The Forgejo Authors.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAPIForgejoRoot(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
req := NewRequest(t, "GET", "/api/forgejo/v1")
|
||||
resp := MakeRequest(t, req, http.StatusNoContent)
|
||||
assert.Contains(t, resp.Header().Get("Link"), "/assets/forgejo/api.v1.yml")
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
// Copyright The Forgejo Authors.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/routers/api/forgejo/v1"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAPIForgejoVersion(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
req := NewRequest(t, "GET", "/api/forgejo/v1/version")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var version v1.Version
|
||||
DecodeJSON(t, resp, &version)
|
||||
assert.Equal(t, "development", *version.Number)
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import SwaggerUI from 'swagger-ui-dist/swagger-ui-es-bundle.js';
|
||||
import 'swagger-ui-dist/swagger-ui.css';
|
||||
|
||||
window.addEventListener('load', async () => {
|
||||
const url = document.getElementById('swagger-ui').getAttribute('data-source');
|
||||
|
||||
const ui = SwaggerUI({
|
||||
url: url,
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
docExpansion: 'none',
|
||||
defaultModelRendering: 'model', // don't show examples by default, because they may be incomplete
|
||||
presets: [
|
||||
SwaggerUI.presets.apis
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUI.plugins.DownloadUrl
|
||||
]
|
||||
});
|
||||
|
||||
window.ui = ui;
|
||||
});
|
Loading…
Reference in New Issue