swagger-api / swagger-ui

Swagger UI is a collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.
https://swagger.io
Apache License 2.0
26.34k stars 8.92k forks source link

Suggestion: Show better error when URL fails due to mixed content #3426

Closed scottohara closed 6 years ago

scottohara commented 7 years ago

When a URL fails to load, the message to the user is simply:

Failed to load spec

As we know, there are a couple of very common reasons why a URL might fail to load:

  1. If the page hosting swagger-ui is https://, but the URL being loaded is http://, most browsers will block the fetch and report the following console error:

The page at 'https://example.com' was loaded over HTTPS, but requested an insecure resource 'http://petstore.swagger.io/v2/swagger.yaml'. This request has been blocked; the content must be served over HTTPS.

  1. If the server hosting the URL doesn't respond with the correct CORS headers

The error messages for both of these common failure cases are buried in the browser console.

Surfacing more information to the user should reduce the number of issues and support requests from users struggling to get their URLs to load.

Unfortunately, for the CORS issue, there's no way (that I'm aware of) to easily detect this in Javascript (the error that Chrome throws is just TypeError: Failed to fetch).

However the mixed content issue can be easily detected, with something like this (in download-url.js):

function next(res) {
  if(res instance Error || res.status >= 400) {
    if (isMixedContent(url)) {
        specActions.updateLoadingStatus("failedMixedContent")
    } else {
        specActions.updateLoadingStatus("failed")
    }

    return errActions.newThrownErr( new Error(res.statusText + " " + url) )
  }

  …
}

// Checks for mixed content errors
const isMixedContent = (url) => {

    // Parse the protocol from the URL
    if ('URL' in window) {
        const urlProtocol = new URL(url).protocol
    } else {
        // legacy browser, use <a href> to parse the URL
        const parser = document.createElement('a')
        parser.href = url
        const urlProtocol = parser.protocol
    }

    // Compare the page protocol and URL protocol
    if (window.location.protocol === "https" && urlProtocol === "http") {
        return true
    }

    return false
}

...and then show a more detailed error message in the layout:

{ loadingStatus === "failedMixedContent" &&
  <div className="info">
    <h4 className="title">Failed to load http:// URL because page is https://</h4>
  </div>
}

Thoughts?

lock[bot] commented 5 years ago

Locking due to inactivity.

This is done to avoid resurrecting old issues and bumping long threads with new, possibly unrelated content.

If you think you're experiencing something similar to what you've found here: please open a new issue, follow the template, and reference this issue in your report.

Thanks!