diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/README.md b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/README.md index 80315040c9..b76ae19f26 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/README.md +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/README.md @@ -4,10 +4,4 @@ This module contains articles about Spring Cloud Gateway ### Relevant Articles: -- [Exploring the New Spring Cloud Gateway](http://www.baeldung.com/spring-cloud-gateway) -- [Writing Custom Spring Cloud Gateway Filters](https://www.baeldung.com/spring-cloud-custom-gateway-filters) -- [Spring Cloud Gateway Routing Predicate Factories](https://www.baeldung.com/spring-cloud-gateway-routing-predicate-factories) -- [Spring Cloud Gateway WebFilter Factories](https://www.baeldung.com/spring-cloud-gateway-webfilter-factories) -- [Using Spring Cloud Gateway with OAuth 2.0 Patterns](https://www.baeldung.com/spring-cloud-gateway-oauth2) -- [URL Rewriting With Spring Cloud Gateway](https://www.baeldung.com/spring-cloud-gateway-url-rewriting) -- [Processing the Response Body in Spring Cloud Gateway](https://www.baeldung.com/spring-cloud-gateway-response-body) +- [Exploring the New Spring Cloud Gateway](http://www.baeldung.com/spring-cloud-gateway) \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/baeldung-realm.json b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/baeldung-realm.json deleted file mode 100644 index 4dad262568..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/baeldung-realm.json +++ /dev/null @@ -1,2186 +0,0 @@ -{ - "id": "baeldung", - "realm": "baeldung", - "notBefore": 0, - "revokeRefreshToken": false, - "refreshTokenMaxReuse": 0, - "accessTokenLifespan": 300, - "accessTokenLifespanForImplicitFlow": 900, - "ssoSessionIdleTimeout": 1800, - "ssoSessionMaxLifespan": 36000, - "ssoSessionIdleTimeoutRememberMe": 0, - "ssoSessionMaxLifespanRememberMe": 0, - "offlineSessionIdleTimeout": 2592000, - "offlineSessionMaxLifespanEnabled": false, - "offlineSessionMaxLifespan": 5184000, - "clientSessionIdleTimeout": 0, - "clientSessionMaxLifespan": 0, - "clientOfflineSessionIdleTimeout": 0, - "clientOfflineSessionMaxLifespan": 0, - "accessCodeLifespan": 60, - "accessCodeLifespanUserAction": 300, - "accessCodeLifespanLogin": 1800, - "actionTokenGeneratedByAdminLifespan": 43200, - "actionTokenGeneratedByUserLifespan": 300, - "enabled": true, - "sslRequired": "external", - "registrationAllowed": false, - "registrationEmailAsUsername": false, - "rememberMe": false, - "verifyEmail": false, - "loginWithEmailAllowed": true, - "duplicateEmailsAllowed": false, - "resetPasswordAllowed": false, - "editUsernameAllowed": false, - "bruteForceProtected": false, - "permanentLockout": false, - "maxFailureWaitSeconds": 900, - "minimumQuickLoginWaitSeconds": 60, - "waitIncrementSeconds": 60, - "quickLoginCheckMilliSeconds": 1000, - "maxDeltaTimeSeconds": 43200, - "failureFactor": 30, - "roles": { - "realm": [ - { - "id": "2f721e46-398b-43ff-845f-3c747f1f69f5", - "name": "standard", - "description": "Standard customer", - "composite": false, - "clientRole": false, - "containerId": "baeldung", - "attributes": {} - }, - { - "id": "b8b1cb49-c953-4cb0-acea-62b24c4b6d30", - "name": "silver", - "description": "Silver customer", - "composite": false, - "clientRole": false, - "containerId": "baeldung", - "attributes": {} - }, - { - "id": "f44f5ba9-2393-4d2a-b581-81cf8dd7f245", - "name": "gold", - "description": "Gold customers", - "composite": false, - "clientRole": false, - "containerId": "baeldung", - "attributes": {} - }, - { - "id": "3b6109f5-6e5a-4578-83c3-791ec3e2bf9e", - "name": "offline_access", - "description": "${role_offline-access}", - "composite": false, - "clientRole": false, - "containerId": "baeldung", - "attributes": {} - }, - { - "id": "0dd6a8c7-d669-4941-9ea1-521980e9c53f", - "name": "uma_authorization", - "description": "${role_uma_authorization}", - "composite": false, - "clientRole": false, - "containerId": "baeldung", - "attributes": {} - }, - { - "id": "ca962095-7f9b-49e2-a190-e391a0d4b704", - "name": "user", - "composite": false, - "clientRole": false, - "containerId": "baeldung", - "attributes": {} - } - ], - "client": { - "newClient": [], - "realm-management": [ - { - "id": "5d00243f-ceec-4b0c-995e-d86d5b8a0ae6", - "name": "view-clients", - "description": "${role_view-clients}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "query-clients" - ] - } - }, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "941612de-bd85-47a5-8dfa-37c270dde28c", - "name": "view-authorization", - "description": "${role_view-authorization}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "5ea9810d-63cc-4277-9b32-ba8a3d3c6091", - "name": "manage-realm", - "description": "${role_manage-realm}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "8b7b0dd8-350b-473e-b8cd-8acad34f1358", - "name": "query-clients", - "description": "${role_query-clients}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "0f8e5ee8-b014-4b7c-9b69-50f46abcba5f", - "name": "query-groups", - "description": "${role_query-groups}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "911b1489-9383-4734-b134-bf49bf992ce9", - "name": "manage-clients", - "description": "${role_manage-clients}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "5d48274c-bd6b-4c26-ad54-f1a2254beac0", - "name": "view-realm", - "description": "${role_view-realm}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "3ea43b64-316f-4693-8346-9ee78b24adaf", - "name": "manage-identity-providers", - "description": "${role_manage-identity-providers}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "49735614-96ec-49b2-98fe-3af9bcd1a33a", - "name": "create-client", - "description": "${role_create-client}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "e8f8c3cc-0ff1-4f72-a271-db6821a3cdb6", - "name": "manage-users", - "description": "${role_manage-users}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "387418b1-4f80-4b00-b9dd-805ca041f805", - "name": "view-identity-providers", - "description": "${role_view-identity-providers}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "427c27d4-521a-464b-a0df-16d7f537e8d5", - "name": "realm-admin", - "description": "${role_realm-admin}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "view-clients", - "view-authorization", - "query-groups", - "manage-realm", - "query-clients", - "manage-clients", - "view-realm", - "manage-identity-providers", - "create-client", - "manage-users", - "view-identity-providers", - "query-users", - "query-realms", - "view-users", - "impersonation", - "manage-authorization", - "manage-events", - "view-events" - ] - } - }, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "a574cf01-03e4-4573-ab9e-276d13a1ce8d", - "name": "query-users", - "description": "${role_query-users}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "c3a253a8-a1b6-4d38-9677-f728f32482ad", - "name": "query-realms", - "description": "${role_query-realms}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "f3cb93da-273e-419a-b2f4-93f09896abcf", - "name": "view-users", - "description": "${role_view-users}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "query-users", - "query-groups" - ] - } - }, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "6eedf2b7-50ef-4495-a89b-54aef751b7fa", - "name": "manage-authorization", - "description": "${role_manage-authorization}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "0332e99b-3dfc-4193-9e13-5728f8f3e6d6", - "name": "impersonation", - "description": "${role_impersonation}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "b690cb9c-0f4a-4be5-ade0-b40443d8149d", - "name": "view-events", - "description": "${role_view-events}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - }, - { - "id": "aac3def5-f193-4a6c-9065-1667a0746a8a", - "name": "manage-events", - "description": "${role_manage-events}", - "composite": false, - "clientRole": true, - "containerId": "6a4bfbd0-576d-4778-af56-56f876647355", - "attributes": {} - } - ], - "security-admin-console": [], - "quotes-client": [], - "admin-cli": [], - "account-console": [], - "broker": [ - { - "id": "397b5703-4c81-48fd-a24c-a7e8177ef657", - "name": "read-token", - "description": "${role_read-token}", - "composite": false, - "clientRole": true, - "containerId": "4b9609f0-48d1-4e71-9381-2ecec08616f9", - "attributes": {} - } - ], - "account": [ - { - "id": "8daa8096-d14e-4d1c-ad1f-83f822016aa1", - "name": "manage-account", - "description": "${role_manage-account}", - "composite": true, - "composites": { - "client": { - "account": [ - "manage-account-links" - ] - } - }, - "clientRole": true, - "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", - "attributes": {} - }, - { - "id": "15f0d8be-932b-4565-8ad0-e8aa170093dd", - "name": "view-consent", - "description": "${role_view-consent}", - "composite": false, - "clientRole": true, - "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", - "attributes": {} - }, - { - "id": "c5aa697c-bf87-47c6-bd94-9121b72420b9", - "name": "view-applications", - "description": "${role_view-applications}", - "composite": false, - "clientRole": true, - "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", - "attributes": {} - }, - { - "id": "f0b3bbe4-aec1-4227-b9d3-2c314d612a04", - "name": "manage-consent", - "description": "${role_manage-consent}", - "composite": true, - "composites": { - "client": { - "account": [ - "view-consent" - ] - } - }, - "clientRole": true, - "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", - "attributes": {} - }, - { - "id": "948269c7-a69c-4c82-a7f3-88868713dfd9", - "name": "manage-account-links", - "description": "${role_manage-account-links}", - "composite": false, - "clientRole": true, - "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", - "attributes": {} - }, - { - "id": "aed18201-2433-4998-8fa3-0979b0b31c10", - "name": "view-profile", - "description": "${role_view-profile}", - "composite": false, - "clientRole": true, - "containerId": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", - "attributes": {} - } - ] - } - }, - "groups": [ - { - "id": "635c3314-f15f-4c02-bcb7-8739fd4c21b7", - "name": "golden_customers", - "path": "/golden_customers", - "attributes": {}, - "realmRoles": [ - "gold" - ], - "clientRoles": {}, - "subGroups": [] - }, - { - "id": "279c5ec4-0588-4884-91c1-2697ed5c9826", - "name": "silver_customers", - "path": "/silver_customers", - "attributes": {}, - "realmRoles": [ - "silver" - ], - "clientRoles": {}, - "subGroups": [] - } - ], - "defaultRoles": [ - "uma_authorization", - "offline_access" - ], - "requiredCredentials": [ - "password" - ], - "otpPolicyType": "totp", - "otpPolicyAlgorithm": "HmacSHA1", - "otpPolicyInitialCounter": 0, - "otpPolicyDigits": 6, - "otpPolicyLookAheadWindow": 1, - "otpPolicyPeriod": 30, - "otpSupportedApplications": [ - "FreeOTP", - "Google Authenticator" - ], - "webAuthnPolicyRpEntityName": "keycloak", - "webAuthnPolicySignatureAlgorithms": [ - "ES256" - ], - "webAuthnPolicyRpId": "", - "webAuthnPolicyAttestationConveyancePreference": "not specified", - "webAuthnPolicyAuthenticatorAttachment": "not specified", - "webAuthnPolicyRequireResidentKey": "not specified", - "webAuthnPolicyUserVerificationRequirement": "not specified", - "webAuthnPolicyCreateTimeout": 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyAcceptableAaguids": [], - "webAuthnPolicyPasswordlessRpEntityName": "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms": [ - "ES256" - ], - "webAuthnPolicyPasswordlessRpId": "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", - "webAuthnPolicyPasswordlessCreateTimeout": 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyPasswordlessAcceptableAaguids": [], - "scopeMappings": [ - { - "clientScope": "offline_access", - "roles": [ - "offline_access" - ] - } - ], - "clientScopeMappings": { - "account": [ - { - "client": "account-console", - "roles": [ - "manage-account" - ] - } - ] - }, - "clients": [ - { - "id": "12eebf0b-a3eb-49f8-9ecf-173cf8a00145", - "clientId": "account", - "name": "${client_account}", - "rootUrl": "${authBaseUrl}", - "baseUrl": "/realms/baeldung/account/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "**********", - "defaultRoles": [ - "manage-account", - "view-profile" - ], - "redirectUris": [ - "/realms/baeldung/account/*" - ], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": {}, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "role_list", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "8209784b-8540-43c2-aece-241acf12ea5a", - "clientId": "account-console", - "name": "${client_account-console}", - "rootUrl": "${authBaseUrl}", - "baseUrl": "/realms/baeldung/account/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "**********", - "redirectUris": [ - "/realms/baeldung/account/*" - ], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "pkce.code.challenge.method": "S256" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "protocolMappers": [ - { - "id": "58395b96-1718-4787-8f92-74577e2bfc30", - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": {} - } - ], - "defaultClientScopes": [ - "web-origins", - "role_list", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "13d76feb-d762-4409-bb84-7a75bc395a61", - "clientId": "admin-cli", - "name": "${client_admin-cli}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "**********", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": {}, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "role_list", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "4b9609f0-48d1-4e71-9381-2ecec08616f9", - "clientId": "broker", - "name": "${client_broker}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "**********", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": {}, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "role_list", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "b88ce206-63d6-43b6-87c9-ea09d8c02f32", - "clientId": "newClient", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "**********", - "redirectUris": [ - "http://localhost:8082/new-client/login/oauth2/code/custom", - "http://localhost:8089/", - "http://localhost:8089/auth/redirect/" - ], - "webOrigins": [ - "+" - ], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": true, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "saml.assertion.signature": "false", - "saml.force.post.binding": "false", - "saml.multivalued.roles": "false", - "saml.encrypt": "false", - "saml.server.signature": "false", - "saml.server.signature.keyinfo.ext": "false", - "exclude.session.state.from.auth.response": "false", - "saml_force_name_id_format": "false", - "saml.client.signature": "false", - "tls.client.certificate.bound.access.tokens": "false", - "saml.authnstatement": "false", - "display.on.consent.screen": "false", - "saml.onetimeuse.condition": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": true, - "nodeReRegistrationTimeout": -1, - "defaultClientScopes": [ - "role_list", - "profile" - ], - "optionalClientScopes": [ - "web-origins", - "address", - "read", - "phone", - "roles", - "offline_access", - "microprofile-jwt", - "write", - "email" - ] - }, - { - "id": "5898f71f-b91e-4c3f-9c86-48de0e8665c4", - "clientId": "quotes-client", - "name": "Quotes Client", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "0e082231-a70d-48e8-b8a5-fbfb743041b6", - "redirectUris": [ - "http://localhost:8082/*", - "http://localhost:8087/*" - ], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "saml.assertion.signature": "false", - "saml.multivalued.roles": "false", - "saml.force.post.binding": "false", - "saml.encrypt": "false", - "saml.server.signature": "false", - "saml.server.signature.keyinfo.ext": "false", - "exclude.session.state.from.auth.response": "false", - "saml_force_name_id_format": "false", - "saml.client.signature": "false", - "tls.client.certificate.bound.access.tokens": "false", - "saml.authnstatement": "false", - "display.on.consent.screen": "false", - "saml.onetimeuse.condition": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": true, - "nodeReRegistrationTimeout": -1, - "protocolMappers": [ - { - "id": "008d32b5-ea7b-4739-89af-e90fe137bda9", - "name": "realm roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "realm_access.roles", - "jsonType.label": "String", - "multivalued": "true" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "role_list", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "6a4bfbd0-576d-4778-af56-56f876647355", - "clientId": "realm-management", - "name": "${client_realm-management}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "**********", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": true, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": {}, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "role_list", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "8e358d2f-b085-4243-8e6e-c175431e5eeb", - "clientId": "security-admin-console", - "name": "${client_security-admin-console}", - "rootUrl": "${authAdminUrl}", - "baseUrl": "/admin/baeldung/console/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "**********", - "redirectUris": [ - "/admin/baeldung/console/*" - ], - "webOrigins": [ - "+" - ], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "pkce.code.challenge.method": "S256" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "protocolMappers": [ - { - "id": "9cfca9ee-493d-4b5e-8170-2d364149de59", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "role_list", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - } - ], - "clientScopes": [ - { - "id": "77c7e29d-1a22-4419-bbfb-4a62bb033449", - "name": "address", - "description": "OpenID Connect built-in scope: address", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${addressScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "94e1879d-b49e-4178-96e0-bf8d7f32c160", - "name": "address", - "protocol": "openid-connect", - "protocolMapper": "oidc-address-mapper", - "consentRequired": false, - "config": { - "user.attribute.formatted": "formatted", - "user.attribute.country": "country", - "user.attribute.postal_code": "postal_code", - "userinfo.token.claim": "true", - "user.attribute.street": "street", - "id.token.claim": "true", - "user.attribute.region": "region", - "access.token.claim": "true", - "user.attribute.locality": "locality" - } - } - ] - }, - { - "id": "b3526ac1-10e2-4344-8621-9c5a0853e97a", - "name": "email", - "description": "OpenID Connect built-in scope: email", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${emailScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "d30270dc-baa6-455a-8ff6-ddccf8a78d86", - "name": "email verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "emailVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email_verified", - "jsonType.label": "boolean" - } - }, - { - "id": "f5b1684d-e479-4134-8578-457fa64717da", - "name": "email", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "email", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "c658ae14-e96a-4745-b21b-2ed5c4c63f5f", - "name": "microprofile-jwt", - "description": "Microprofile - JWT built-in scope", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "959521bc-5ffd-465b-95f2-5b0c20d1909c", - "name": "upn", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "upn", - "jsonType.label": "String" - } - }, - { - "id": "07b8550c-b298-4cce-9ffb-900182575b76", - "name": "groups", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "multivalued": "true", - "userinfo.token.claim": "true", - "user.attribute": "foo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "groups", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "569b3d44-4ecd-4768-a58c-70ff38f4b4fe", - "name": "offline_access", - "description": "OpenID Connect built-in scope: offline_access", - "protocol": "openid-connect", - "attributes": { - "consent.screen.text": "${offlineAccessScopeConsentText}", - "display.on.consent.screen": "true" - } - }, - { - "id": "a3e7b19d-df6c-437e-9eea-06fec1becb2f", - "name": "phone", - "description": "OpenID Connect built-in scope: phone", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${phoneScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "72a070f7-4363-4c88-8153-6fd2d12b9b04", - "name": "phone number verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "phoneNumberVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number_verified", - "jsonType.label": "boolean" - } - }, - { - "id": "24b42c6d-a93c-4aa1-9a03-2a2b55954c13", - "name": "phone number", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "phoneNumber", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "ba8c9950-fd0b-4434-8be6-b58456d7b6d4", - "name": "profile", - "description": "OpenID Connect built-in scope: profile", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${profileScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "0a9ddd71-309c-40f0-8ea6-a0791070c6ed", - "name": "profile", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "profile", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "profile", - "jsonType.label": "String" - } - }, - { - "id": "fbf53bbd-1ad0-4bf8-8030-50f81696d8ee", - "name": "nickname", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "nickname", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "nickname", - "jsonType.label": "String" - } - }, - { - "id": "423be2cd-42c0-462e-9030-18f9b28ff2d3", - "name": "gender", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "gender", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "gender", - "jsonType.label": "String" - } - }, - { - "id": "53eb9006-4b81-474a-8b60-80f775d54b63", - "name": "picture", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "picture", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "picture", - "jsonType.label": "String" - } - }, - { - "id": "4d8bc82a-eaeb-499e-8eb2-0f1dcbe91699", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - }, - { - "id": "d3b25485-4042-419d-afff-cfd63a76e229", - "name": "full name", - "protocol": "openid-connect", - "protocolMapper": "oidc-full-name-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "access.token.claim": "true", - "userinfo.token.claim": "true" - } - }, - { - "id": "422cfa5a-f2f4-4f36-82df-91b47ae1ea50", - "name": "given name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "firstName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "given_name", - "jsonType.label": "String" - } - }, - { - "id": "3f2863c1-d98d-45b5-b08f-af9c4d9c10f8", - "name": "website", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "website", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "website", - "jsonType.label": "String" - } - }, - { - "id": "c98c063d-eee4-41a0-9130-595afd709d1f", - "name": "middle name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "middleName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "middle_name", - "jsonType.label": "String" - } - }, - { - "id": "8dbed80a-d672-4185-8dda-4bba2a56ec83", - "name": "family name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "lastName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "family_name", - "jsonType.label": "String" - } - }, - { - "id": "5e5c690c-93cf-489d-a054-b109eab8911b", - "name": "updated at", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "updatedAt", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "updated_at", - "jsonType.label": "String" - } - }, - { - "id": "3b985202-af8a-42f1-ac5f-0966a404f5d7", - "name": "birthdate", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "birthdate", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "birthdate", - "jsonType.label": "String" - } - }, - { - "id": "6eafd1b3-7121-4919-ad1e-039fa58acc32", - "name": "username", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "preferred_username", - "jsonType.label": "String" - } - }, - { - "id": "73cba925-8c31-443f-9601-b1514e6396c1", - "name": "zoneinfo", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "zoneinfo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "zoneinfo", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "c1a2eb23-25c6-4be7-a791-bbdca99c83f7", - "name": "read", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true" - } - }, - { - "id": "18e141bf-dabe-4858-879c-dbc439cdead4", - "name": "role_list", - "description": "SAML role list", - "protocol": "saml", - "attributes": { - "consent.screen.text": "${samlRoleListScopeConsentText}", - "display.on.consent.screen": "true" - }, - "protocolMappers": [ - { - "id": "10cbe37f-0198-4d65-bc8a-bfe5ad8145d1", - "name": "role list", - "protocol": "saml", - "protocolMapper": "saml-role-list-mapper", - "consentRequired": false, - "config": { - "single": "false", - "attribute.nameformat": "Basic", - "attribute.name": "Role" - } - } - ] - }, - { - "id": "111ed87a-5fd3-4cee-96df-8dbfb88cfdc0", - "name": "roles", - "description": "OpenID Connect scope for add user roles to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "true", - "consent.screen.text": "${rolesScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "24924d8d-6071-4a93-b40f-326176cb335e", - "name": "realm roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "realm_access.roles", - "jsonType.label": "String", - "multivalued": "true" - } - }, - { - "id": "2f6a9bdf-3758-484c-996d-e4f93555559f", - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": {} - }, - { - "id": "804d4798-d9a3-4fd3-8b28-d12142e8cb3d", - "name": "client roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "resource_access.${client_id}.roles", - "jsonType.label": "String", - "multivalued": "true" - } - } - ] - }, - { - "id": "51d49314-b511-43e0-9258-bfb873758a78", - "name": "web-origins", - "description": "OpenID Connect scope for add allowed web origins to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false", - "consent.screen.text": "" - }, - "protocolMappers": [ - { - "id": "2b384cd0-9e85-4a87-8eeb-2b480b0587b7", - "name": "allowed web origins", - "protocol": "openid-connect", - "protocolMapper": "oidc-allowed-origins-mapper", - "consentRequired": false, - "config": {} - } - ] - }, - { - "id": "c3e253fb-7361-47cf-9d4a-86245686fdf1", - "name": "write", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true" - } - } - ], - "defaultDefaultClientScopes": [ - "roles", - "role_list", - "web-origins", - "email", - "profile" - ], - "defaultOptionalClientScopes": [ - "offline_access", - "address", - "phone", - "microprofile-jwt" - ], - "browserSecurityHeaders": { - "contentSecurityPolicyReportOnly": "", - "xContentTypeOptions": "nosniff", - "xRobotsTag": "none", - "xFrameOptions": "SAMEORIGIN", - "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection": "1; mode=block", - "strictTransportSecurity": "max-age=31536000; includeSubDomains" - }, - "smtpServer": {}, - "eventsEnabled": false, - "eventsListeners": [ - "jboss-logging" - ], - "enabledEventTypes": [], - "adminEventsEnabled": false, - "adminEventsDetailsEnabled": false, - "components": { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ - { - "id": "84305f42-4b6d-4b0a-ac7c-53e406e3ac63", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allow-default-scopes": [ - "true" - ] - } - }, - { - "id": "c7c38a95-744f-4558-a403-9cf692fe1944", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allow-default-scopes": [ - "true" - ] - } - }, - { - "id": "365b2899-befe-4417-b89b-562650ec4446", - "name": "Full Scope Disabled", - "providerId": "scope", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "81c32244-7921-43e9-9356-a3469259b78c", - "name": "Trusted Hosts", - "providerId": "trusted-hosts", - "subType": "anonymous", - "subComponents": {}, - "config": { - "host-sending-registration-request-must-match": [ - "true" - ], - "client-uris-must-match": [ - "true" - ] - } - }, - { - "id": "d09b2147-afea-4f7f-a49c-0aec7eee10de", - "name": "Max Clients Limit", - "providerId": "max-clients", - "subType": "anonymous", - "subComponents": {}, - "config": { - "max-clients": [ - "200" - ] - } - }, - { - "id": "41ffde1b-72a2-416f-87a7-94989e940dc0", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "saml-user-property-mapper", - "oidc-address-mapper", - "oidc-usermodel-property-mapper", - "oidc-full-name-mapper", - "oidc-sha256-pairwise-sub-mapper", - "saml-role-list-mapper", - "oidc-usermodel-attribute-mapper", - "saml-user-attribute-mapper" - ] - } - }, - { - "id": "76075388-2782-4656-a986-313493239a9f", - "name": "Consent Required", - "providerId": "consent-required", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "3caaf57a-9cd7-48c1-b709-b40b887414f7", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "oidc-usermodel-attribute-mapper", - "saml-user-property-mapper", - "oidc-usermodel-property-mapper", - "oidc-full-name-mapper", - "saml-user-attribute-mapper", - "oidc-address-mapper", - "saml-role-list-mapper", - "oidc-sha256-pairwise-sub-mapper" - ] - } - } - ], - "org.keycloak.keys.KeyProvider": [ - { - "id": "d67a940a-52e4-44a5-9f69-6ffdd67a188f", - "name": "rsa-generated", - "providerId": "rsa-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ] - } - }, - { - "id": "48d40de3-6234-42e8-9449-f68f56abb54b", - "name": "aes-generated", - "providerId": "aes-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ] - } - }, - { - "id": "52ea1c5d-2a30-459f-b66a-249f298b32f8", - "name": "hmac-generated", - "providerId": "hmac-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ], - "algorithm": [ - "HS256" - ] - } - } - ] - }, - "internationalizationEnabled": false, - "supportedLocales": [], - "authenticationFlows": [ - { - "id": "b35b726e-c1cc-4a31-8670-8c858c088498", - "alias": "Handle Existing Account", - "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-confirm-link", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "requirement": "REQUIRED", - "priority": 20, - "flowAlias": "Handle Existing Account - Alternatives - 0", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "id": "b7cb4b8c-0064-4c6b-95ee-d7f50011bae7", - "alias": "Handle Existing Account - Alternatives - 0", - "description": "Subflow of Handle Existing Account with alternative executions", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-email-verification", - "requirement": "ALTERNATIVE", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "requirement": "ALTERNATIVE", - "priority": 20, - "flowAlias": "Verify Existing Account by Re-authentication", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "id": "2576bf21-a516-4e22-8ed8-8a1a3d35c06a", - "alias": "Verify Existing Account by Re-authentication", - "description": "Reauthentication of existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-username-password-form", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "requirement": "CONDITIONAL", - "priority": 20, - "flowAlias": "Verify Existing Account by Re-authentication - auth-otp-form - Conditional", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "id": "867b0355-c2b0-4f4e-b535-09406e2bc086", - "alias": "Verify Existing Account by Re-authentication - auth-otp-form - Conditional", - "description": "Flow to determine if the auth-otp-form authenticator should be used or not.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "auth-otp-form", - "requirement": "REQUIRED", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - } - ] - }, - { - "id": "52e45a6a-292f-4a34-9c02-7f97d9997a9c", - "alias": "browser", - "description": "browser based authentication", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-cookie", - "requirement": "ALTERNATIVE", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "auth-spnego", - "requirement": "DISABLED", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "identity-provider-redirector", - "requirement": "ALTERNATIVE", - "priority": 25, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "requirement": "ALTERNATIVE", - "priority": 30, - "flowAlias": "forms", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "id": "ef818d24-fb06-418a-a093-16239068cb58", - "alias": "clients", - "description": "Base authentication for clients", - "providerId": "client-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "client-secret", - "requirement": "ALTERNATIVE", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "client-jwt", - "requirement": "ALTERNATIVE", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "client-secret-jwt", - "requirement": "ALTERNATIVE", - "priority": 30, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "client-x509", - "requirement": "ALTERNATIVE", - "priority": 40, - "userSetupAllowed": false, - "autheticatorFlow": false - } - ] - }, - { - "id": "f7864004-be4b-40f2-8534-454981f09f98", - "alias": "direct grant", - "description": "OpenID Connect Resource Owner Grant", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "direct-grant-validate-username", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "direct-grant-validate-password", - "requirement": "REQUIRED", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "requirement": "CONDITIONAL", - "priority": 30, - "flowAlias": "direct grant - direct-grant-validate-otp - Conditional", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "id": "233225f2-78b0-4756-9568-a775ea7cc975", - "alias": "direct grant - direct-grant-validate-otp - Conditional", - "description": "Flow to determine if the direct-grant-validate-otp authenticator should be used or not.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "direct-grant-validate-otp", - "requirement": "REQUIRED", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - } - ] - }, - { - "id": "2787939c-3312-4d56-9d61-22a71947e154", - "alias": "docker auth", - "description": "Used by Docker clients to authenticate against the IDP", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "docker-http-basic-authenticator", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - } - ] - }, - { - "id": "c80ca473-6e65-4140-a9d1-035414546bfb", - "alias": "first broker login", - "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "review profile config", - "authenticator": "idp-review-profile", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "requirement": "REQUIRED", - "priority": 20, - "flowAlias": "first broker login - Alternatives - 0", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "id": "700a71e1-f176-432e-9e70-ccb06d539730", - "alias": "first broker login - Alternatives - 0", - "description": "Subflow of first broker login with alternative executions", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "create unique user config", - "authenticator": "idp-create-user-if-unique", - "requirement": "ALTERNATIVE", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "requirement": "ALTERNATIVE", - "priority": 20, - "flowAlias": "Handle Existing Account", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "id": "13cd2ee9-8ebb-4651-8a9d-535d4020d889", - "alias": "forms", - "description": "Username, password, otp and other auth forms.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-username-password-form", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "requirement": "CONDITIONAL", - "priority": 20, - "flowAlias": "forms - auth-otp-form - Conditional", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "id": "80067ebf-72b9-4ba5-abc3-161dfdd53938", - "alias": "forms - auth-otp-form - Conditional", - "description": "Flow to determine if the auth-otp-form authenticator should be used or not.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "auth-otp-form", - "requirement": "REQUIRED", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - } - ] - }, - { - "id": "269354b1-7dd7-46ff-8a69-084cd2c7be80", - "alias": "http challenge", - "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "no-cookie-redirect", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "basic-auth", - "requirement": "REQUIRED", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "basic-auth-otp", - "requirement": "DISABLED", - "priority": 30, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "auth-spnego", - "requirement": "DISABLED", - "priority": 40, - "userSetupAllowed": false, - "autheticatorFlow": false - } - ] - }, - { - "id": "c5fa64a0-e784-490f-8879-0e8a209e3636", - "alias": "registration", - "description": "registration flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-page-form", - "requirement": "REQUIRED", - "priority": 10, - "flowAlias": "registration form", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "id": "bc48f897-4d16-49a8-be70-183c7867e20a", - "alias": "registration form", - "description": "registration form", - "providerId": "form-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-user-creation", - "requirement": "REQUIRED", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "registration-profile-action", - "requirement": "REQUIRED", - "priority": 40, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "registration-password-action", - "requirement": "REQUIRED", - "priority": 50, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "registration-recaptcha-action", - "requirement": "DISABLED", - "priority": 60, - "userSetupAllowed": false, - "autheticatorFlow": false - } - ] - }, - { - "id": "fddaba41-87b1-40d1-b147-f062c38e39ad", - "alias": "reset credentials", - "description": "Reset credentials for a user if they forgot their password or something", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "reset-credentials-choose-user", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "reset-credential-email", - "requirement": "REQUIRED", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "reset-password", - "requirement": "REQUIRED", - "priority": 30, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "requirement": "CONDITIONAL", - "priority": 40, - "flowAlias": "reset credentials - reset-otp - Conditional", - "userSetupAllowed": false, - "autheticatorFlow": true - } - ] - }, - { - "id": "6b9fa295-1eb4-48b0-a286-b17ebd6be7e1", - "alias": "reset credentials - reset-otp - Conditional", - "description": "Flow to determine if the reset-otp authenticator should be used or not.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }, - { - "authenticator": "reset-otp", - "requirement": "REQUIRED", - "priority": 20, - "userSetupAllowed": false, - "autheticatorFlow": false - } - ] - }, - { - "id": "c890d4c4-e4e2-4618-b69d-8d30f8278965", - "alias": "saml ecp", - "description": "SAML ECP Profile Authentication Flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "http-basic-authenticator", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - } - ] - } - ], - "authenticatorConfig": [ - { - "id": "2b02fbe4-e05e-4238-bb0e-04da7d4efd4e", - "alias": "create unique user config", - "config": { - "require.password.update.after.registration": "false" - } - }, - { - "id": "07dd933b-ce95-4a7c-bd81-3efa24f9558c", - "alias": "review profile config", - "config": { - "update.profile.on.first.login": "missing" - } - } - ], - "requiredActions": [ - { - "alias": "CONFIGURE_TOTP", - "name": "Configure OTP", - "providerId": "CONFIGURE_TOTP", - "enabled": true, - "defaultAction": false, - "priority": 10, - "config": {} - }, - { - "alias": "terms_and_conditions", - "name": "Terms and Conditions", - "providerId": "terms_and_conditions", - "enabled": false, - "defaultAction": false, - "priority": 20, - "config": {} - }, - { - "alias": "UPDATE_PASSWORD", - "name": "Update Password", - "providerId": "UPDATE_PASSWORD", - "enabled": true, - "defaultAction": false, - "priority": 30, - "config": {} - }, - { - "alias": "UPDATE_PROFILE", - "name": "Update Profile", - "providerId": "UPDATE_PROFILE", - "enabled": true, - "defaultAction": false, - "priority": 40, - "config": {} - }, - { - "alias": "VERIFY_EMAIL", - "name": "Verify Email", - "providerId": "VERIFY_EMAIL", - "enabled": true, - "defaultAction": false, - "priority": 50, - "config": {} - }, - { - "alias": "update_user_locale", - "name": "Update User Locale", - "providerId": "update_user_locale", - "enabled": true, - "defaultAction": false, - "priority": 1000, - "config": {} - } - ], - "browserFlow": "browser", - "registrationFlow": "registration", - "directGrantFlow": "direct grant", - "resetCredentialsFlow": "reset credentials", - "clientAuthenticationFlow": "clients", - "dockerAuthenticationFlow": "docker auth", - "attributes": { - "clientOfflineSessionMaxLifespan": "0", - "clientSessionIdleTimeout": "0", - "clientSessionMaxLifespan": "0", - "clientOfflineSessionIdleTimeout": "0" - }, - "keycloakVersion": "11.0.2", - "userManagedAccessAllowed": false -} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/pom.xml index 520646cc7d..004e7fa302 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/pom.xml @@ -4,13 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 gateway-2 - spring-cloud-gateway + gateway-2 jar - com.baeldung.spring.cloud - spring-cloud-modules - 1.0.0-SNAPSHOT + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../../parent-boot-2 @@ -44,107 +45,36 @@ org.springframework.cloud spring-cloud-starter-gateway - - - org.springframework.cloud - spring-cloud-starter-circuitbreaker-reactor-resilience4j - - - - org.springframework.boot - spring-boot-starter-data-redis-reactive - - - - it.ozimov - embedded-redis - ${redis.version} - test - - - org.hibernate - hibernate-validator-cdi - ${hibernate-validator.version} - - - javax.validation - validation-api - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-devtools - - - - org.springframework.boot - spring-boot-starter-oauth2-resource-server - - - org.springframework.boot - spring-boot-starter-oauth2-client - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - ${java.version} - ${java.version} - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - - - - - - - gateway-url-rewrite - - - - org.springframework.boot - spring-boot-maven-plugin - - com.baeldung.springcloudgateway.rewrite.URLRewriteGatewayApplication - -Dspring.profiles.active=url-rewrite - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - 6.0.2.Final - 0.7.2 - 9.19 - + 2021.0.3 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/CustomFiltersGatewayApplication.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/CustomFiltersGatewayApplication.java deleted file mode 100644 index fae25bb7cc..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/CustomFiltersGatewayApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.PropertySource; - -@SpringBootApplication -@PropertySource("classpath:customfilters-global-application.properties") -public class CustomFiltersGatewayApplication { - - public static void main(String[] args) { - SpringApplication.run(CustomFiltersGatewayApplication.class, args); - } - -} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/config/WebClientConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/config/WebClientConfig.java deleted file mode 100644 index 0589d8c321..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/config/WebClientConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.reactive.function.client.WebClient; - -@Configuration -public class WebClientConfig { - - @Bean - WebClient client() { - return WebClient.builder() - .build(); - } - -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ChainRequestGatewayFilterFactory.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ChainRequestGatewayFilterFactory.java deleted file mode 100644 index f53b0a3c93..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ChainRequestGatewayFilterFactory.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories; - -import java.util.Arrays; -import java.util.List; -import java.util.Locale.LanguageRange; -import java.util.stream.Collectors; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.gateway.filter.GatewayFilter; -import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.client.WebClient; - -import reactor.core.publisher.Mono; - -@Component -public class ChainRequestGatewayFilterFactory extends AbstractGatewayFilterFactory { - - final Logger logger = LoggerFactory.getLogger(ChainRequestGatewayFilterFactory.class); - - private final WebClient client; - - public ChainRequestGatewayFilterFactory(WebClient client) { - super(Config.class); - this.client = client; - } - - @Override - public List shortcutFieldOrder() { - return Arrays.asList("languageServiceEndpoint", "defaultLanguage"); - } - - @Override - public GatewayFilter apply(Config config) { - return (exchange, chain) -> { - return client.get() - .uri(config.getLanguageServiceEndpoint()) - .exchange() - .flatMap(response -> { - return (response.statusCode() - .is2xxSuccessful()) ? response.bodyToMono(String.class) : Mono.just(config.getDefaultLanguage()); - }) - .map(LanguageRange::parse) - .map(range -> { - exchange.getRequest() - .mutate() - .headers(h -> h.setAcceptLanguage(range)); - - String allOutgoingRequestLanguages = exchange.getRequest() - .getHeaders() - .getAcceptLanguage() - .stream() - .map(r -> r.getRange()) - .collect(Collectors.joining(",")); - - logger.info("Chain Request output - Request contains Accept-Language header: " + allOutgoingRequestLanguages); - - return exchange; - }) - .flatMap(chain::filter); - - }; - } - - public static class Config { - private String languageServiceEndpoint; - private String defaultLanguage; - - public Config() { - } - - public String getLanguageServiceEndpoint() { - return languageServiceEndpoint; - } - - public void setLanguageServiceEndpoint(String languageServiceEndpoint) { - this.languageServiceEndpoint = languageServiceEndpoint; - } - - public String getDefaultLanguage() { - return defaultLanguage; - } - - public void setDefaultLanguage(String defaultLanguage) { - this.defaultLanguage = defaultLanguage; - } - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/LoggingGatewayFilterFactory.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/LoggingGatewayFilterFactory.java deleted file mode 100644 index 900d36cc02..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/LoggingGatewayFilterFactory.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories; - -import java.util.Arrays; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.gateway.filter.GatewayFilter; -import org.springframework.cloud.gateway.filter.OrderedGatewayFilter; -import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; -import org.springframework.stereotype.Component; - -import reactor.core.publisher.Mono; - -@Component -public class LoggingGatewayFilterFactory extends AbstractGatewayFilterFactory { - - final Logger logger = LoggerFactory.getLogger(LoggingGatewayFilterFactory.class); - - public static final String BASE_MSG = "baseMessage"; - public static final String PRE_LOGGER = "preLogger"; - public static final String POST_LOGGER = "postLogger"; - - public LoggingGatewayFilterFactory() { - super(Config.class); - } - - @Override - public List shortcutFieldOrder() { - return Arrays.asList(BASE_MSG, PRE_LOGGER, POST_LOGGER); - } - - @Override - public GatewayFilter apply(Config config) { - return new OrderedGatewayFilter((exchange, chain) -> { - if (config.isPreLogger()) - logger.info("Pre GatewayFilter logging: " + config.getBaseMessage()); - return chain.filter(exchange) - .then(Mono.fromRunnable(() -> { - if (config.isPostLogger()) - logger.info("Post GatewayFilter logging: " + config.getBaseMessage()); - })); - }, 1); - } - - public static class Config { - private String baseMessage; - private boolean preLogger; - private boolean postLogger; - - public Config() { - }; - - public Config(String baseMessage, boolean preLogger, boolean postLogger) { - super(); - this.baseMessage = baseMessage; - this.preLogger = preLogger; - this.postLogger = postLogger; - } - - public String getBaseMessage() { - return this.baseMessage; - } - - public boolean isPreLogger() { - return preLogger; - } - - public boolean isPostLogger() { - return postLogger; - } - - public void setBaseMessage(String baseMessage) { - this.baseMessage = baseMessage; - } - - public void setPreLogger(boolean preLogger) { - this.preLogger = preLogger; - } - - public void setPostLogger(boolean postLogger) { - this.postLogger = postLogger; - } - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ModifyRequestGatewayFilterFactory.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ModifyRequestGatewayFilterFactory.java deleted file mode 100644 index 5828f35a36..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ModifyRequestGatewayFilterFactory.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Optional; -import java.util.stream.Collectors; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.gateway.filter.GatewayFilter; -import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; -import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.util.UriComponentsBuilder; - -@Component -public class ModifyRequestGatewayFilterFactory extends AbstractGatewayFilterFactory { - - final Logger logger = LoggerFactory.getLogger(ModifyRequestGatewayFilterFactory.class); - - public ModifyRequestGatewayFilterFactory() { - super(Config.class); - } - - @Override - public List shortcutFieldOrder() { - return Arrays.asList("defaultLocale"); - } - - @Override - public GatewayFilter apply(Config config) { - return (exchange, chain) -> { - if (exchange.getRequest() - .getHeaders() - .getAcceptLanguage() - .isEmpty()) { - - String queryParamLocale = exchange.getRequest() - .getQueryParams() - .getFirst("locale"); - - Locale requestLocale = Optional.ofNullable(queryParamLocale) - .map(l -> Locale.forLanguageTag(l)) - .orElse(config.getDefaultLocale()); - - exchange.getRequest() - .mutate() - .headers(h -> h.setAcceptLanguageAsLocales(Collections.singletonList(requestLocale))); - } - - String allOutgoingRequestLanguages = exchange.getRequest() - .getHeaders() - .getAcceptLanguage() - .stream() - .map(range -> range.getRange()) - .collect(Collectors.joining(",")); - - logger.info("Modify request output - Request contains Accept-Language header: {}", allOutgoingRequestLanguages); - - ServerWebExchange modifiedExchange = exchange.mutate() - .request(originalRequest -> originalRequest.uri(UriComponentsBuilder.fromUri(exchange.getRequest() - .getURI()) - .replaceQueryParams(new LinkedMultiValueMap()) - .build() - .toUri())) - .build(); - - logger.info("Removed all query params: {}", modifiedExchange.getRequest() - .getURI()); - - return chain.filter(modifiedExchange); - }; - } - - public static class Config { - private Locale defaultLocale; - - public Config() { - } - - public Locale getDefaultLocale() { - return defaultLocale; - } - - public void setDefaultLocale(String defaultLocale) { - this.defaultLocale = Locale.forLanguageTag(defaultLocale); - }; - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ModifyResponseGatewayFilterFactory.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ModifyResponseGatewayFilterFactory.java deleted file mode 100644 index f5efa69402..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ModifyResponseGatewayFilterFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories; - -import java.util.Optional; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.gateway.filter.GatewayFilter; -import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.stereotype.Component; - -import reactor.core.publisher.Mono; - -@Component -public class ModifyResponseGatewayFilterFactory extends AbstractGatewayFilterFactory { - - final Logger logger = LoggerFactory.getLogger(ModifyResponseGatewayFilterFactory.class); - - public ModifyResponseGatewayFilterFactory() { - super(Config.class); - } - - @Override - public GatewayFilter apply(Config config) { - return (exchange, chain) -> { - return chain.filter(exchange) - .then(Mono.fromRunnable(() -> { - ServerHttpResponse response = exchange.getResponse(); - - Optional.ofNullable(exchange.getRequest() - .getQueryParams() - .getFirst("locale")) - .ifPresent(qp -> { - String responseContentLanguage = response.getHeaders() - .getContentLanguage() - .getLanguage(); - - response.getHeaders() - .add("Bael-Custom-Language-Header", responseContentLanguage); - logger.info("Added custom header to Response"); - }); - })); - }; - } - - public static class Config { - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterFactory.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterFactory.java deleted file mode 100644 index dbe9a9fb4f..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterFactory.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories; - -import java.util.Arrays; -import java.util.List; -import java.util.regex.Pattern; - -import org.reactivestreams.Publisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.gateway.filter.GatewayFilter; -import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; -import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory; -import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction; -import org.springframework.stereotype.Component; -import org.springframework.web.server.ServerWebExchange; - -import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.TextNode; - -import reactor.core.publisher.Mono; - -@Component -public class ScrubResponseGatewayFilterFactory extends AbstractGatewayFilterFactory { - - final Logger logger = LoggerFactory.getLogger(ScrubResponseGatewayFilterFactory.class); - private ModifyResponseBodyGatewayFilterFactory modifyResponseBodyFilterFactory; - - public ScrubResponseGatewayFilterFactory(ModifyResponseBodyGatewayFilterFactory modifyResponseBodyFilterFactory) { - super(Config.class); - this.modifyResponseBodyFilterFactory = modifyResponseBodyFilterFactory; - } - - @Override - public List shortcutFieldOrder() { - return Arrays.asList("fields", "replacement"); - } - - - @Override - public GatewayFilter apply(Config config) { - - return modifyResponseBodyFilterFactory - .apply(c -> c.setRewriteFunction(JsonNode.class, JsonNode.class, new Scrubber(config))); - } - - public static class Config { - - private String fields; - private String replacement; - - - public String getFields() { - return fields; - } - public void setFields(String fields) { - this.fields = fields; - } - public String getReplacement() { - return replacement; - } - public void setReplacement(String replacement) { - this.replacement = replacement; - } - } - - - public static class Scrubber implements RewriteFunction { - private final Pattern fields; - private final String replacement; - - public Scrubber(Config config) { - this.fields = Pattern.compile(config.getFields()); - this.replacement = config.getReplacement(); - } - - @Override - public Publisher apply(ServerWebExchange t, JsonNode u) { - return Mono.just(scrubRecursively(u)); - } - - private JsonNode scrubRecursively(JsonNode u) { - if ( !u.isContainerNode()) { - return u; - } - - if ( u.isObject()) { - ObjectNode node = (ObjectNode)u; - node.fields().forEachRemaining((f) -> { - if ( fields.matcher(f.getKey()).matches() && f.getValue().isTextual()) { - f.setValue(TextNode.valueOf(replacement)); - } - else { - f.setValue(scrubRecursively(f.getValue())); - } - }); - } - else if ( u.isArray()) { - ArrayNode array = (ArrayNode)u; - for ( int i = 0 ; i < array.size() ; i++ ) { - array.set(i, scrubRecursively(array.get(i))); - } - } - - return u; - } - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/FirstPreLastPostGlobalFilter.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/FirstPreLastPostGlobalFilter.java deleted file mode 100644 index 687f3fe685..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/FirstPreLastPostGlobalFilter.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.global; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.gateway.filter.GatewayFilterChain; -import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.core.Ordered; -import org.springframework.stereotype.Component; -import org.springframework.web.server.ServerWebExchange; - -import reactor.core.publisher.Mono; - -@Component -public class FirstPreLastPostGlobalFilter implements GlobalFilter, Ordered { - - final Logger logger = LoggerFactory.getLogger(FirstPreLastPostGlobalFilter.class); - - @Override - public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - logger.info("First Pre Global Filter"); - return chain.filter(exchange) - .then(Mono.fromRunnable(() -> { - logger.info("Last Post Global Filter"); - })); - } - - @Override - public int getOrder() { - return -1; - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/LoggingGlobalFilterProperties.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/LoggingGlobalFilterProperties.java deleted file mode 100644 index 4bf6453355..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/LoggingGlobalFilterProperties.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.global; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties("logging.global") -public class LoggingGlobalFilterProperties { - - private boolean enabled; - private boolean requestHeaders; - private boolean requestBody; - private boolean responseHeaders; - private boolean responseBody; - - public boolean isEnabled() { - return enabled; - } - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - public boolean isRequestHeaders() { - return requestHeaders; - } - public void setRequestHeaders(boolean requestHeaders) { - this.requestHeaders = requestHeaders; - } - public boolean isRequestBody() { - return requestBody; - } - public void setRequestBody(boolean requestBody) { - this.requestBody = requestBody; - } - public boolean isResponseHeaders() { - return responseHeaders; - } - public void setResponseHeaders(boolean responseHeaders) { - this.responseHeaders = responseHeaders; - } - public boolean isResponseBody() { - return responseBody; - } - public void setResponseBody(boolean responseBody) { - this.responseBody = responseBody; - } - - - -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/LoggingGlobalFiltersConfigurations.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/LoggingGlobalFiltersConfigurations.java deleted file mode 100644 index 2dead8da3b..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/LoggingGlobalFiltersConfigurations.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.global; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import reactor.core.publisher.Mono; - -@Configuration -public class LoggingGlobalFiltersConfigurations { - - final Logger logger = LoggerFactory.getLogger(LoggingGlobalFiltersConfigurations.class); - - @Bean - public GlobalFilter postGlobalFilter() { - return (exchange, chain) -> { - return chain.filter(exchange) - .then(Mono.fromRunnable(() -> { - logger.info("Global Post Filter executed"); - })); - }; - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/LoggingGlobalPreFilter.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/LoggingGlobalPreFilter.java deleted file mode 100644 index 2bacf033db..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/global/LoggingGlobalPreFilter.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.global; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.gateway.filter.GatewayFilterChain; -import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.stereotype.Component; -import org.springframework.web.server.ServerWebExchange; - -import reactor.core.publisher.Mono; - -@Component -public class LoggingGlobalPreFilter implements GlobalFilter { - - final Logger logger = LoggerFactory.getLogger(LoggingGlobalPreFilter.class); - - @Override - public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - logger.info("Global Pre Filter executed"); - return chain.filter(exchange); - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/routes/ServiceRouteConfiguration.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/routes/ServiceRouteConfiguration.java deleted file mode 100644 index 17d4827d93..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/routes/ServiceRouteConfiguration.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.routes; - -import org.springframework.cloud.gateway.route.RouteLocator; -import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; -import org.springframework.context.annotation.Bean; - -import com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories.LoggingGatewayFilterFactory; -import com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories.LoggingGatewayFilterFactory.Config; - -/** - * Note: We want to keep this as an example of configuring a Route with a custom filter - * - * This corresponds with the properties configuration we have - */ -// @Configuration -public class ServiceRouteConfiguration { - - @Bean - public RouteLocator routes(RouteLocatorBuilder builder, LoggingGatewayFilterFactory loggingFactory) { - - return builder.routes() - .route("service_route_java_config", r -> r.path("/service/**") - .filters(f -> f.rewritePath("/service(?/?.*)", "$\\{segment}") - .filter(loggingFactory.apply(new Config("My Custom Message", true, true)))) - .uri("http://localhost:8081")) - .build(); - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/secondservice/SecondServiceApplication.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/secondservice/SecondServiceApplication.java deleted file mode 100644 index b65d0efbd6..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/secondservice/SecondServiceApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.secondservice; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.PropertySource; - -@SpringBootApplication -@PropertySource("classpath:secondservice-application.properties") -public class SecondServiceApplication { - - public static void main(String[] args) { - SpringApplication.run(SecondServiceApplication.class, args); - } - -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/secondservice/web/SecondServiceRestController.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/secondservice/web/SecondServiceRestController.java deleted file mode 100644 index 1ac44ba6b1..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/secondservice/web/SecondServiceRestController.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.secondservice.web; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -import reactor.core.publisher.Mono; - -@RestController -public class SecondServiceRestController { - - @GetMapping("/resource/language") - public Mono> getResource() { - return Mono.just(ResponseEntity.ok() - .body("es")); - - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/service/ServiceApplication.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/service/ServiceApplication.java deleted file mode 100644 index 1e2ffb63c2..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/service/ServiceApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.service; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.PropertySource; - -@SpringBootApplication -@PropertySource("classpath:service-application.properties") -public class ServiceApplication { - - public static void main(String[] args) { - SpringApplication.run(ServiceApplication.class, args); - } - -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/service/web/ServiceRestController.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/service/web/ServiceRestController.java deleted file mode 100644 index 3ca09f6853..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/customfilters/service/web/ServiceRestController.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.service.web; - -import java.util.Locale; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -import reactor.core.publisher.Mono; - -@RestController -public class ServiceRestController { - - @GetMapping("/resource") - public Mono> getResource() { - return Mono.just(ResponseEntity.ok() - .header(HttpHeaders.CONTENT_LANGUAGE, Locale.ENGLISH.getLanguage()) - .body("Service Resource")); - - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplication.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplication.java deleted file mode 100644 index 46541b4826..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplication.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * - */ -package com.baeldung.springcloudgateway.rewrite; - -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.gateway.filter.GatewayFilter; - -import reactor.core.publisher.Mono; - -/** - * @author Baeldung - * - */ -@SpringBootApplication -public class URLRewriteGatewayApplication { - - public static void main(String[] args) { - new SpringApplicationBuilder(URLRewriteGatewayApplication.class) - .profiles("url-rewrite") - .run(args); - } - -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/rewrite/routes/DynamicRewriteRoute.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/rewrite/routes/DynamicRewriteRoute.java deleted file mode 100644 index 29d40d7021..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/rewrite/routes/DynamicRewriteRoute.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.baeldung.springcloudgateway.rewrite.routes; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.cloud.gateway.route.RouteLocator; -import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.http.server.reactive.ServerHttpRequest; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl; - -import java.util.Random; - -@Configuration -@Profile("url-rewrite") -public class DynamicRewriteRoute { - - @Value("${rewrite.backend.uri}") - private String backendUri; - private static Random rnd = new Random(); - - @Bean - public RouteLocator dynamicZipCodeRoute(RouteLocatorBuilder builder) { - return builder.routes() - .route("dynamicRewrite", r -> - r.path("/v2/zip/**") - .filters(f -> f.filter((exchange, chain) -> { - ServerHttpRequest req = exchange.getRequest(); - addOriginalRequestUrl(exchange, req.getURI()); - String path = req.getURI().getRawPath(); - String newPath = path.replaceAll( - "/v2/zip/(?.*)", - "/api/zip/${zipcode}-" + String.format("%03d", rnd.nextInt(1000))); - ServerHttpRequest request = req.mutate().path(newPath).build(); - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI()); - return chain.filter(exchange.mutate().request(request).build()); - })) - .uri(backendUri)) - .build(); - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/webfilters/WebFilterGatewayApplication.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/webfilters/WebFilterGatewayApplication.java deleted file mode 100644 index 9e212cc4bf..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/webfilters/WebFilterGatewayApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.springcloudgateway.webfilters; - -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; - -@SpringBootApplication -public class WebFilterGatewayApplication { - - public static void main(String[] args) { - new SpringApplicationBuilder(WebFilterGatewayApplication.class) - .profiles("url-rewrite") - .run(args); - } - -} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/webfilters/config/ModifyBodyRouteConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/webfilters/config/ModifyBodyRouteConfig.java deleted file mode 100644 index 7b6188b66a..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/webfilters/config/ModifyBodyRouteConfig.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.baeldung.springcloudgateway.webfilters.config; - -import org.springframework.cloud.gateway.route.RouteLocator; -import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.MediaType; - -import reactor.core.publisher.Mono; - -@Configuration -public class ModifyBodyRouteConfig { - - @Bean - public RouteLocator routes(RouteLocatorBuilder builder) { - return builder.routes() - .route("modify_request_body", r -> r.path("/post") - .filters(f -> f.modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE, - (exchange, s) -> Mono.just(new Hello(s.toUpperCase())))).uri("https://httpbin.org")) - .build(); - } - - @Bean - public RouteLocator responseRoutes(RouteLocatorBuilder builder) { - return builder.routes() - .route("modify_response_body", r -> r.path("/put/**") - .filters(f -> f.modifyResponseBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE, - (exchange, s) -> Mono.just(new Hello("New Body")))).uri("https://httpbin.org")) - .build(); - } - - static class Hello { - String message; - - public Hello() { } - - public Hello(String message) { - this.message = message; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/webfilters/config/RequestRateLimiterResolverConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/webfilters/config/RequestRateLimiterResolverConfig.java deleted file mode 100644 index f80a742fa6..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/java/com/baeldung/springcloudgateway/webfilters/config/RequestRateLimiterResolverConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.springcloudgateway.webfilters.config; - -import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import reactor.core.publisher.Mono; - -@Configuration -public class RequestRateLimiterResolverConfig { - - @Bean - KeyResolver userKeyResolver() { - return exchange -> Mono.just("1"); - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-nosecurity.yml b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-nosecurity.yml deleted file mode 100644 index 40a52ded0f..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-nosecurity.yml +++ /dev/null @@ -1,8 +0,0 @@ -# Enable this profile to disable security -spring: - autoconfigure: - exclude: - - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration - - org.springframework.boot.actuate.autoconfigure.ManagementSecurityAutoConfiguration - - org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration - - org.springframework.boot.actuate.autoconfigure.security.reactive.ReactiveManagementWebSecurityAutoConfiguration \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-scrub.yml b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-scrub.yml deleted file mode 100644 index da7dfea0a7..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-scrub.yml +++ /dev/null @@ -1,12 +0,0 @@ -spring: - cloud: - gateway: - routes: - - id: rewrite_with_scrub - uri: ${rewrite.backend.uri:http://example.com} - predicates: - - Path=/v1/customer/** - filters: - - RewritePath=/v1/customer/(?.*),/api/$\{segment} - - ScrubResponse=ssn,*** - \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-url-rewrite.yml b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-url-rewrite.yml deleted file mode 100644 index b2656151db..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-url-rewrite.yml +++ /dev/null @@ -1,11 +0,0 @@ -spring: - cloud: - gateway: - routes: - - id: rewrite_v1 - uri: ${rewrite.backend.uri:http://example.com} - predicates: - - Path=/v1/customer/** - filters: - - RewritePath=/v1/customer/(?.*),/api/$\{segment} - \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-webfilters.yml b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-webfilters.yml deleted file mode 100644 index 3348cbbba0..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/application-webfilters.yml +++ /dev/null @@ -1,102 +0,0 @@ -logging: - level: - org.springframework.cloud.gateway: INFO - reactor.netty.http.client: INFO - -spring: - redis: - host: localhost - port: 6379 - cloud: - gateway: - routes: - - id: request_header_route - uri: https://httpbin.org - predicates: - - Path=/get/** - filters: - - AddRequestHeader=My-Header-Good,Good - - AddRequestHeader=My-Header-Remove,Remove - - AddRequestParameter=var, good - - AddRequestParameter=var2, remove - - MapRequestHeader=My-Header-Good, My-Header-Bad - - MapRequestHeader=My-Header-Set, My-Header-Bad - - SetRequestHeader=My-Header-Set, Set - - RemoveRequestHeader=My-Header-Remove - - RemoveRequestParameter=var2 - - PreserveHostHeader - - - id: response_header_route - uri: https://httpbin.org - predicates: - - Path=/header/post/** - filters: - - AddResponseHeader=My-Header-Good,Good - - AddResponseHeader=My-Header-Set,Good - - AddResponseHeader=My-Header-Rewrite, password=12345678 - - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin - - AddResponseHeader=My-Header-Remove,Remove - - SetResponseHeader=My-Header-Set, Set - - RemoveResponseHeader=My-Header-Remove - - RewriteResponseHeader=My-Header-Rewrite, password=[^&]+, password=*** - - RewriteLocationResponseHeader=AS_IN_REQUEST, Location, , - - StripPrefix=1 - - - id: path_route - uri: https://httpbin.org - predicates: - - Path=/new/post/** - filters: - - RewritePath=/new(?/?.*), $\{segment} - - SetPath=/post - - - id: redirect_route - uri: https://httpbin.org - predicates: - - Path=/fake/post/** - filters: - - RedirectTo=302, https://httpbin.org - - - id: status_route - uri: https://httpbin.org - predicates: - - Path=/delete/** - filters: - - SetStatus=401 - - - id: size_route - uri: https://httpbin.org - predicates: - - Path=/anything - filters: - - name: RequestSize - args: - maxSize: 5000000 - - - id: retry_test - uri: https://httpbin.org - predicates: - - Path=/status/502 - filters: - - name: Retry - args: - retries: 3 - statuses: BAD_GATEWAY - methods: GET,POST - backoff: - firstBackoff: 10ms - maxBackoff: 50ms - factor: 2 - basedOnPreviousValue: false - - - id: request_rate_limiter - uri: https://httpbin.org - predicates: - - Path=/redis/get/** - filters: - - StripPrefix=1 - - name: RequestRateLimiter - args: - redis-rate-limiter.replenishRate: 10 - redis-rate-limiter.burstCapacity: 5 - key-resolver: "#{@userKeyResolver}" \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/customfilters-global-application.properties b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/customfilters-global-application.properties deleted file mode 100644 index 08421a0653..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/customfilters-global-application.properties +++ /dev/null @@ -1,19 +0,0 @@ -spring.cloud.gateway.routes[0].id=service_route -spring.cloud.gateway.routes[0].uri=http://localhost:8081 -spring.cloud.gateway.routes[0].predicates[0]=Path=/service/** -spring.cloud.gateway.routes[0].filters[0]=RewritePath=/service(?/?.*), $\{segment} -spring.cloud.gateway.routes[0].filters[1]=Logging=My Custom Message, true, true -# Or, as an alternative: -#spring.cloud.gateway.routes[0].filters[1].name=Logging -#spring.cloud.gateway.routes[0].filters[1].args[baseMessage]=My Custom Message -#spring.cloud.gateway.routes[0].filters[1].args[preLogger]=true -#spring.cloud.gateway.routes[0].filters[1].args[postLogger]=true - -spring.cloud.gateway.routes[0].filters[2]=ModifyResponse -spring.cloud.gateway.routes[0].filters[3]=ModifyRequest=en -spring.cloud.gateway.routes[0].filters[4]=ChainRequest=http://localhost:8082/resource/language, fr - -management.endpoints.web.exposure.include=* - -server.port=80 - diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/secondservice-application.properties b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/secondservice-application.properties deleted file mode 100644 index 3cf12afeb9..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/secondservice-application.properties +++ /dev/null @@ -1 +0,0 @@ -server.port=8082 diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/service-application.properties b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/service-application.properties deleted file mode 100644 index 4d360de145..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/main/resources/service-application.properties +++ /dev/null @@ -1 +0,0 @@ -server.port=8081 diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/CustomFiltersLiveTest.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/CustomFiltersLiveTest.java deleted file mode 100644 index f49f8c68b6..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/CustomFiltersLiveTest.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.assertj.core.api.Condition; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec; - -import com.baeldung.springcloudgateway.customfilters.gatewayapp.utils.LoggerListAppender; - -import ch.qos.logback.classic.spi.ILoggingEvent; - -/** - * This test requires: - * * the service in com.baeldung.service running - * * the 'second service' in com.baeldung.secondservice running - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -public class CustomFiltersLiveTest { - - @LocalServerPort - String port; - - @Autowired - private WebTestClient client; - - @BeforeEach - public void clearLogList() { - LoggerListAppender.clearEventList(); - client = WebTestClient.bindToServer() - .baseUrl("http://localhost:" + port) - .build(); - } - - @Test - public void whenCallServiceThroughGateway_thenAllConfiguredFiltersGetExecuted() { - ResponseSpec response = client.get() - .uri("/service/resource") - .exchange(); - - response.expectStatus() - .isOk() - .expectHeader() - .doesNotExist("Bael-Custom-Language-Header") - .expectBody(String.class) - .isEqualTo("Service Resource"); - - assertThat(LoggerListAppender.getEvents()) - // Global Pre Filter - .haveAtLeastOne(eventContains("Global Pre Filter executed")) - // Global Post Filter - .haveAtLeastOne(eventContains("Global Post Filter executed")) - // Global Pre and Post Filter - .haveAtLeastOne(eventContains("First Pre Global Filter")) - .haveAtLeastOne(eventContains("Last Post Global Filter")) - // Logging Filter Factory - .haveAtLeastOne(eventContains("Pre GatewayFilter logging: My Custom Message")) - .haveAtLeastOne(eventContains("Post GatewayFilter logging: My Custom Message")) - // Modify Request - .haveAtLeastOne(eventContains("Modify request output - Request contains Accept-Language header:")) - .haveAtLeastOne(eventContainsExcept("Removed all query params: ", "locale")) - // Modify Response - .areNot(eventContains("Added custom header to Response")) - // Chain Request - .haveAtLeastOne(eventContains("Chain Request output - Request contains Accept-Language header:")); - } - - @Test - public void givenRequestWithLocaleQueryParam_whenCallServiceThroughGateway_thenAllConfiguredFiltersGetExecuted() { - ResponseSpec response = client.get() - .uri("/service/resource?locale=en") - .exchange(); - - response.expectStatus() - .isOk() - .expectHeader() - .exists("Bael-Custom-Language-Header") - .expectBody(String.class) - .isEqualTo("Service Resource"); - - assertThat(LoggerListAppender.getEvents()) - // Modify Response - .haveAtLeastOne(eventContains("Added custom header to Response")) - .haveAtLeastOne(eventContainsExcept("Removed all query params: ", "locale")); - } - - /** - * This condition will be successful if the event contains a substring - */ - private Condition eventContains(String substring) { - return new Condition(entry -> (substring == null || (entry.getFormattedMessage() != null && entry.getFormattedMessage() - .contains(substring))), String.format("entry with message '%s'", substring)); - } - - /** - * This condition will be successful if the event contains a substring, but not another one - */ - private Condition eventContainsExcept(String substring, String except) { - return new Condition(entry -> (substring == null || (entry.getFormattedMessage() != null && entry.getFormattedMessage() - .contains(substring) - && !entry.getFormattedMessage() - .contains(except))), - String.format("entry with message '%s'", substring)); - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterFactoryUnitTest.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterFactoryUnitTest.java deleted file mode 100644 index 667aabaddc..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterFactoryUnitTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories; - -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.Test; - -import com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories.ScrubResponseGatewayFilterFactory.Config; -import com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories.ScrubResponseGatewayFilterFactory.Scrubber; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.ObjectCodec; -import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; - -import reactor.core.publisher.Mono; - -class ScrubResponseGatewayFilterFactoryUnitTest { - - private static final String JSON_WITH_FIELDS_TO_SCRUB = "{\r\n" - + " \"name\" : \"John Doe\",\r\n" - + " \"ssn\" : \"123-45-9999\",\r\n" - + " \"account\" : \"9999888877770000\"\r\n" - + "}"; - - - @Test - void givenJsonWithFieldsToScrub_whenApply_thenScrubFields() throws Exception{ - - JsonFactory jf = new JsonFactory(new ObjectMapper()); - JsonParser parser = jf.createParser(JSON_WITH_FIELDS_TO_SCRUB); - JsonNode root = parser.readValueAsTree(); - - Config config = new Config(); - config.setFields("ssn|account"); - config.setReplacement("*"); - Scrubber scrubber = new ScrubResponseGatewayFilterFactory.Scrubber(config); - - JsonNode scrubbed = Mono.from(scrubber.apply(null, root)).block(); - assertNotNull(scrubbed); - assertEquals("*", scrubbed.get("ssn").asText()); - } - - @Test - void givenJsonWithoutFieldsToScrub_whenApply_theBodUnchanged() throws Exception{ - - JsonFactory jf = new JsonFactory(new ObjectMapper()); - JsonParser parser = jf.createParser(JSON_WITH_FIELDS_TO_SCRUB); - JsonNode root = parser.readValueAsTree(); - - Config config = new Config(); - config.setFields("xxxx"); - config.setReplacement("*"); - Scrubber scrubber = new ScrubResponseGatewayFilterFactory.Scrubber(config); - - JsonNode scrubbed = Mono.from(scrubber.apply(null, root)).block(); - assertNotNull(scrubbed); - assertNotEquals("*", scrubbed.get("ssn").asText()); - } - -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterLiveTest.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterLiveTest.java deleted file mode 100644 index 8906af774e..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterLiveTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.filters.factories; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.Collections; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory; -import org.springframework.cloud.gateway.route.RouteLocator; -import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; -import org.springframework.http.MediaType; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.web.server.SecurityWebFilterChain; -import org.springframework.test.web.reactive.server.WebTestClient; - -import com.sun.net.httpserver.HttpServer; - -import reactor.netty.http.client.HttpClient; - -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -public class ScrubResponseGatewayFilterLiveTest { - - private static Logger log = LoggerFactory.getLogger(ScrubResponseGatewayFilterLiveTest.class); - - private static final String JSON_WITH_FIELDS_TO_SCRUB = "{\r\n" - + " \"name\" : \"John Doe\",\r\n" - + " \"ssn\" : \"123-45-9999\",\r\n" - + " \"account\" : \"9999888877770000\"\r\n" - + "}"; - - private static final String JSON_WITH_SCRUBBED_FIELDS = "{\r\n" - + " \"name\" : \"John Doe\",\r\n" - + " \"ssn\" : \"*\",\r\n" - + " \"account\" : \"9999888877770000\"\r\n" - + "}"; - - @LocalServerPort - String port; - - @Autowired - private WebTestClient client; - - @Autowired HttpServer server; - - @Test - public void givenRequestToScrubRoute_thenResponseScrubbed() { - - client.get() - .uri("/scrub") - .accept(MediaType.APPLICATION_JSON) - .exchange() - .expectStatus() - .is2xxSuccessful() - .expectHeader() - .contentType(MediaType.APPLICATION_JSON) - .expectBody() - .json(JSON_WITH_SCRUBBED_FIELDS); - } - - - @TestConfiguration - public static class TestRoutesConfiguration { - - - @Bean - public RouteLocator scrubSsnRoute(RouteLocatorBuilder builder, ScrubResponseGatewayFilterFactory scrubFilterFactory, SetPathGatewayFilterFactory pathFilterFactory, HttpServer server ) { - - log.info("[I92] Creating scrubSsnRoute..."); - - int mockServerPort = server.getAddress().getPort(); - ScrubResponseGatewayFilterFactory.Config config = new ScrubResponseGatewayFilterFactory.Config(); - config.setFields("ssn"); - config.setReplacement("*"); - - SetPathGatewayFilterFactory.Config pathConfig = new SetPathGatewayFilterFactory.Config(); - pathConfig.setTemplate("/customer"); - - return builder.routes() - .route("scrub_ssn", - r -> r.path("/scrub") - .filters( - f -> f - .filter(scrubFilterFactory.apply(config)) - .filter(pathFilterFactory.apply(pathConfig))) - .uri("http://localhost:" + mockServerPort )) - .build(); - } - - @Bean - public SecurityWebFilterChain testFilterChain(ServerHttpSecurity http ) { - - // @formatter:off - return http.authorizeExchange() - .anyExchange() - .permitAll() - .and() - .build(); - // @formatter:on - } - - @Bean - public HttpServer mockServer() throws IOException { - - log.info("[I48] Starting mock server..."); - - HttpServer server = HttpServer.create(new InetSocketAddress(0),0); - server.createContext("/customer", (exchange) -> { - exchange.getResponseHeaders().set("Content-Type", "application/json"); - - byte[] response = JSON_WITH_FIELDS_TO_SCRUB.getBytes("UTF-8"); - exchange.sendResponseHeaders(200,response.length); - exchange.getResponseBody().write(response); - }); - - server.setExecutor(null); - server.start(); - - log.info("[I65] Mock server started. port={}", server.getAddress().getPort()); - return server; - } - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/secondservice/SecondServiceIntegrationTest.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/secondservice/SecondServiceIntegrationTest.java deleted file mode 100644 index f4b3d0f00d..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/secondservice/SecondServiceIntegrationTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.secondservice; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration; -import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; -import org.springframework.test.web.reactive.server.WebTestClient; - -import com.baeldung.springcloudgateway.customfilters.secondservice.web.SecondServiceRestController; - -@WebFluxTest(controllers = SecondServiceRestController.class, - excludeAutoConfiguration = ReactiveSecurityAutoConfiguration.class) -public class SecondServiceIntegrationTest { - - @Autowired - private WebTestClient webClient; - - @Test - public void whenResourceLanguageEndpointCalled_thenRetrievesSpanishLanguageString() throws Exception { - this.webClient.get() - .uri("/resource/language") - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .isEqualTo("es"); - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/secondservice/SpringContextTest.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/secondservice/SpringContextTest.java deleted file mode 100644 index eaf94c0a42..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/secondservice/SpringContextTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.secondservice; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest(classes = SecondServiceApplication.class) -public class SpringContextTest { - - @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/service/ServiceIntegrationTest.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/service/ServiceIntegrationTest.java deleted file mode 100644 index 9990cd003c..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/service/ServiceIntegrationTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.service; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration; -import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; -import org.springframework.http.HttpHeaders; -import org.springframework.test.web.reactive.server.WebTestClient; - -import com.baeldung.springcloudgateway.customfilters.service.web.ServiceRestController; - -@WebFluxTest(controllers = ServiceRestController.class, - excludeAutoConfiguration = ReactiveSecurityAutoConfiguration.class) -public class ServiceIntegrationTest { - - @Autowired - private WebTestClient webClient; - - @Test - public void whenResourceEndpointCalled_thenRetrievesResourceStringWithContentLanguageHeader() throws Exception { - this.webClient.get() - .uri("/resource") - .exchange() - .expectStatus() - .isOk() - .expectHeader() - .valueEquals(HttpHeaders.CONTENT_LANGUAGE, "en") - .expectBody(String.class) - .isEqualTo("Service Resource"); - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/service/SpringContextTest.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/service/SpringContextTest.java deleted file mode 100644 index 2a9b322d5e..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/service/SpringContextTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.springcloudgateway.customfilters.service; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest(classes = ServiceApplication.class) -public class SpringContextTest { - - @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/utils/LoggerListAppender.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/introduction/LoggerListAppender.java similarity index 88% rename from spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/utils/LoggerListAppender.java rename to spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/introduction/LoggerListAppender.java index 8e113b417b..33855cd15d 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/utils/LoggerListAppender.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/introduction/LoggerListAppender.java @@ -1,4 +1,4 @@ -package com.baeldung.springcloudgateway.customfilters.gatewayapp.utils; +package com.baeldung.springcloudgateway.introduction; import java.util.ArrayList; import java.util.List; diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplicationLiveTest.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplicationLiveTest.java deleted file mode 100644 index 41fe37045c..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplicationLiveTest.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.baeldung.springcloudgateway.rewrite; - -import static org.junit.Assert.assertTrue; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.OutputStream; -import java.net.InetSocketAddress; - -import org.junit.AfterClass; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; -import org.springframework.test.web.reactive.server.WebTestClient; - -import com.sun.net.httpserver.HttpServer; - -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -@ActiveProfiles({ "nosecurity", "url-rewrite" }) -class URLRewriteGatewayApplicationLiveTest { - - // NOTE for Eclipse users: By default, Eclipse will complain about com.sun.** classes. - // To solve this issue, follow instructions available at the : - // https://stackoverflow.com/questions/13155734/eclipse-cant-recognize-com-sun-net-httpserver-httpserver-package - private static HttpServer mockServer; - private static Logger log = LoggerFactory.getLogger(URLRewriteGatewayApplicationLiveTest.class); - - // Create a running HttpServer that echoes back the request URL. - private static HttpServer startTestServer() { - - try { - log.info("[I26] Starting mock server"); - mockServer = HttpServer.create(); - mockServer.bind(new InetSocketAddress(0), 0); - mockServer.createContext("/api", (xchg) -> { - String uri = xchg.getRequestURI() - .toString(); - log.info("[I23] Backend called: uri={}", uri); - xchg.getResponseHeaders() - .add("Content-Type", "text/plain"); - xchg.sendResponseHeaders(200, 0); - OutputStream os = xchg.getResponseBody(); - os.write(uri.getBytes()); - os.flush(); - os.close(); - }); - - mockServer.start(); - InetSocketAddress localAddr = mockServer.getAddress(); - log.info("[I36] mock server started: local address={}", localAddr); - - return mockServer; - } catch (Exception ex) { - throw new RuntimeException(ex); - } - - } - - // TIP: https://www.baeldung.com/spring-dynamicpropertysource - @DynamicPropertySource - static void registerBackendServer(DynamicPropertyRegistry registry) { - registry.add("rewrite.backend.uri", () -> { - HttpServer s = startTestServer(); - return "http://localhost:" + s.getAddress().getPort(); - }); - } - - @AfterClass - public static void stopMockBackend() throws Exception { - log.info("[I40] Shutdown mock http server"); - mockServer.stop(5); - } - - @LocalServerPort - private int localPort; - - @Test - void testWhenApiCall_thenRewriteSuccess(@Autowired WebTestClient webClient) { - webClient.get() - .uri("http://localhost:" + localPort + "/v1/customer/customer1") - .exchange() - .expectBody() - .consumeWith((result) -> { - String body = new String(result.getResponseBody()); - log.info("[I99] body={}", body); - assertEquals("/api/customer1", body); - }); - } - - @Test - void testWhenDslCall_thenRewriteSuccess(@Autowired WebTestClient webClient) { - webClient.get() - .uri("http://localhost:" + localPort + "/v2/zip/123456") - .exchange() - .expectBody() - .consumeWith((result) -> { - String body = new String(result.getResponseBody()); - log.info("[I99] body={}", body); - assertTrue(body.matches("/api/zip/123456-\\d{3}")); - }); - } - -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/webfilters/RedisWebFilterFactoriesLiveTest.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/webfilters/RedisWebFilterFactoriesLiveTest.java deleted file mode 100644 index a28eb68775..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/webfilters/RedisWebFilterFactoriesLiveTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.baeldung.springcloudgateway.webfilters; - -import org.junit.After; -import org.junit.Before; -import org.junit.jupiter.api.RepeatedTest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.ActiveProfiles; - -import redis.embedded.RedisServer; - -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -@ActiveProfiles("webfilters") -@TestConfiguration -public class RedisWebFilterFactoriesLiveTest { - - private static final Logger LOGGER = LoggerFactory.getLogger(RedisWebFilterFactoriesLiveTest.class); - - private RedisServer redisServer; - - public RedisWebFilterFactoriesLiveTest() { - } - - @Before - public void postConstruct() { - this.redisServer = new RedisServer(6379); - redisServer.start(); - } - - @LocalServerPort - String port; - - @Autowired - private TestRestTemplate restTemplate; - - @Autowired - TestRestTemplate template; - - @RepeatedTest(25) - public void whenCallRedisGetThroughGateway_thenOKStatusOrIsReceived() { - String url = "http://localhost:" + port + "/redis/get"; - - ResponseEntity r = restTemplate.getForEntity(url, String.class); - // assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - - LOGGER.info("Received: status->{}, reason->{}, remaining->{}", - r.getStatusCodeValue(), r.getStatusCode().getReasonPhrase(), - r.getHeaders().get("X-RateLimit-Remaining")); - } - - @After - public void preDestroy() { - redisServer.stop(); - } - -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/webfilters/WebFilterFactoriesLiveTest.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/webfilters/WebFilterFactoriesLiveTest.java deleted file mode 100644 index 67e00a42fc..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/java/com/baeldung/springcloudgateway/webfilters/WebFilterFactoriesLiveTest.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.baeldung.springcloudgateway.webfilters; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import org.assertj.core.api.Condition; -import org.json.JSONException; -import org.json.JSONObject; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec; - -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -@ActiveProfiles("webfilters") -public class WebFilterFactoriesLiveTest { - - @LocalServerPort - String port; - - @Autowired - private WebTestClient client; - - @Autowired - private TestRestTemplate restTemplate; - - @BeforeEach - public void configureClient() { - client = WebTestClient.bindToServer() - .baseUrl("http://localhost:" + port) - .build(); - } - - @Test - public void whenCallGetThroughGateway_thenAllHTTPRequestHeadersParametersAreSet() throws JSONException { - String url = "http://localhost:" + port + "/get"; - ResponseEntity response = restTemplate.getForEntity(url, String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - - JSONObject json = new JSONObject(response.getBody()); - JSONObject headers = json.getJSONObject("headers"); - assertThat(headers.getString("My-Header-Good")).isEqualTo("Good"); - assertThat(headers.getString("My-Header-Bad")).isEqualTo("Good"); - assertThat(headers.getString("My-Header-Set")).isEqualTo("Set"); - assertTrue(headers.isNull("My-Header-Remove")); - JSONObject vars = json.getJSONObject("args"); - assertThat(vars.getString("var")).isEqualTo("good"); - } - - @Test - public void whenCallHeaderPostThroughGateway_thenAllHTTPResponseHeadersAreSet() { - ResponseSpec response = client.post() - .uri("/header/post") - .exchange(); - - response.expectStatus() - .isOk() - .expectHeader() - .valueEquals("My-Header-Rewrite", "password=***") - .expectHeader() - .valueEquals("My-Header-Set", "Set") - .expectHeader() - .valueEquals("My-Header-Good", "Good") - .expectHeader() - .doesNotExist("My-Header-Remove"); - } - - @Test - public void whenCallPostThroughGateway_thenBodyIsRetrieved() throws JSONException { - String url = "http://localhost:" + port + "/post"; - - HttpEntity entity = new HttpEntity<>("content", new HttpHeaders()); - - ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - - JSONObject json = new JSONObject(response.getBody()); - JSONObject data = json.getJSONObject("json"); - assertThat(data.getString("message")).isEqualTo("CONTENT"); - } - - @Test - public void whenCallPutThroughGateway_thenBodyIsRetrieved() throws JSONException { - String url = "http://localhost:" + port + "/put"; - - HttpEntity entity = new HttpEntity<>("CONTENT", new HttpHeaders()); - - ResponseEntity response = restTemplate.exchange(url, HttpMethod.PUT, entity, String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - - JSONObject json = new JSONObject(response.getBody()); - assertThat(json.getString("message")).isEqualTo("New Body"); - } - - @Test - public void whenCallDeleteThroughGateway_thenIsUnauthorizedCodeIsSet() { - ResponseSpec response = client.delete() - .uri("/delete") - .exchange(); - - response.expectStatus() - .isUnauthorized(); - } - - @Test - public void whenCallFakePostThroughGateway_thenIsUnauthorizedCodeIsSet() { - ResponseSpec response = client.post() - .uri("/fake/post") - .exchange(); - - response.expectStatus() - .is3xxRedirection(); - } - - @Test - public void whenCallStatus504ThroughGateway_thenCircuitBreakerIsExecuted() throws JSONException { - String url = "http://localhost:" + port + "/status/504"; - ResponseEntity response = restTemplate.getForEntity(url, String.class); - - JSONObject json = new JSONObject(response.getBody()); - assertThat(json.getString("url")).contains("anything"); - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/postman/OAuth_Gateway.postman_collection.json b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/postman/OAuth_Gateway.postman_collection.json deleted file mode 100644 index ac920a271b..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/postman/OAuth_Gateway.postman_collection.json +++ /dev/null @@ -1,203 +0,0 @@ -{ - "info": { - "_postman_id": "b3d00e23-c2cd-40ce-a90b-673efb25e5c0", - "name": "Baeldung - OAuth", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "Token", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var jsonData = pm.response.json();\r", - "pm.environment.set(\"access_token\", jsonData.access_token);\r", - "pm.environment.set(\"refresh_token\", jsonData.refresh_token);\r", - "pm.environment.set(\"backend_token\", \"Bearer \" + jsonData.access_token);" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "client_id", - "value": "{{client_id}}", - "type": "text" - }, - { - "key": "client_secret", - "value": "{{client_secret}}", - "type": "text" - }, - { - "key": "grant_type", - "value": "password", - "type": "text" - }, - { - "key": "scope", - "value": "email roles profile", - "type": "text" - }, - { - "key": "username", - "value": "maxwell.smart", - "type": "text" - }, - { - "key": "password", - "value": "1234", - "type": "text" - } - ] - }, - "url": { - "raw": "{{keycloack_base}}/token", - "host": [ - "{{keycloack_base}}" - ], - "path": [ - "token" - ] - } - }, - "response": [] - }, - { - "name": "Quote", - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "accept": true - } - }, - "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json", - "type": "text" - } - ], - "url": { - "raw": "http://localhost:8085/quotes/:symbol", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "8085", - "path": [ - "quotes", - ":symbol" - ], - "variable": [ - { - "key": "symbol", - "value": "IBM" - } - ] - } - }, - "response": [] - }, - { - "name": "Quote via Gateway", - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "accept": true - } - }, - "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json", - "type": "text" - } - ], - "url": { - "raw": "http://localhost:8086/quotes/:symbol", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "8086", - "path": [ - "quotes", - ":symbol" - ], - "variable": [ - { - "key": "symbol", - "value": "IBM" - } - ] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ], - "variable": [ - { - "key": "keycloack_base", - "value": "http://localhost:8083/auth/realms/baeldung/protocol/openid-connect" - }, - { - "key": "client_id", - "value": "quotes-client" - }, - { - "key": "client_secret", - "value": "56be94c8-b20a-4374-899c-e39cb022d3f8" - } - ] -} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/resources/logback-test.xml b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/resources/logback-test.xml index 6980d119b1..90c8f570aa 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/resources/logback-test.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway-2/src/test/resources/logback-test.xml @@ -1,7 +1,7 @@ + class="com.baeldung.springcloudgateway.introduction.LoggerListAppender">