mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-10-20 19:52:04 +00:00
[API] Forgejo API /api/forgejo/v1
(cherry picked from commit20b5669269) (cherry picked from commit1574643a6a) Update semantic version according to specification (cherry picked from commit22510f4130) Mise à jour de 'Makefile' (cherry picked from commitc3d85d8409) (cherry picked from commit5ea2309851) (cherry picked from commitec5217b9d1) (cherry picked from commit14f08e364b) (cherry picked from commitb4465c67b8) [API] [SEMVER] replace number with version (cherry picked from commitfba48e6497) (cherry picked from commit532ec5d878) [API] [SEMVER] [v1.20] less is replaced by css (cherry picked from commit01ca3a4f42) (cherry picked from commit1d928c3ab2) (cherry picked from commita39dc804cd) Conflicts: webpack.config.js (cherry picked from commitadc68578b3) (cherry picked from commit9b8d98475f) (cherry picked from commit2516103974) (cherry picked from commit18e6287963) (cherry picked from commite9694e67ab) (cherry picked from commita9763edaf0) (cherry picked from commite2b550f4fb) (cherry picked from commit2edac36701) [API] Forgejo API /api/forgejo/v1 (squash) Update semver as v1.20 is entering release candidate mode (cherry picked from commit4995098ec3) (cherry picked from commit578ccfdd27) (cherry picked from commit1bf6ac0952) (cherry picked from commit2fe16b2bfe) (cherry picked from commit7cd9d027ee) (cherry picked from commiteaed4be2ae) (cherry picked from commitcc94f3115f) (cherry picked from commitd7a77e35cc) (cherry picked from commitcd8eb68ab7) (cherry picked from commit68487ac95f) (cherry picked from commit616dceb565) (cherry picked from commit545fe5975b) (cherry picked from commitc042cf8eda) (cherry picked from commitae5e5a7468) (cherry picked from commit8034ef5fa2) (cherry picked from commitaaf0293034)
This commit is contained in:
parent
d7b3f85db2
commit
daafa8ce58
14 changed files with 398 additions and 2 deletions
32
Makefile
32
Makefile
|
|
@ -88,7 +88,10 @@ else
|
||||||
endif
|
endif
|
||||||
VERSION = ${GITEA_VERSION}
|
VERSION = ${GITEA_VERSION}
|
||||||
|
|
||||||
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
# SemVer
|
||||||
|
FORGEJO_VERSION := 5.0.0+0-gitea-1.20.0
|
||||||
|
|
||||||
|
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)" -X "code.gitea.io/gitea/routers/api/forgejo/v1.ForgejoVersion=$(FORGEJO_VERSION)"
|
||||||
|
|
||||||
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
||||||
|
|
||||||
|
|
@ -140,6 +143,8 @@ ifdef DEPS_PLAYWRIGHT
|
||||||
PLAYWRIGHT_FLAGS += --with-deps
|
PLAYWRIGHT_FLAGS += --with-deps
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
FORGEJO_API_SPEC := public/forgejo/api.v1.yml
|
||||||
|
|
||||||
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
|
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
|
||||||
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|g
|
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|g
|
||||||
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|"basePath": "/api/v1"|g
|
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|"basePath": "/api/v1"|g
|
||||||
|
|
@ -220,6 +225,8 @@ help:
|
||||||
@echo " - generate-license update license files"
|
@echo " - generate-license update license files"
|
||||||
@echo " - generate-gitignore update gitignore files"
|
@echo " - generate-gitignore update gitignore files"
|
||||||
@echo " - generate-manpage generate manpage"
|
@echo " - generate-manpage generate manpage"
|
||||||
|
@echo " - generate-forgejo-api generate the forgejo API from spec"
|
||||||
|
@echo " - forgejo-api-validate check if the forgejo API matches the specs"
|
||||||
@echo " - generate-swagger generate the swagger spec from code comments"
|
@echo " - generate-swagger generate the swagger spec from code comments"
|
||||||
@echo " - swagger-validate check if the swagger spec is valid"
|
@echo " - swagger-validate check if the swagger spec is valid"
|
||||||
@echo " - go-licenses regenerate go licenses"
|
@echo " - go-licenses regenerate go licenses"
|
||||||
|
|
@ -305,6 +312,27 @@ ifneq "$(TAGS)" "$(shell cat $(TAGS_EVIDENCE) 2>/dev/null)"
|
||||||
TAGS_PREREQ := $(TAGS_EVIDENCE)
|
TAGS_PREREQ := $(TAGS_EVIDENCE)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
OAPI_CODEGEN_PACKAGE ?= github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.12.4
|
||||||
|
KIN_OPENAPI_CODEGEN_PACKAGE ?= github.com/getkin/kin-openapi/cmd/validate@v0.114.0
|
||||||
|
FORGEJO_API_SERVER = routers/api/forgejo/v1/generated.go
|
||||||
|
|
||||||
|
.PHONY: generate-forgejo-api
|
||||||
|
generate-forgejo-api: $(FORGEJO_API_SPEC)
|
||||||
|
$(GO) run $(OAPI_CODEGEN_PACKAGE) -package v1 -generate chi-server,types $< > $(FORGEJO_API_SERVER)
|
||||||
|
|
||||||
|
.PHONY: forgejo-api-check
|
||||||
|
forgejo-api-check: generate-forgejo-api
|
||||||
|
@diff=$$(git diff $(FORGEJO_API_SERVER) ; \
|
||||||
|
if [ -n "$$diff" ]; then \
|
||||||
|
echo "Please run 'make generate-forgejo-api' and commit the result:"; \
|
||||||
|
echo "$${diff}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: forgejo-api-validate
|
||||||
|
forgejo-api-validate:
|
||||||
|
$(GO) run $(KIN_OPENAPI_CODEGEN_PACKAGE) $(FORGEJO_API_SPEC)
|
||||||
|
|
||||||
.PHONY: generate-swagger
|
.PHONY: generate-swagger
|
||||||
generate-swagger: $(SWAGGER_SPEC)
|
generate-swagger: $(SWAGGER_SPEC)
|
||||||
|
|
||||||
|
|
@ -335,7 +363,7 @@ checks: checks-frontend checks-backend
|
||||||
checks-frontend: lockfile-check svg-check
|
checks-frontend: lockfile-check svg-check
|
||||||
|
|
||||||
.PHONY: checks-backend
|
.PHONY: checks-backend
|
||||||
checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-validate security-check
|
checks-backend: tidy-check swagger-check fmt-check misspell-check forgejo-api-validate swagger-validate security-check
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: lint-frontend lint-backend
|
lint: lint-frontend lint-backend
|
||||||
|
|
|
||||||
40
public/forgejo/api.v1.yml
Normal file
40
public/forgejo/api.v1.yml
Normal file
|
|
@ -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:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
|
||||||
16
routers/api/forgejo/v1/api.go
Normal file
16
routers/api/forgejo/v1/api.go
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.gitea.io/gitea/modules/web"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Routes() *web.Route {
|
||||||
|
m := web.NewRoute()
|
||||||
|
forgejo := NewForgejo()
|
||||||
|
m.Get("", Root)
|
||||||
|
m.Get("/version", forgejo.GetVersion)
|
||||||
|
return m
|
||||||
|
}
|
||||||
24
routers/api/forgejo/v1/forgejo.go
Normal file
24
routers/api/forgejo/v1/forgejo.go
Normal file
|
|
@ -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})
|
||||||
|
}
|
||||||
167
routers/api/forgejo/v1/generated.go
Normal file
167
routers/api/forgejo/v1/generated.go
Normal file
|
|
@ -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 {
|
||||||
|
Version *string `json:"version,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
|
||||||
|
}
|
||||||
14
routers/api/forgejo/v1/root.go
Normal file
14
routers/api/forgejo/v1/root.go
Normal file
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/translation"
|
"code.gitea.io/gitea/modules/translation"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
actions_router "code.gitea.io/gitea/routers/api/actions"
|
actions_router "code.gitea.io/gitea/routers/api/actions"
|
||||||
|
forgejo "code.gitea.io/gitea/routers/api/forgejo/v1"
|
||||||
packages_router "code.gitea.io/gitea/routers/api/packages"
|
packages_router "code.gitea.io/gitea/routers/api/packages"
|
||||||
apiv1 "code.gitea.io/gitea/routers/api/v1"
|
apiv1 "code.gitea.io/gitea/routers/api/v1"
|
||||||
"code.gitea.io/gitea/routers/common"
|
"code.gitea.io/gitea/routers/common"
|
||||||
|
|
@ -175,6 +176,7 @@ func NormalRoutes() *web.Route {
|
||||||
|
|
||||||
r.Mount("/", web_routers.Routes())
|
r.Mount("/", web_routers.Routes())
|
||||||
r.Mount("/api/v1", apiv1.Routes())
|
r.Mount("/api/v1", apiv1.Routes())
|
||||||
|
r.Mount("/api/forgejo/v1", forgejo.Routes())
|
||||||
r.Mount("/api/internal", private.Routes())
|
r.Mount("/api/internal", private.Routes())
|
||||||
|
|
||||||
r.Post("/-/fetch-redirect", common.FetchRedirectDelegate)
|
r.Post("/-/fetch-redirect", common.FetchRedirectDelegate)
|
||||||
|
|
|
||||||
19
routers/web/misc/swagger-forgejo.go
Normal file
19
routers/web/misc/swagger-forgejo.go
Normal file
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -261,6 +261,7 @@ func Routes() *web.Route {
|
||||||
if setting.API.EnableSwagger {
|
if setting.API.EnableSwagger {
|
||||||
// Note: The route is here but no in API routes because it renders a web page
|
// Note: The route is here but no in API routes because it renders a web page
|
||||||
routes.Get("/api/swagger", append(mid, misc.Swagger)...) // Render V1 by default
|
routes.Get("/api/swagger", append(mid, misc.Swagger)...) // Render V1 by default
|
||||||
|
routes.Get("/api/forgejo/swagger", append(mid, misc.SwaggerForgejo)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: These really seem like things that could be folded into Contexter or as helper functions
|
// TODO: These really seem like things that could be folded into Contexter or as helper functions
|
||||||
|
|
|
||||||
13
templates/swagger/forgejo-ui.tmpl
Normal file
13
templates/swagger/forgejo-ui.tmpl
Normal file
|
|
@ -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>
|
||||||
21
tests/integration/api_forgejo_root_test.go
Normal file
21
tests/integration/api_forgejo_root_test.go
Normal file
|
|
@ -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")
|
||||||
|
}
|
||||||
25
tests/integration/api_forgejo_version_test.go
Normal file
25
tests/integration/api_forgejo_version_test.go
Normal file
|
|
@ -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.Version)
|
||||||
|
}
|
||||||
22
web_src/js/standalone/forgejo-swagger.js
Normal file
22
web_src/js/standalone/forgejo-swagger.js
Normal file
|
|
@ -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;
|
||||||
|
});
|
||||||
|
|
@ -76,6 +76,10 @@ export default {
|
||||||
webcomponents: [
|
webcomponents: [
|
||||||
fileURLToPath(new URL('web_src/js/webcomponents/webcomponents.js', import.meta.url)),
|
fileURLToPath(new URL('web_src/js/webcomponents/webcomponents.js', import.meta.url)),
|
||||||
],
|
],
|
||||||
|
forgejoswagger: [ // Forgejo swagger is OpenAPI 3.0.0 and has specific parameters
|
||||||
|
fileURLToPath(new URL('web_src/js/standalone/forgejo-swagger.js', import.meta.url)),
|
||||||
|
fileURLToPath(new URL('web_src/css/standalone/swagger.css', import.meta.url)),
|
||||||
|
],
|
||||||
swagger: [
|
swagger: [
|
||||||
fileURLToPath(new URL('web_src/js/standalone/swagger.js', import.meta.url)),
|
fileURLToPath(new URL('web_src/js/standalone/swagger.js', import.meta.url)),
|
||||||
fileURLToPath(new URL('web_src/css/standalone/swagger.css', import.meta.url)),
|
fileURLToPath(new URL('web_src/css/standalone/swagger.css', import.meta.url)),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue