summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2022-09-29 20:16:30 +0000
committerGerrit Code Review <review@openstack.org>2022-09-29 20:16:30 +0000
commit8007ccb79794835e25c5943aa4e56b6e0124039b (patch)
tree74fb15e467f153b213f3daa5f5f851c4ce7391b4
parent591b0b5da855085f0ae229578c80df761041e87d (diff)
parent279547417fb406d0066c2f454ef93965f35a8754 (diff)
downloadzuul-8007ccb79794835e25c5943aa4e56b6e0124039b.tar.gz
Merge "Detect and handle auth proxy redirects"
-rw-r--r--web/src/api.js78
1 files changed, 56 insertions, 22 deletions
diff --git a/web/src/api.js b/web/src/api.js
index 1ba39998c..f9a3bd07d 100644
--- a/web/src/api.js
+++ b/web/src/api.js
@@ -103,93 +103,127 @@ function getStreamUrl(apiPrefix) {
return streamUrl
}
+function getWithCorsHandling(url) {
+ // This performs a simple GET and tries to detect if CORS errors are
+ // due to proxy authentication errors.
+ const instance = Axios.create({
+ baseURL: apiUrl
+ })
+ // First try the request as normal
+ let res = instance.get(url).catch(err => {
+ if (err.response === undefined) {
+ // This is either a Network, DNS, or CORS error, but we can't tell which.
+ // If we're behind an authz proxy, it's possible our creds have timed out
+ // and the CORS error is because we're getting a redirect.
+ // Apache mod_auth_mellon (and possibly other authz proxies) will avoid
+ // issuing a redirect if X-Requested-With is set to 'XMLHttpRequest' and
+ // will instead issue a 403. We can use this to detect that case.
+ instance.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
+ let res2 = instance.get(url).catch(err2 => {
+ if (err2.response && err2.response.status === 403) {
+ // We might be getting a redirect or something else,
+ // so reload the page.
+ console.log('Received 403 after unknown error; reloading')
+ window.location.reload()
+ }
+ // If we're still getting an error, we don't know the cause,
+ // it could be a transient network error, so we won't reload, we'll just
+ // wait for it to clear.
+ throw (err2)
+ })
+ return res2
+ }
+ })
+ return res
+}
+
// Direct APIs
function fetchInfo() {
- return Axios.get(apiUrl + 'info')
+ return getWithCorsHandling('info')
}
function fetchComponents() {
- return Axios.get(apiUrl + 'components')
+ return getWithCorsHandling('components')
}
function fetchTenantInfo(apiPrefix) {
- return Axios.get(apiUrl + apiPrefix + 'info')
+ return getWithCorsHandling(apiPrefix + 'info')
}
function fetchOpenApi() {
return Axios.get(getHomepageUrl() + 'openapi.yaml')
}
function fetchTenants() {
- return Axios.get(apiUrl + 'tenants')
+ return getWithCorsHandling(apiUrl + 'tenants')
}
function fetchConfigErrors(apiPrefix) {
- return Axios.get(apiUrl + apiPrefix + 'config-errors')
+ return getWithCorsHandling(apiPrefix + 'config-errors')
}
function fetchStatus(apiPrefix) {
- return Axios.get(apiUrl + apiPrefix + 'status')
+ return getWithCorsHandling(apiPrefix + 'status')
}
function fetchChangeStatus(apiPrefix, changeId) {
- return Axios.get(apiUrl + apiPrefix + 'status/change/' + changeId)
+ return getWithCorsHandling(apiPrefix + 'status/change/' + changeId)
}
function fetchFreezeJob(apiPrefix, pipelineName, projectName, branchName, jobName) {
- return Axios.get(apiUrl + apiPrefix +
+ return getWithCorsHandling(apiPrefix +
'pipeline/' + pipelineName +
'/project/' + projectName +
'/branch/' + branchName +
'/freeze-job/' + jobName)
}
function fetchBuild(apiPrefix, buildId) {
- return Axios.get(apiUrl + apiPrefix + 'build/' + buildId)
+ return getWithCorsHandling(apiPrefix + 'build/' + buildId)
}
function fetchBuilds(apiPrefix, queryString) {
let path = 'builds'
if (queryString) {
path += '?' + queryString.slice(1)
}
- return Axios.get(apiUrl + apiPrefix + path)
+ return getWithCorsHandling(apiPrefix + path)
}
function fetchBuildset(apiPrefix, buildsetId) {
- return Axios.get(apiUrl + apiPrefix + 'buildset/' + buildsetId)
+ return getWithCorsHandling(apiPrefix + 'buildset/' + buildsetId)
}
function fetchBuildsets(apiPrefix, queryString) {
let path = 'buildsets'
if (queryString) {
path += '?' + queryString.slice(1)
}
- return Axios.get(apiUrl + apiPrefix + path)
+ return getWithCorsHandling(apiPrefix + path)
}
function fetchPipelines(apiPrefix) {
- return Axios.get(apiUrl + apiPrefix + 'pipelines')
+ return getWithCorsHandling(apiPrefix + 'pipelines')
}
function fetchProject(apiPrefix, projectName) {
- return Axios.get(apiUrl + apiPrefix + 'project/' + projectName)
+ return getWithCorsHandling(apiPrefix + 'project/' + projectName)
}
function fetchProjects(apiPrefix) {
- return Axios.get(apiUrl + apiPrefix + 'projects')
+ return getWithCorsHandling(apiPrefix + 'projects')
}
function fetchJob(apiPrefix, jobName) {
- return Axios.get(apiUrl + apiPrefix + 'job/' + jobName)
+ return getWithCorsHandling(apiPrefix + 'job/' + jobName)
}
function fetchJobGraph(apiPrefix, projectName, pipelineName, branchName) {
- return Axios.get(apiUrl + apiPrefix +
+ return getWithCorsHandling(apiPrefix +
'pipeline/' + pipelineName +
'/project/' + projectName +
'/branch/' + branchName +
'/freeze-jobs')
}
function fetchJobs(apiPrefix) {
- return Axios.get(apiUrl + apiPrefix + 'jobs')
+ return getWithCorsHandling(apiPrefix + 'jobs')
}
function fetchLabels(apiPrefix) {
- return Axios.get(apiUrl + apiPrefix + 'labels')
+ return getWithCorsHandling(apiPrefix + 'labels')
}
function fetchNodes(apiPrefix) {
- return Axios.get(apiUrl + apiPrefix + 'nodes')
+ return getWithCorsHandling(apiPrefix + 'nodes')
}
function fetchAutoholds(apiPrefix) {
- return Axios.get(apiUrl + apiPrefix + 'autohold')
+ return getWithCorsHandling(apiPrefix + 'autohold')
}
function fetchAutohold(apiPrefix, requestId) {
- return Axios.get(apiUrl + apiPrefix + 'autohold/' + requestId)
+ return getWithCorsHandling(apiPrefix + 'autohold/' + requestId)
}
// token-protected API