github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/openapi/swagger.go (about)

     1  // Copyright 2022 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  // BSD 3-Clause License
    15  //
    16  // Copyright (c) 2020, Juan Font
    17  // All rights reserved.
    18  
    19  // This file is almost a copy of
    20  // https://github.com/juanfont/headscale/blob/19455399f4762fb0ab1308a78f4625ce746b2c51/swagger.go.
    21  // The only difference is the apiV1JSON variable.
    22  
    23  package openapi
    24  
    25  import (
    26  	"bytes"
    27  	_ "embed"
    28  	"html/template"
    29  	"net/http"
    30  
    31  	"github.com/pingcap/log"
    32  	"go.uber.org/zap"
    33  )
    34  
    35  //go:embed apiv1.swagger.json
    36  var apiV1JSON []byte
    37  
    38  // SwaggerUI renders the swagger ui.
    39  func SwaggerUI(
    40  	writer http.ResponseWriter,
    41  	_ *http.Request,
    42  ) {
    43  	swaggerTemplate := template.Must(template.New("swagger").Parse(`
    44  <html>
    45  	<head>
    46  	<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3/swagger-ui.css">
    47  
    48  	<script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-standalone-preset.js"></script>
    49  	<script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js" charset="UTF-8"></script>
    50  	</head>
    51  	<body>
    52  	<div id="swagger-ui"></div>
    53  	<script>
    54  		window.addEventListener('load', (event) => {
    55  			const ui = SwaggerUIBundle({
    56  			    url: "/swagger/v1/openapiv2.json",
    57  			    dom_id: '#swagger-ui',
    58  			    presets: [
    59  			      SwaggerUIBundle.presets.apis,
    60  			      SwaggerUIBundle.SwaggerUIStandalonePreset
    61  			    ],
    62  				plugins: [
    63                  	SwaggerUIBundle.plugins.DownloadUrl
    64              	],
    65  				deepLinking: true,
    66  				// TODO(kradalby): Figure out why this does not work
    67  				// layout: "StandaloneLayout",
    68  			  })
    69  			window.ui = ui
    70  		});
    71  	</script>
    72  	</body>
    73  </html>`))
    74  
    75  	var payload bytes.Buffer
    76  	if err := swaggerTemplate.Execute(&payload, struct{}{}); err != nil {
    77  		log.Warn("Could not render Swagger", zap.Error(err))
    78  
    79  		writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
    80  		writer.WriteHeader(http.StatusInternalServerError)
    81  		_, err := writer.Write([]byte("Could not render Swagger"))
    82  		log.Warn("Failed to write response", zap.Error(err))
    83  
    84  		return
    85  	}
    86  
    87  	writer.Header().Set("Content-Type", "text/html; charset=utf-8")
    88  	writer.WriteHeader(http.StatusOK)
    89  	_, err := writer.Write(payload.Bytes())
    90  	if err != nil {
    91  		log.Warn("Failed to write response", zap.Error(err))
    92  	}
    93  }
    94  
    95  // SwaggerAPIv1 serves the apiv1 swagger json file.
    96  func SwaggerAPIv1(
    97  	writer http.ResponseWriter,
    98  	_ *http.Request,
    99  ) {
   100  	writer.Header().Set("Content-Type", "application/json; charset=utf-8")
   101  	writer.WriteHeader(http.StatusOK)
   102  	if _, err := writer.Write(apiV1JSON); err != nil {
   103  		log.Warn("Failed to write response", zap.Error(err))
   104  	}
   105  }