Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

separated index.html and index.js to prevent unsafe-inline #120

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
79 changes: 42 additions & 37 deletions swagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ func Handler(configFns ...func(*Config)) http.HandlerFunc {

// create a template with name
index, _ := template.New("swagger_index.html").Parse(indexTempl)
indexJs, _ := template.New("swagger_index.js").Parse(indexJsTempl)

re := regexp.MustCompile(`^(.*/)([^?].*)?[?|.]*$`)

Expand Down Expand Up @@ -212,6 +213,8 @@ func Handler(configFns ...func(*Config)) http.HandlerFunc {
switch path {
case "index.html":
_ = index.Execute(w, config)
case "index.js":
_ = indexJs.Execute(w, config)
case "doc.json":
doc, err := swag.ReadDoc(config.InstanceName)
if err != nil {
Expand All @@ -236,6 +239,44 @@ func Handler(configFns ...func(*Config)) http.HandlerFunc {
}
}

const indexJsTempl = `
window.onload = function() {
{{- if .BeforeScript}}
{{.BeforeScript}}
{{- end}}
// Build a system
const ui = SwaggerUIBundle({
url: "{{.URL}}",
deepLinking: {{.DeepLinking}},
docExpansion: "{{.DocExpansion}}",
dom_id: "#{{.DomID}}",
persistAuthorization: {{.PersistAuthorization}},
validatorUrl: null,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
{{- range $plugin := .Plugins }},
{{$plugin}}
{{- end}}
],
{{- range $k, $v := .UIConfig}}
{{$k}}: {{$v}},
{{- end}}
layout: "{{$.Layout}}",
defaultModelsExpandDepth: {{.DefaultModelsExpandDepth}},
showExtensions: {{.ShowExtensions}}
})

window.ui = ui
{{- if .AfterScript}}
{{.AfterScript}}
{{- end}}
}
`

const indexTempl = `<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
Expand Down Expand Up @@ -302,45 +343,9 @@ const indexTempl = `<!-- HTML for static distribution bundle build -->

<div id="swagger-ui"></div>

<script src="./index.js"> </script>
<script src="./swagger-ui-bundle.js"> </script>
<script src="./swagger-ui-standalone-preset.js"> </script>
<script>
window.onload = function() {
{{- if .BeforeScript}}
{{.BeforeScript}}
{{- end}}
// Build a system
const ui = SwaggerUIBundle({
url: "{{.URL}}",
deepLinking: {{.DeepLinking}},
docExpansion: "{{.DocExpansion}}",
dom_id: "#{{.DomID}}",
persistAuthorization: {{.PersistAuthorization}},
validatorUrl: null,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
{{- range $plugin := .Plugins }},
{{$plugin}}
{{- end}}
],
{{- range $k, $v := .UIConfig}}
{{$k}}: {{$v}},
{{- end}}
layout: "{{$.Layout}}",
defaultModelsExpandDepth: {{.DefaultModelsExpandDepth}},
showExtensions: {{.ShowExtensions}}
})

window.ui = ui
{{- if .AfterScript}}
{{.AfterScript}}
{{- end}}
}
</script>
</body>

</html>
Expand Down
121 changes: 25 additions & 96 deletions swagger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,83 +300,6 @@ func TestUIConfigOptions(t *testing.T) {
exp string
}

hdr := `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}

body {
margin:0;
background: #fafafa;
}
</style>
</head>

<body>

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
<defs>
<symbol viewBox="0 0 20 20" id="unlocked">
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
</symbol>

<symbol viewBox="0 0 20 20" id="locked">
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
</symbol>

<symbol viewBox="0 0 20 20" id="close">
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
</symbol>

<symbol viewBox="0 0 20 20" id="large-arrow">
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
</symbol>

<symbol viewBox="0 0 20 20" id="large-arrow-down">
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
</symbol>

<symbol viewBox="0 0 24 24" id="jump-to">
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
</symbol>

<symbol viewBox="0 0 24 24" id="expand">
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
</symbol>
</defs>
</svg>

<div id="swagger-ui"></div>

<script src="./swagger-ui-bundle.js"> </script>
<script src="./swagger-ui-standalone-preset.js"> </script>
<script>
`
ftr := `
</script>
</body>

</html>
`

fixtures := []fixture{
{
desc: "default configuration",
Expand All @@ -389,14 +312,15 @@ func TestUIConfigOptions(t *testing.T) {
Layout: StandaloneLayout,
DefaultModelsExpandDepth: ShowModel,
},
exp: `window.onload = function() {

exp: `
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
url: "doc.json",
deepLinking: true ,
deepLinking: true,
docExpansion: "list",
dom_id: "#swagger-ui",
persistAuthorization: false ,
persistAuthorization: false,
validatorUrl: null,
presets: [
SwaggerUIBundle.presets.apis,
Expand All @@ -406,11 +330,13 @@ func TestUIConfigOptions(t *testing.T) {
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout",
defaultModelsExpandDepth: 1
defaultModelsExpandDepth: 1,
showExtensions: false
})

window.ui = ui
}`,
}
`,
},
{
desc: "script configuration",
Expand Down Expand Up @@ -440,18 +366,19 @@ func TestUIConfigOptions(t *testing.T) {
},
DefaultModelsExpandDepth: HideModel,
},
exp: `window.onload = function() {
const SomePlugin = (system) => ({
exp: `
window.onload = function() {
const SomePlugin = (system) =&gt; ({
// Some plugin
});


// Build a system
const ui = SwaggerUIBundle({
url: "swagger.json",
deepLinking: false ,
deepLinking: false,
docExpansion: "none",
dom_id: "#swagger-ui-id",
persistAuthorization: true ,
persistAuthorization: true,
validatorUrl: null,
presets: [
SwaggerUIBundle.presets.apis,
Expand All @@ -462,36 +389,38 @@ func TestUIConfigOptions(t *testing.T) {
SomePlugin,
AnotherPlugin
],
defaultModelRendering: "model",
onComplete: () => { window.ui.setBasePath('v3'); },
defaultModelRendering: &#34;model&#34;,
onComplete: () =&gt; { window.ui.setBasePath(&#39;v3&#39;); },
showExtensions: true,
layout: "StandaloneLayout",
defaultModelsExpandDepth: -1
defaultModelsExpandDepth: -1,
showExtensions: false
})

window.ui = ui
const someOtherCode = function(){
// Do something
};
someOtherCode();
}`,
}
`,
},
}

for _, fix := range fixtures {
t.Run(fix.desc, func(t *testing.T) {
tmpl := template.New("swagger_index.html")
index, err := tmpl.Parse(indexTempl)
tmpl := template.New("swagger_index.js")
indexJs, err := tmpl.Parse(indexJsTempl)
if err != nil {
t.Fatal(err)
}

buf := bytes.NewBuffer(nil)
if err := index.Execute(buf, fix.cfg); err != nil {
if err := indexJs.Execute(buf, fix.cfg); err != nil {
t.Fatal(err)
}

exp := hdr + fix.exp + ftr
exp := fix.exp

// Compare line by line
explns := strings.Split(exp, "\n")
Expand Down
Loading