In our swagger.json we are setting basePath to /api, however, when the application is deployed in docker container, the context path is not /api. This could be different thing and we don't know what it is so we can't hard code it.
I am trying to set requestInterceptor as per the following guide, in order to catch the request and modify the url path perhaps:
https://swagger.io/docs/swagger-tools/#customization-36
But it seems requestInterceptor is being ignored. Is this possible? If not, how can I set the correct path at runtime?
This is my code in index.html
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
url: "../api-docs/swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
requestInterceptor: function(request) {
window.alert(request);
},
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
window.ui = ui
}
We are using Swagger 2.0
Upgrade to the latest version from here, or update your node package. I had the same problem because I downloaded the distribution before requestInterceptor support was added.
Related
I saw in the swagger ui documentation that you can provide a urls parameter which is:
An array of API definition objects ({url: "", name: ""}) used by Topbar plugin. When used and Topbar plugin is enabled, the url parameter will not be parsed. Names and URLs must be unique among all items in this array, since they're used as identifiers.
I was hoping that this will give me a selector from which I can chose which of my yaml files to process. Unfortunately, it doesn't seem to do anything.
Here is my code:
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
urls: [
{url:"http://test.dev/documentation/microservices/microservices.yaml",name:"All Microservices"},
{url:"http://test.dev/documentation/microservices/plans.yaml",name:"Plans"},
],
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
window.ui = ui
}
I'd also like to set the primaryName to All Microservices.
Any ideas on where I'm going wrong?
The urls configuration option is supported in Swagger UI 3.0.18 and later.
You can use it instead of url like this:
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
urls: [
{url: "https://path/to/api1.yaml", name: "API One"},
{url: "https://path/to/api2.yaml", name: "API Two"},
],
"urls.primaryName": "API Two" // default document (if other than the first)
...
})
Result:
I want to host Swagger UI as static content using Vert.x. The swagger-initializer.js needs the spec somewhere on the server and I want it to be in /api/swagger-ui as well, so I can define the spec in swagger-initializer.js as
window.onload = function() {
window.ui = SwaggerUIBundle({
url: "petstore.yaml",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
};
It works perfectly like this
Router.router(vertx).route("/api/swagger-ui/petstore.json").handler(StaticHandler.create("path/to/petstore.json"));
Router.router(vertx).route("/api/swagger-ui/*").handler(StaticHandler.create("path/to/swagger-ui"));
serving Swagger UI together with the provided spec.
But I wonder if there are any side effects by mixing a wildcard with an explicit route?
Are there any resources if this is good practice and it doesn't just work by coincidence?
It's fine, because by default routes are matched in the order they are added to the router.
When a request arrives, the router will step through each route and check if it matches, if it matches then the handler for that route will be called.
I'm trying to create SwaggerUIBundle where the urls will be of Azure Blob Storage container files.
For testing purpose I have hard coded the urls in here like this in my index.jsp file:
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
urls: [
{url: "https://backendsa.blob.core.windows.net/swagger-consolidation/*****", name: "SwaggerConsolidation"},
{url: "https://backendsa.blob.core.windows.net/swagger-consolidation/*****2", name: "SwaggerConsolidation2"},
],
dom_id: '#swagger-ui',
deepLinking: true,
spec: location.host,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
// End Swagger UI call region
These urls are pointing SAS urls for Azure Blob Storage files and are accessible while hitting in open network.
But while I deploy the code it gives below error :
Fetch error
NetworkError when attempting to fetch resource. https://backendsa.blob.core.windows.net/swagger-consolidation/*****
Fetch error
Possible cross-origin (CORS) issue? The URL origin (https://backendsa.blob.core.windows.net) does not match the page (https://router-sc.dev-wus.digitalservices.com). Check the server returns the correct 'Access-Control-Allow-*' headers.
Any insight over the issue would be helpful.
According to the error you provide, you need to configure CORS in Azure blob. Because the swaager UI application is a SPA application. when we call the rest api from a domain different from your website in the application, we will get CORS issue. Regarding how to configure it, please refer to the docuemnt.
For example
Allowed origins: *
Allowed verbs: DELETE,GET,HEAD,MERGE,POST,OPTIONS,PUT
Allowed headers: *
Exposed headers: *
Maximum age (seconds): 86400
Context
I'm using parcel-plugin-sw-precache which wraps around sw-precache to make it work with Parcel.js. Everything was working as expected, and I have been testing my offline app.
Problem
I added react-pdf.js into my project, one of the dependencies for this library doesn't get added into the service worker when it is generated by the sw-precache. I know this because the file "pdf.worker.entry.7ce4fb6a.js" gives a 304 error when I switch to offline mode.
What I have tried
I'm trying to add the file manually to the package.json parcel-plugin-sw-precache config using this code:
"sw-precache": {
"maximumFileSizeToCacheInBytes": 10485760,
"staticFileGlobs": [
"/pdf.worker.entry.7ce4fb6a.js"
]
},
I'm not sure if the file path should be relative to package.json or relative the generated service worker. In anycase, the manually specified file doesn't get added to generate services worker as I would expect. As seen below.
self.__precacheManifest = [{
"url": "index.html",
"revision": "ac5ace7a43a0fef7ae65fd3119987d1f"
}, {
"url": "castly.e31bb0bc.css",
"revision": "657409f7159cb857b9409c44a15e653f"
}, {
"url": "castly.e31bb0bc.js",
"revision": "018d4664d809ec19d167421b359823ad"
}, {
"url": "/",
"revision": "af5513bb330deae3098ab289d69a40c7"
}]
The question
If the sw-precache or parcel-plugin-sw-precache seem to be missing some files, how can I make sure they get added to the generated service worker?
In my exploration for an answer. I gave up on using parcel-plugin-sw-precache and instead I switched to using workbox. If you are interested in creating an offline app with Parcel.js. Then I recommend Workbox as it is the next generation of sw-precache.
There is how I got it working:
Learning
Learn what Workbox is and what is does with this code lab.
Implimenting
1) Install the Workbox CLI globally.
2) create a placeholding service worker in the root directory. e.g. sw_shell.js
- The shell is a holding file. The Workbox wizard will pick it up and generate a
new sw.js file automatically.
3) Add to the sw_config.js the following code:
importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.3/workbox-sw.js");
if (workbox) {
workbox.skipWaiting();
workbox.clientsClaim();
workbox.precaching.suppressWarnings();
// The next line came from the code lab
workbox.precaching.precacheAndRoute([]);
workbox.routing.registerNavigationRoute("/index.html");
} else {
console.log(`Boo! Workbox didn't load 😬`);
}
4) Run this code from a command line opened in your project's root directory.
workbox wizard --injectManifest
5) Follow the steps in the wizard. For dev purposes point the "root web app" to your parcel dist folder. Workbox does it's magic and picks up those files to be hashed into a new sw.js file.
6) The wizard will ask for your existing sw.js file. In my case I use the sw_shell.js.
a:Workbox picks up the sw_shell.js.
c:Generates as new sw.js file in a location specfied when running the wizard, and injects the files to run offline.
In my case I let the new sw.js generate in my root folder because Parcel picks it up automatically as per the script in my index.js.
'use strict';
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('sw.js').then(function(reg) {
console.log('Worker registration started')
reg.onupdatefound = function() {
console.log('update found')
var installingWorker = reg.installing;
installingWorker.onstatechange = function() {
console.log('installing worker')
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
console.log('New or updated content is available.');
} else {
console.log('Content is now available offline!');
}
break;
case 'redundant':
console.error('The installing service worker became redundant.');
break;
}
};
};
}).catch(function(e) {
console.error('Error during service worker registration:', e);
});
});
}
7) Add workbox injectManifest to your package.json to make sure Workbox picks up any changes to your files:
"scripts": {
"start": "parcel index.html workbox injectManifest"
}
Let me know if you want to know more about this. There is a video here that helped me a little bit also.
I'm using sw-precache in a jekyll website to add offline capabilities with the following configuration:
gulp.task('generate-service-worker', function(cb) {
var path = require('path');
var swPrecache = require('sw-precache');
var rootDir = '_site';
var packageJson = require('./package.json');
swPrecache.write('./service-worker.js', {
staticFileGlobs: [rootDir + '/**/*.{html,css,png,jpg,gif,svg}', rootDir + '/js/*'],
stripPrefix: rootDir + '/',
runtimeCaching: [{
urlPattern: /\/$/,
handler: 'networkOnly'
}],
handleFetch: argv.cacheAssets || false,
maximumFileSizeToCacheInBytes: 10485760, // 10 mb
cacheId: packageJson.name + '-v' + packageJson.version
}, cb);
});
The problem is that, when I change content in the website (for example, text in a blog post, or some text from the index page) the changes won't be shown until the new serviceworker version has been installed and the browser has been refreshed, which of course, is the expected behaviour of cacheFirst.
What I want is to make the request to the index of the site always network first, which is what I'm trying here:
runtimeCaching: [{
urlPattern: /\/$/,
handler: 'networkFirst'
}]
But this isn't working, the index is always getting fetch from the serviceworker and not from network, how can I accomplish this?
My problem is that I was including the actual page contents for precache: '/**/*.{html,css,png,jpg,gif,svg}'.
Excluding the html files works as expected:
'/**/*.{css,png,jpg,gif,svg}'
Change the url pattern to
urlPattern: "'/'"
This is a exact match pattern. Your index will match to this and nothing else.
The solution for this is, treat your index.html as dynamic content.
Change you sw webpack config to
new SWPrecacheWebpackPlugin({
cacheId: 'yourcacheid',
filename: 'service-worker.js',
staticFileGlobs: [
'dist/**/*.{js,css}'
],
minify: true,
stripPrefix: 'dist/',
runtimeCaching: [{
urlPattern: /\/$/,
handler: 'networkFirst'
}]
})
Remove your index.html from staticFileGlobs and add you root index to runtime caching.
Then look at your cache storage. You will see something like $$$toolbox-cache$$$https://your-domain.com as a new cache item. Inspect that and you can see your index cached there.