Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ auth := okapi.BasicAuth{
Username: "admin",
Password: "password",
Realm: "Restricted",
ContextKey: "user",// where to store the username e.g. "user", default(username)

}
// Global middleware
o.Use(auth.Middleware)
Expand Down Expand Up @@ -498,7 +500,7 @@ Example:
```go
jwtAuth.ValidateClaims = func(c Context, claims jwt.Claims) error {
method := c.Request().Method
fPrint("Request method,", "method", method)
slog.Info("Request method,", "method", method)
mapClaims, ok := claims.(jwt.MapClaims)
if !ok {
return errors.New("invalid claims type")
Expand Down
2 changes: 1 addition & 1 deletion constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@ const banner = `
| | | | |/ / _` + "`" + ` | '_ \| |
| |_| | < (_| | |_) | |
\___/|_|\_\__,_| .__/|_|
|_|`
🦒 |_|`
91 changes: 91 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,94 @@
//
// For more information and documentation, visit: https://github.com/jkaninda/okapi
package okapi

import (
"html/template"
"net/http"
)

const (
redoc = `

<!DOCTYPE html>
<html>
<head>
<title> {{.Title }}</title>
<!-- needed for adaptive design -->
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<!--
Redoc doesn't change outer page styles
-->
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<redoc spec-URL='/openapi.json'></redoc>
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"> </script>
</body>
</html>
`
swagger = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="SwaggerUI" />
<title> {{.Title }}</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.27.1/swagger-ui.css" />
<link rel="icon" type="image/png" sizes="32x32" href="https://unpkg.com/swagger-ui-dist@5.27.1/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="https://unpkg.com/swagger-ui-dist@5.27.1/favicon-16x16.png">
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5.27.1/swagger-ui-bundle.js" charset="UTF-8"></script>
<script src="https://unpkg.com/swagger-ui-dist@5.27.1/swagger-ui-standalone-preset.js" charset="UTF-8"></script>
<script src="https://unpkg.com/swagger-ui-dist@5.27.1/swagger-initializer.js" charset="UTF-8"></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
url: '/openapi.json',
dom_id: '#swagger-ui',
deepLinking: true,
});
};
</script>
</body>
</html>
`
)

var (
redocTemplate = template.Must(template.New("redoc").Parse(redoc))
swaggerTemplate = template.Must(template.New("swagger").Parse(swagger))
)

// registerDocRoutes registers the OpenAPI documentation routes for the Okapi instance.
func (o *Okapi) registerDocRoutes(title string) {
// Register the OpenAPI JSON route
o.Get(openApiDocPath, func(c Context) error {
return c.JSON(http.StatusOK, o.openapiSpec)
}).internalRoute().Hide() // Hide the route from the OpenAPI documentation
// Register the swagger route
o.Get(openApiDocPrefix, func(c Context) error {
return c.renderHTML(http.StatusOK, swaggerTemplate, M{"Title": title})
},
).internalRoute().Hide() // Hide the route from the OpenAPI documentation
// TODO: remove this route in the next major release
o.Get("/docs/index.html", func(c Context) error {
return c.renderHTML(http.StatusOK, swaggerTemplate, M{"Title": title})
},
).internalRoute().Hide() // Hide the route from the OpenAPI documentation
// Register the Redoc route
o.Get("/redoc", func(c Context) error {
return c.renderHTML(http.StatusOK, redocTemplate, M{"Title": title})
},
).internalRoute().Hide() // Hide the route from the OpenAPI documentation
}
111 changes: 0 additions & 111 deletions doc_handler.go

This file was deleted.

5 changes: 3 additions & 2 deletions doc_handler_test.go → doc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ import (
"testing"
)

func TestRegisterDocUI(t *testing.T) {
func TestRegisterDocRoutes(t *testing.T) {
o := New()
o.Get("/", func(c Context) error {
return c.Text(http.StatusOK, "Hello World!")
})

o.registerDocUIHandler(o.openAPI.Title)
o.registerDocRoutes(o.openAPI.Title)

go func() {
if err := o.Start(); err != nil && !errors.Is(err, http.ErrServerClosed) {
Expand All @@ -51,6 +51,7 @@ func TestRegisterDocUI(t *testing.T) {
}(o)

waitForServer()
assertStatus(t, "GET", "http://localhost:8080/openapi.json", nil, nil, "", http.StatusOK)
assertStatus(t, "GET", "http://localhost:8080/docs", nil, nil, "", http.StatusOK)
assertStatus(t, "GET", "http://localhost:8080/redoc", nil, nil, "", http.StatusOK)

Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ go 1.24.5
require (
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/gorilla/mux v1.8.1
google.golang.org/protobuf v1.36.7
google.golang.org/protobuf v1.36.8
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/getkin/kin-openapi v0.132.0
github.com/google/uuid v1.6.0
github.com/jkaninda/go-utils v0.1.1
github.com/jkaninda/go-utils v0.1.3
github.com/stretchr/testify v1.10.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-openapi/jsonpointer v0.21.1 // indirect
github.com/go-openapi/jsonpointer v0.21.2 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58=
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
github.com/go-openapi/jsonpointer v0.21.2 h1:AqQaNADVwq/VnkCmQg6ogE+M3FOsKTytwges0JdwVuA=
github.com/go-openapi/jsonpointer v0.21.2/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
Expand All @@ -16,8 +16,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/jkaninda/go-utils v0.1.1 h1:PMrtXR9d51YzHo85y9Z6YVL0YyBURbRTPemHVbFDqZg=
github.com/jkaninda/go-utils v0.1.1/go.mod h1:pf0/U6k4JbxlablM2G4eSTZdQ2LFshfAsCK5Q8qNfGo=
github.com/jkaninda/go-utils v0.1.3 h1:BhVRHpR6JIGhE7JVgqOgiFketIqmNtvMvYpveVwDqqY=
github.com/jkaninda/go-utils v0.1.3/go.mod h1:Aa54jEAcDykc3CnOdreqZG80UfSZOvrYecyusu+oPb4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
Expand All @@ -42,8 +42,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
Expand Down
15 changes: 6 additions & 9 deletions okapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"bufio"
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"github.com/getkin/kin-openapi/openapi3"
Expand Down Expand Up @@ -533,13 +532,8 @@ func (o *Okapi) WithOpenAPIDocs(cfg ...OpenAPI) *Okapi {
}

o.buildOpenAPISpec()

o.router.mux.HandleFunc(openApiDocPath, func(w http.ResponseWriter, r *http.Request) {
w.Header().Set(ContentTypeHeader, "application/json")
_ = json.NewEncoder(w).Encode(o.openapiSpec)
})
// Register the Swagger UI handler
o.registerDocUIHandler(o.openAPI.Title)
// Register the OpenAPI JSON and Swagger UI routes
o.registerDocRoutes(o.openAPI.Title)
return o
}

Expand Down Expand Up @@ -883,11 +877,12 @@ func (o *Okapi) addRoute(method, path string, tags []string, h HandleFunc, opts
Name: handleName(h),
Path: path,
Method: method,
tags: tags,
tags: goutils.RemoveDuplicates(tags),
handle: h,
chain: o,
responses: make(map[int]*openapi3.SchemaRef),
}
// Register all route options
for _, opt := range opts {
opt(route)
}
Expand All @@ -900,10 +895,12 @@ func (o *Okapi) addRoute(method, path string, tags []string, h HandleFunc, opts
response: &response{writer: w},
okapi: o,
}
// if the route is disabled, return 404 Not Found
if route.disabled {
http.Error(w, "404 Not Found", http.StatusNotFound)
return
}
// Any error returned by the route will result in a 500 Internal Server Error
if err := route.handler(ctx); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
Expand Down
4 changes: 2 additions & 2 deletions openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ func (o *Okapi) buildOpenAPISpec() {
OperationID: r.operationId,
Summary: r.summary,
Description: r.description,
Tags: r.tags,
Tags: goutils.RemoveDuplicates(r.tags), // Remove duplicates in tags
Parameters: append(append(r.pathParams, r.queryParams...), r.headers...),
Responses: &openapi3.Responses{},
Deprecated: r.deprecated,
Expand All @@ -741,7 +741,7 @@ func (o *Okapi) buildOpenAPISpec() {

// Add example if available
if r.requestExample != nil {
requestBody.Content["application/json"].Example = r.requestExample
requestBody.Content[JSON].Example = r.requestExample
}

op.RequestBody = &openapi3.RequestBodyRef{Value: requestBody}
Expand Down
Loading