diff --git a/src/pages/ca-certificates/List.vue b/src/pages/ca-certificates/List.vue
index a4ad8bba..0c8adf31 100644
--- a/src/pages/ca-certificates/List.vue
+++ b/src/pages/ca-certificates/List.vue
@@ -57,6 +57,7 @@ const getEditRoute = (id: string) => ({
const caCertificateListConfig = reactive({
...useListGeneralConfig(),
+ isExactMatch: true,
createRoute,
getViewRoute,
getEditRoute,
diff --git a/src/pages/certificates/List.vue b/src/pages/certificates/List.vue
index a4b00d8f..166b20e6 100644
--- a/src/pages/certificates/List.vue
+++ b/src/pages/certificates/List.vue
@@ -57,6 +57,7 @@ const getEditRoute = (id: string) => ({
const certificateListConfig = reactive({
...useListGeneralConfig(),
+ isExactMatch: true,
createRoute,
getViewRoute,
getEditRoute,
diff --git a/src/pages/overview/Overview.vue b/src/pages/overview/Overview.vue
index 20bcd0ba..b201798d 100644
--- a/src/pages/overview/Overview.vue
+++ b/src/pages/overview/Overview.vue
@@ -15,7 +15,7 @@
{{ item.value }}
diff --git a/src/pages/plugins/Form.vue b/src/pages/plugins/Form.vue
index 1ac44f74..09f4195b 100644
--- a/src/pages/plugins/Form.vue
+++ b/src/pages/plugins/Form.vue
@@ -191,6 +191,27 @@ export default {
},
tags: typedefs.tags,
+
+ protocols: {
+ default: [],
+ type: 'multiselect',
+ label: 'Protocols',
+ values: [
+ { label: 'grpc', value: 'grpc' },
+ { label: 'grpcs', value: 'grpcs' },
+ { label: 'http', value: 'http' },
+ { label: 'https', value: 'https' },
+ { label: 'tcp', value: 'tcp' },
+ { label: 'tls', value: 'tls' },
+ { label: 'tls_passthrough', value: 'tls_passthrough' },
+ { label: 'udp', value: 'udp' },
+ { label: 'ws', value: 'ws' },
+ { label: 'wss', value: 'wss' },
+ ],
+ help: 'A list of the request protocols that will trigger this plugin. The default value, as well as the possible values allowed on this field, may change depending on the plugin type.',
+ placeholder: 'Select valid protocols for the plugin',
+ styleClasses: 'plugin-protocols-select',
+ },
},
customSchemas: {
@@ -400,6 +421,16 @@ export default {
const configResponse = configField ? configField.config : response
+ const protocolsField = response.fields.find(field => field.protocols)?.protocols
+ if (protocolsField) {
+ const { default: defaultValues = [], elements = {} } = protocolsField
+
+ this.defaultFormSchema.protocols.default = defaultValues
+ if (elements.one_of?.length) {
+ this.defaultFormSchema.protocols.values = elements.one_of.map(value => ({ label: value, value }))
+ }
+ }
+
this.schema = this.buildFormSchema('config', configResponse, this.defaultFormSchema)
}).catch(err => {
this.error = err
diff --git a/tests/playwright/specs/plugins/01-Plugins.spec.ts b/tests/playwright/specs/plugins/01-Plugins.spec.ts
index a8a65a95..20de9732 100644
--- a/tests/playwright/specs/plugins/01-Plugins.spec.ts
+++ b/tests/playwright/specs/plugins/01-Plugins.spec.ts
@@ -287,6 +287,35 @@ test.describe('plugins', () => {
await expect(getPropertyValue(page, 'name')).toContainText(new RegExp(mockPluginName, 'i'))
})
+ test('plugin protocols', async ({ page }) => {
+ await clearKongResources('/plugins')
+ await withNavigation(
+ page,
+ async () => await page.locator('.empty-state-content .primary').click()
+ )
+ await withNavigation(
+ page,
+ async () => await page.click('a.plugin-card[title="Basic Authentication"]')
+ )
+
+ await page.click('.plugin-protocols-select .k-multiselect-trigger')
+ await page.click('.k-multiselect-item[data-testid="k-multiselect-item-grpcs"]')
+ await page.click('.k-multiselect-item[data-testid="k-multiselect-item-https"]')
+ await page.click('.k-multiselect-item[data-testid="k-multiselect-item-wss"]')
+ await page.click('.plugin-protocols-select .k-multiselect-trigger')
+
+ await withNavigation(
+ page,
+ async () => await page.locator('.plugin-form .primary').click()
+ )
+ await withNavigation(page, async () => await clickEntityListAction(page, 'view'))
+
+ await expect(page.getByTestId('protocols-property-value')).toContainText('http')
+ await expect(page.getByTestId('protocols-property-value')).toContainText('grpc')
+ await expect(page.getByTestId('protocols-property-value')).toContainText('ws')
+ await expect(page.getByTestId('protocols-property-value').locator('.config-badge')).toHaveCount(3)
+ })
+
test('submit/cancel plugin editing using footer actions', async ({ page }) => {
await withNavigation(page, async () => await clickEntityListAction(page, 'edit'))
await withNavigation(