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

Static Route doesn't resolve correctly link that start with ./ #1228

Closed
mdaneri opened this issue Jan 5, 2024 · 19 comments · Fixed by #1246
Closed

Static Route doesn't resolve correctly link that start with ./ #1228

mdaneri opened this issue Jan 5, 2024 · 19 comments · Fixed by #1246
Assignees
Labels

Comments

@mdaneri
Copy link
Contributor

mdaneri commented Jan 5, 2024

Describe the Bug

I have this webpage

<!DOCTYPE html>
<!-- HTML for static distribution bundle build -->
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Swagger Editor</title>
  <style>
  * {
    box-sizing: border-box;
  }
  body {
    font-family: Roboto,sans-serif;
    font-size: 9px;
    line-height: 1.42857143;
    color: #444;
    margin: 0px;
  }

  #swagger-editor {
    font-size: 1.3em;
  }

  .container {
    height: 100%;
    max-width: 880px;
    margin-left: auto;
    margin-right: auto;
  }

  #editor-wrapper {
    height: 100%;
    border:1em solid #000;
    border:none;
  }

  .Pane2 {
    overflow-y: scroll;
  }

  </style>
  <link href="./swagger-editor-dist/swagger-editor.css" rel="stylesheet">
  <link rel="icon" type="image/png" href="./swagger-editor-dist/favicon-32x32.png" sizes="32x32" />
  <link rel="icon" type="image/png" href="./swagger-editor-dist/favicon-16x16.png" sizes="16x16" />
</head>

<body>
  <div id="swagger-editor"></div>
  <script src="./swagger-editor-dist/swagger-editor-bundle.js"> </script>
  <script src="./swagger-editor-dist/swagger-editor-standalone-preset.js"> </script>
  <script>
  window.onload = function() {
    // Build a system
    // info here https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md#core
    const editor = SwaggerEditorBundle({
      dom_id: '#swagger-editor',
      layout: 'StandaloneLayout',
      presets: [
        SwaggerEditorStandalonePreset
      ],
      queryConfigEnabled: false,
      url: "$($data.OpenApi)",
      requestSnippetsEnabled: true
    })

  window.editor = editor
    window.editor = editor
  }
  </script>
  

</body>

</html>

