github.com/weaviate/weaviate@v1.24.6/adapters/handlers/rest/swagger_middleware/swagger_middleware.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package swagger_middleware 13 14 import ( 15 "fmt" 16 "html/template" 17 "net/http" 18 "strings" 19 ) 20 21 const swaggerUIVersion = "3.19.4" 22 23 type templateData struct { 24 Prefix string 25 APIKey string 26 APIToken string 27 } 28 29 func AddMiddleware(swaggerJSON []byte, next http.Handler) http.Handler { 30 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 31 if strings.HasPrefix(r.URL.Path, "/v1/swagger.json") && r.Method == http.MethodGet { 32 w.Header().Set("Content-Type", "application/json") 33 w.Write(swaggerJSON) 34 } else if strings.HasPrefix(r.URL.Path, "/v1/swagger") && r.Method == http.MethodGet { 35 renderSwagger(w, r) 36 } else { 37 next.ServeHTTP(w, r) 38 } 39 }) 40 } 41 42 // renderswagger renders the swagger GUI 43 func renderSwagger(w http.ResponseWriter, r *http.Request) { 44 w.Header().Set("WWW-Authenticate", `Basic realm="Provide your key and token (as username as password respectively)"`) 45 46 user, password, authOk := r.BasicAuth() 47 if !authOk { 48 http.Error(w, "Not authorized", 401) 49 return 50 } 51 52 t := template.New("Swagger") 53 t, err := t.Parse(swaggerTemplate) 54 if err != nil { 55 http.Error(w, err.Error(), http.StatusInternalServerError) 56 return 57 } 58 59 // Create result string 60 d := templateData{ 61 Prefix: fmt.Sprintf("https://cdn.jsdelivr.net/npm/swagger-ui-dist@%s", swaggerUIVersion), 62 APIKey: user, 63 APIToken: password, 64 } 65 66 err = t.ExecuteTemplate(w, "index", d) 67 if err != nil { 68 http.Error(w, err.Error(), http.StatusInternalServerError) 69 } 70 } 71 72 // tmpl is the page template to render GraphiQL 73 const swaggerTemplate = ` 74 {{ define "index" }} 75 <!-- HTML for static distribution bundle build --> 76 <!DOCTYPE html> 77 <html lang="en"> 78 <head> 79 <meta charset="UTF-8"> 80 <title>Weaviate API</title> 81 <link rel="stylesheet" type="text/css" href="{{ .Prefix }}/swagger-ui.css" > 82 <link rel="icon" type="image/png" href="{{ .Prefix }}/favicon-32x32.png" sizes="32x32" /> 83 <link rel="icon" type="image/png" href="{{ .Prefix }}/favicon-16x16.png" sizes="16x16" /> 84 <style> 85 html 86 { 87 box-sizing: border-box; 88 overflow: -moz-scrollbars-vertical; 89 overflow-y: scroll; 90 } 91 92 *, 93 *:before, 94 *:after 95 { 96 box-sizing: inherit; 97 } 98 99 body 100 { 101 margin:0; 102 background: #fafafa; 103 } 104 </style> 105 </head> 106 107 <body> 108 <div id="swagger-ui"></div> 109 110 <script src="{{ .Prefix }}/swagger-ui-bundle.js"> </script> 111 <script src="{{ .Prefix }}/swagger-ui-standalone-preset.js"> </script> 112 <script> 113 window.onload = function() { 114 115 // Build a system 116 const ui = SwaggerUIBundle({ 117 url: "/v1/swagger.json", 118 dom_id: '#swagger-ui', 119 deepLinking: true, 120 presets: [ 121 SwaggerUIBundle.presets.apis, 122 SwaggerUIStandalonePreset 123 ], 124 requestInterceptor: function(request) { 125 request.headers["X-API-KEY"] = "{{ .APIKey }}" 126 request.headers["X-API-TOKEN"] = "{{ .APIToken }}" 127 128 var requestUrl = null 129 try { 130 requestUrl = new URL(request.url) 131 } catch (err) { 132 console.log("Could not parse url in request", request, "; not checking if we need to change the protocol.") 133 } 134 135 if (requestUrl != null && requestUrl.protocol != location.protocol) { 136 requestUrl.protocol = location.protocol 137 request.url = requestUrl.toString() 138 } 139 140 return request 141 }, 142 plugins: [ 143 SwaggerUIBundle.plugins.DownloadUrl 144 ], 145 layout: "StandaloneLayout" 146 }) 147 148 window.ui = ui 149 } 150 </script> 151 </body> 152 </html> 153 {{ end }} 154 `