this page is published using

   # set a default path
        $Path = Protect-PodeValue -Value $Path -Default "/docs/swagger-editor"
        if ([string]::IsNullOrWhiteSpace($Title)) {
            throw "No route path supplied for $($Type) page"
        }
        if (Test-OpenAPIVersion -Version 3.1 -DefinitionTag $DefinitionTag) {
            throw "This version on Swagger-Editor doesn't support OpenAPI 3.1"
        }
        # setup meta info
        $meta = @{
            Title             = $Title
            OpenApi           = $OpenApiUrl
            DarkMode          = $DarkMode
            DefinitionTag     = $DefinitionTag
            SwaggerEditorDist = "$Path/swagger-editor-dist"
        }
        $route = Add-PodeRoute -Method Get -Path $Path `
            -Middleware $Middleware -ArgumentList $meta -EndpointName $EndpointName -PassThru -ScriptBlock {
            param($meta)
            $Data = @{
                Title             = $meta.Title
                OpenApi           = $meta.OpenApi
                SwaggerEditorDist = $meta.SwaggerEditorDist
            }

            $podeRoot = Get-PodeModuleMiscPath
            Write-PodeFileResponse -Path ([System.IO.Path]::Combine($podeRoot, 'default-swagger-editor.html.pode')) -Data $Data
        }

        $swaggerEditorPath = Join-Path -Path $(Get-PodeModuleMiscPath) -ChildPath 'swagger-editor-dist'
        Add-PodeStaticRoute -Path  $meta.SwaggerEditorDist -Source $swaggerEditorPath -EndpointName $EndpointName

        $PodeContext.Server.OpenAPI[$DefinitionTag].hiddenComponents.viewer['editor'] = $Path

all static files are under the swagger-editor-dist folder

Problem

when I open the page I get errors that all links are not valid
I checked the content of $WebEvent and this is the result

{
    "AcceptEncoding": "",
    "Path": "/docs/swagger-editor-dist/favicon-16x16.png",
    "Response": {
        "StatusCode": 200,
        "SendChunked": false,
        "Headers": {
            "Count": 5,
            "Keys": "Access-Control-Allow-Origin Access-Control-Allow-Credentials Access-Control-Max-Age Access-Control-Allow-Headers Access-Control-Allow-Methods"
        },
        "OutputStream": {
            "CanRead": true,
            "CanSeek": true,
            "CanWrite": true,
            "Capacity": 0,
            "Length": 0,
            "Position": 0,
            "CanTimeout": false,
            "ReadTimeout": null,
            "WriteTimeout": null
        },
        "Sent": false,
        "IsDisposed": false,
        "StatusDescription": "OK",
        "ContentLength64": 0,
        "ContentType": "",
        "HttpResponseLine": "HTTP/1.1 200 OK\r\n"
    },
    "Streamed": true,
    "Data": null,
    "Cookies": {},
    "Request": {
        "HttpMethod": "GET",
        "QueryString": null,
        "Protocol": "HTTP/1.1",
        "ProtocolVersion": "1.1",
        "ContentType": "",
        "ContentLength": 0,
        "ContentEncoding": {
            "Preamble": null,
            "BodyName": "utf-8",
            "EncodingName": "Unicode (UTF-8)",
            "HeaderName": "utf-8",
            "WebName": "utf-8",
            "WindowsCodePage": 1200,
            "IsBrowserDisplay": true,
            "IsBrowserSave": true,
            "IsMailNewsDisplay": true,
            "IsMailNewsSave": true,
            "IsSingleByte": false,
            "EncoderFallback": "System.Text.EncoderReplacementFallback",
            "DecoderFallback": "System.Text.DecoderReplacementFallback",
            "IsReadOnly": true,
            "CodePage": 65001
        },
        "TransferEncoding": "",
        "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "UrlReferrer": "http://localhost:8081/docs/swagger-editor",
        "Url": "http://localhost:8081/docs/swagger-editor-dist/favicon-16x16.png",
        "Headers": {
            "Sec-Fetch-Mode": "no-cors",
            "Sec-Fetch-Dest": "image",
            "Referer": "http://localhost:8081/docs/swagger-editor",
            "Sec-GPC": "1",
            "sec-ch-ua-platform": "\"Windows\"",
            "Cookie": "pode.sid=s:ef35f34c-673a-4b49-9ca5-0c8912c566d0.LnTLYqmm6jNkNDs2bi5OYUAjyMCgZdyBPMU72Rmafhg=",
            "Accept": "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
            "Connection": "keep-alive",
            "sec-ch-ua-mobile": "?0",
            "Host": "localhost:8081",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
            "Accept-Language": "en-US,en",
            "Accept-Encoding": "gzip, deflate, br",
            "sec-ch-ua": "\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Brave\";v=\"120\"",
            "Sec-Fetch-Site": "same-origin"
        },
        "RawBody": [],
        "Host": "localhost:8081",
        "AwaitingBody": false,
        "Form": null,
        "Body": "",
        "CloseImmediately": false,
        "IsProcessable": true,
        "RemoteEndPoint": {
            "AddressFamily": 2,
            "Address": "127.0.0.1",
            "Port": 63863
        },
        "LocalEndPoint": {
            "AddressFamily": 2,
            "Address": "127.0.0.1",
            "Port": 8081
        },
        "IsSsl": false,
        "SslUpgraded": false,
        "IsKeepAlive": true,
        "InputStream": {
            "Socket": "System.Net.Sockets.Socket",
            "CanRead": true,
            "CanSeek": false,
            "CanWrite": true,
            "CanTimeout": true,
            "ReadTimeout": 100,
            "WriteTimeout": -1,
            "DataAvailable": false,
            "Length": null,
            "Position": null
        },
        "Certificate": null,
        "AllowClientCertificate": false,
        "TlsMode": 0,
        "ClientCertificate": null,
        "ClientCertificateErrors": 0,
        "Protocols": 3120,
        "Error": null,
        "IsAborted": false,
        "IsDisposed": false,
        "Address": "127.0.0.1:8081",
        "Scheme": "Http",
        "Type": 1,
        "IsHttp": true,
        "IsWebSocket": false,
        "IsSmtp": false,
        "IsTcp": false,
        "IsUnknown": false
    },
    "Timestamp": "2024-01-05T03:07:52.1728449Z",
    "ContentType": "",
    "Files": null,
    "Parameters": null,
    "Auth": {},
    "StaticContent": null,
    "Lockable": {},
    "PendingCookies": {},
    "TransferEncoding": "",
    "Ranges": null,
    "OnEnd": [],
    "Endpoint": {
        "Address": "localhost:8081",
        "Protocol": "http",
        "Name": null
    },
    "Method": "get",
    "Route": null,
    "Query": null,
    "ErrorType": null
}

"Path" is /docs/swagger-editor-dist/favicon-16x16.png instead of /docs/swagger-editor/swagger-editor-dist/favicon-16x16.png

@mdaneri mdaneri changed the title Static Route doesn't resolve correctly url with . Static Route doesn't resolve correctly url starting with./ Jan 5, 2024
@mdaneri mdaneri changed the title Static Route doesn't resolve correctly url starting with./ Static Route doesn't resolve correctly url starting with. / Jan 5, 2024
@mdaneri mdaneri changed the title Static Route doesn't resolve correctly url starting with. / Static Route doesn't resolve correctly url starting with./ Jan 5, 2024
@mdaneri mdaneri changed the title Static Route doesn't resolve correctly url starting with./ Static Route doesn't resolve correctly url starting with ./ Jan 5, 2024
@mdaneri mdaneri changed the title Static Route doesn't resolve correctly url starting with ./ Static Route doesn't resolve correctly link that start with ./ Jan 5, 2024
@Badgerati
Copy link
Owner

Hi @mdaneri,

The translation is done at the HTML level client side. If I remember rightly relative paths in HTML are based on the current "folder" which in this case would be /docs as /swagger-editor is the document you're viewing rather than a folder (as far as the client side is concerned). So you'd need to add ./swagger-editor to all the URLs - which which work if someone was using a custom URL for the editor.

You do have the static content path available in $data.SwaggerEditorDist, so dynamic generating the href URLs could work:

<link rel="icon" type="image/png" href="$($data.SwaggerEditorDist)/favicon-32x32.png" sizes="32x32" />

@mdaneri
Copy link
Contributor Author

mdaneri commented Jan 17, 2024

Yes but this is a workaround I have to use to make it works.

If I use any other webserver (IIS, Apache or anything else) and my page is http://localhost/rootpage/test/index.html`
./swagger-editor-dist/swagger-editor.css inside index.html redirects to http://localhost/rootpage/test/swagger-editor/swagger-editor-dist/swagger-editor.css not to http://localhost/rootpage/swagger-editor/swagger-editor-dist/swagger-editor.css

@Badgerati
Copy link
Owner

But the correct option is what's occurring no?

Your page is at http://localhost/docs/swagger-editor and your href is ./swagger-editor-dist/swagger-editor.css, therefore it would load the content from http://localhost/docs/swagger-editor-dist/swagger-editor.css

If the page was at http://localhost/docs/swagger-editor/index.html as it was loading the css from http://localhost/docs/swagger-editor-dist/swagger-editor.css I'd agree, but in the former example /swagger-editor is the document rather than a folder 🤔

@mdaneri
Copy link
Contributor Author

mdaneri commented Jan 17, 2024

I created a sample to replicate the issue.
https://github.com/mdaneri/Pode/tree/develop/examples/SwaggerEditor.
this is the way I'm publishing the editor

 # STATIC asset folder route
    Add-PodeStaticRoute -Path '/editor' -Source './www' -Defaults @('index.html')
    Add-PodeStaticRoute -Path '/editor/swagger-editor-dist' -Source './swagger-editor-dist'
    Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
        Move-PodeResponseUrl -Url '/editor'
    }

It should work, but it's not.

@mdaneri
Copy link
Contributor Author

mdaneri commented Jan 18, 2024

Looks like the issue is not related to the translation but the static routes order.

I changed the code and now more or less is working

   # STATIC asset folder route
    Add-PodeStaticRoute -Path '/editor/swagger-editor-dist' -Source './swagger-editor-dist'
    Add-PodeStaticRoute -Path '/editor' -Source './www' -Defaults @('index.html')

    Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
        Move-PodeResponseUrl -Url '/editor'
    }

What is not working is the -Defaults @('index.html')
I have to specify http://localhost:8085/editor/index.html to access the page

This looks like a bug. Can you please confirm it?

@Badgerati
Copy link
Owner

Ah yes, the ordering that hierarchical routes like that are created in does matter.

It's been reported before that the -Defaults doesn't work, but I could never reproduce it; I'll try again just in case.

@Badgerati
Copy link
Owner

Hi @mdaneri,

I just tested myself and http://localhost:8085/editor does load the index.html page, however it is just a white screen - which makes sense as the ./swagger-editor-dist/swagger-editor.css references would call http://localhost:8085/swagger-editor-dist/swagger-editor.css which doesn't exist.

If I do call http://localhost:8085/editor/index.html directly the page loads normally, because the relative ./swagger-editor-dist/swagger-editor.css path would map from the /editor folder in the URL.

Other than that, the -Defaults is working and using index.html for me; do you get something different like a 404 page?

@mdaneri
Copy link
Contributor Author

mdaneri commented Jan 22, 2024

I created 2 samples and removed the swagger-editor-dist folder.
Now is using the /src/Misc/swagger-editor-dist folder as source.

  • swagger-editor.ps1 - the editor works but not -Defaults @('index.html')
  • swagger-editor-broken.ps1 - the editor doesn't work but -Defaults @('index.html') works as expected

@Badgerati
Copy link
Owner

Hi @mdaneri,

I'm still seeing the same as my previous response. For the swagger-editor-broken.ps1 I would expect this to not work, as the order the static routes are created in does matter, and the longer /editor/swagger-editor-dist route does need to be created before the /editor route.

For swagger-editor.ps1 though, this does load the index.html content when navigating to http://localhost:8085/editor for me; though I do get a white screen because the CSS/JS it's trying to load can't be found:
image

However if I update the index.html CSS/JS to include /editor as well:

<link href="./editor/swagger-editor-dist/swagger-editor.css" rel="stylesheet">

Then loading the page works:
image

This is expected to me, because the CSS/JS relative paths will be looking for http://localhost:8085/swagger-editor-dist/swagger-editor.css when loaded from http://localhost:8085/editor, because the /editor part is a page not a folder like it would be with http://localhost:8085/editor/index.html.

Is this the same as what you're seeing, or are you seeing something different - like a 404 page instead of a white page?

@mdaneri
Copy link
Contributor Author

mdaneri commented Jan 27, 2024

Sorry, I misread your previous comment when you said that "the ordering that hierarchical routes like that are created does matter."
I understood the opposite 😀

Do we have this limitation in the documentation?

Do you think is worth spending time to fix it?

@Badgerati
Copy link
Owner

It'd be a difficult one to fix without breaking people's integrations who are already aware that the order matters. Best to fix it in 3.0.0 😉

For now, adding a section into the /Tutorials/Routes/Utilities/StaticContent page in the docs it good enough.

@mdaneri
Copy link
Contributor Author

mdaneri commented Jan 28, 2024

Maybe a check with a warning can be good enough

@Badgerati
Copy link
Owner

I had a thought about this last night; it should be fine to fix for just static content. I've an idea on how to quickly fix it, which I'll commit in a moment.

@mdaneri
Copy link
Contributor Author

mdaneri commented Jan 30, 2024

Please can you fix the default page issue?

@Badgerati
Copy link
Owner

What is the problem you're actually seeing with -Default, have you any screenshots, etc.? Because for me it's working as expected.

@Badgerati
Copy link
Owner

That commit, for static content only, will sort the paths it's searching on into the correct order. I've tested it using your editor examples, and flipping the two static route definitions around, and all works now for me regardless of order the routes are created in.

@mdaneri
Copy link
Contributor Author

mdaneri commented Jan 31, 2024

Yes, it is working, and the route order is not relevant now. But still, the page doesn't work unless I use http://localhost:8085/editor/index.html

The page should work without the need to specify index.html in the URL.
if you try http://localhost:8085 automatically, you are redirected to http://localhost:8085/editor, and the index.html is loaded, but the links on the page are broken.

image
image

This is the issue with -Default

@Badgerati
Copy link
Owner

The way -Default is working is as expected, the issue is caused by the way relative paths work in HTML.

The only way I can fix this is to add a switch parameter which tells Pode to redirect to /editor/index.html instead of rendering the index.html file as /editor.

@Badgerati
Copy link
Owner

I've added a -RedirectToDefault switch to Add-PodeStaticRoute, which will instead reirect to /editor/index.html instead of loading the index.html file in place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants