StickyUtils.java
- /*
- * GovWay - A customizable API Gateway
- * https://govway.org
- *
- * Copyright (c) 2005-2025 Link.it srl (https://link.it).
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3, as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- package org.openspcoop2.pdd.core.behaviour.built_in.load_balance.sticky;
- import java.io.ByteArrayOutputStream;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import javax.servlet.http.Cookie;
- import javax.servlet.http.HttpServletRequest;
- import org.apache.commons.lang.StringUtils;
- import org.openspcoop2.core.config.PortaApplicativa;
- import org.openspcoop2.core.config.Proprieta;
- import org.openspcoop2.core.id.IDPortaApplicativa;
- import org.openspcoop2.message.OpenSPCoop2Message;
- import org.openspcoop2.message.constants.MessageType;
- import org.openspcoop2.message.constants.ServiceBinding;
- import org.openspcoop2.pdd.config.ConfigurazionePdDManager;
- import org.openspcoop2.pdd.config.OpenSPCoop2Properties;
- import org.openspcoop2.pdd.core.CostantiPdD;
- import org.openspcoop2.pdd.core.PdDContext;
- import org.openspcoop2.pdd.core.behaviour.BehaviourEmitDiagnosticException;
- import org.openspcoop2.pdd.core.behaviour.BehaviourException;
- import org.openspcoop2.pdd.core.behaviour.BehaviourPropertiesUtils;
- import org.openspcoop2.pdd.core.behaviour.conditional.ConditionalUtils;
- import org.openspcoop2.pdd.core.dynamic.DynamicUtils;
- import org.openspcoop2.pdd.core.dynamic.ErrorHandler;
- import org.openspcoop2.pdd.core.dynamic.MessageContent;
- import org.openspcoop2.pdd.core.dynamic.Template;
- import org.openspcoop2.pdd.logger.MsgDiagnosticiProperties;
- import org.openspcoop2.pdd.logger.MsgDiagnostico;
- import org.openspcoop2.pdd.services.connector.FormUrlEncodedHttpServletRequest;
- import org.openspcoop2.protocol.sdk.Busta;
- import org.openspcoop2.protocol.sdk.state.IState;
- import org.openspcoop2.protocol.sdk.state.RequestInfo;
- import org.openspcoop2.utils.regexp.RegExpNotFoundException;
- import org.openspcoop2.utils.regexp.RegularExpressionEngine;
- import org.openspcoop2.utils.transport.TransportUtils;
- import org.openspcoop2.utils.transport.http.HttpServletTransportRequestContext;
- import org.openspcoop2.utils.xml.AbstractXPathExpressionEngine;
- import org.openspcoop2.utils.xml2json.JsonXmlPathExpressionEngine;
- import org.slf4j.Logger;
- /**
- * ConditionalUtils
- *
- * @author Andrea Poli (apoli@link.it)
- * @author $Author$
- * @version $Rev$, $Date$
- */
- public class StickyUtils {
-
- public static StickyResult getStickyResult(PortaApplicativa pa, OpenSPCoop2Message message, Busta busta,
- RequestInfo requestInfo, PdDContext pddContext,
- MsgDiagnostico msgDiag, Logger log,
- IState state) throws BehaviourException, BehaviourEmitDiagnosticException {
-
- if(isConfigurazioneSticky(pa, log)==false) {
- return null; // non vi è da fare alcun filtro condizionale
- }
-
- StickyResult result = new StickyResult();
-
- StickyConfigurazione config = read(pa, log);
- StickyTipoSelettore tipoSelettore = config.getTipoSelettore();
- String patternSelettore = config.getPattern();
-
- String pattern = "";
- try {
- Map<String, List<String>> pTrasporto = null;
- String urlInvocazione = null;
- Map<String, List<String>> pQuery = null;
- Map<String, List<String>> pForm = null;
- if(requestInfo!=null && requestInfo.getProtocolContext()!=null) {
- pTrasporto = requestInfo.getProtocolContext().getHeaders();
- urlInvocazione = requestInfo.getProtocolContext().getUrlInvocazione_formBased();
- pQuery = requestInfo.getProtocolContext().getParameters();
- if(requestInfo.getProtocolContext() instanceof HttpServletTransportRequestContext) {
- HttpServletTransportRequestContext httpServletContext = (HttpServletTransportRequestContext) requestInfo.getProtocolContext();
- HttpServletRequest httpServletRequest = httpServletContext.getHttpServletRequest();
- if(httpServletRequest!=null && httpServletRequest instanceof FormUrlEncodedHttpServletRequest) {
- FormUrlEncodedHttpServletRequest formServlet = (FormUrlEncodedHttpServletRequest) httpServletRequest;
- if(formServlet.getFormUrlEncodedParametersValues()!=null &&
- !formServlet.getFormUrlEncodedParametersValues().isEmpty()) {
- pForm = formServlet.getFormUrlEncodedParametersValues();
- }
- }
- }
- }
- MessageContent messageContent = null;
- boolean bufferMessage_readOnly = OpenSPCoop2Properties.getInstance().isReadByPathBufferEnabled();
- if(StickyTipoSelettore.CONTENT_BASED.equals(tipoSelettore) || tipoSelettore.isTemplate()) {
- if(ServiceBinding.SOAP.equals(message.getServiceBinding())){
- messageContent = new MessageContent(message.castAsSoap(), bufferMessage_readOnly, pddContext);
- }
- else{
- if(MessageType.XML.equals(message.getMessageType())){
- messageContent = new MessageContent(message.castAsRestXml(), bufferMessage_readOnly, pddContext);
- }
- else if(MessageType.JSON.equals(message.getMessageType())){
- messageContent = new MessageContent(message.castAsRestJson(), bufferMessage_readOnly, pddContext);
- }
- else{
- if(StickyTipoSelettore.CONTENT_BASED.equals(tipoSelettore)
- // Nei template potrei utilizzare gli header o altre informazioni che non entrano nel merito del contenuto //|| tipoSelettore.isTemplate()
- ) {
- throw new Exception("Selettore '"+tipoSelettore.getValue()+"' non supportato per il message-type '"+message.getMessageType()+"'");
- }
- }
- }
- }
-
- msgDiag.addKeyword(CostantiPdD.KEY_TIPO_SELETTORE, tipoSelettore.getValue());
- msgDiag.addKeyword(CostantiPdD.KEY_PATTERN_SELETTORE, pattern); // per eliminare @@ dove non serve
-
- String condition = null;
- switch (tipoSelettore) {
-
- case COOKIE_BASED:
- pattern = " (Cookie: "+patternSelettore+")";
- msgDiag.addKeyword(CostantiPdD.KEY_PATTERN_SELETTORE, pattern);
- StickyCookieConfig stickyCookie = new StickyCookieConfig(patternSelettore);
- if(requestInfo!=null && requestInfo.getProtocolContext()!=null && requestInfo.getProtocolContext().getHttpServletRequest()!=null) {
- Cookie [] cookies = requestInfo.getProtocolContext().getHttpServletRequest().getCookies();
- if(cookies!=null && cookies.length>0) {
- for (Cookie cookie : cookies) {
- if(cookie.getName().equalsIgnoreCase(stickyCookie.getName())) {
-
- // NOTA: Nelle richieste il domani e il path non dovrebbero mai esserci. Lascio comunque il codice.
-
- if(!StringUtils.isEmpty(stickyCookie.getDomain())) {
- if(!stickyCookie.getDomain().equals(cookie.getDomain())) {
- continue; // il cookie non ha un match sul domain
- }
- }
- if(!StringUtils.isEmpty(stickyCookie.getPath())) {
- if(!stickyCookie.getPath().equals(cookie.getPath())) {
- continue; // il cookie non ha un match sul domain
- }
- }
-
- condition = cookie.getValue();
-
- if(cookie.getMaxAge()>0) {
- result.setMaxAgeSeconds(cookie.getMaxAge());
- }
-
- break;
- }
- }
- }
- }
- if(condition==null) {
- throw new Exception("cookie non presente");
- }
- break;
-
- case HEADER_BASED:
- pattern = " (Header HTTP: "+patternSelettore+")";
- msgDiag.addKeyword(CostantiPdD.KEY_PATTERN_SELETTORE, pattern);
- condition = TransportUtils.getFirstValue(pTrasporto, patternSelettore);
- if(condition==null) {
- throw new Exception("header non presente");
- }
- break;
-
- case URLBASED:
- pattern = " (Espressione Regolare: "+patternSelettore+")";
- msgDiag.addKeyword(CostantiPdD.KEY_PATTERN_SELETTORE, pattern);
- try{
- condition = RegularExpressionEngine.getStringMatchPattern(urlInvocazione, patternSelettore);
- }catch(RegExpNotFoundException notFound){}
- break;
-
- case FORM_BASED:
- pattern = " (Parametro URL: "+patternSelettore+")";
- msgDiag.addKeyword(CostantiPdD.KEY_PATTERN_SELETTORE, pattern);
- condition = TransportUtils.getFirstValue(pQuery, patternSelettore);
- if(condition==null) {
- throw new Exception("parametro della url non presente");
- }
- break;
-
- case CONTENT_BASED:
- AbstractXPathExpressionEngine xPathEngine = null;
- if(messageContent==null) {
- throw new Exception("messaggio non presente");
- }
- if(messageContent.isXml()) {
- pattern = " (xPath: "+patternSelettore+")";
- msgDiag.addKeyword(CostantiPdD.KEY_PATTERN_SELETTORE, pattern);
- xPathEngine = new org.openspcoop2.message.xml.XPathExpressionEngine(message.getFactory());
- condition = AbstractXPathExpressionEngine.extractAndConvertResultAsString(messageContent.getElement(), xPathEngine, patternSelettore, log);
- }
- else {
- pattern = " (jsonPath: "+patternSelettore+")";
- msgDiag.addKeyword(CostantiPdD.KEY_PATTERN_SELETTORE, pattern);
- condition = JsonXmlPathExpressionEngine.extractAndConvertResultAsString(messageContent.getElementJson(), patternSelettore, log);
- }
- break;
-
- case INDIRIZZO_IP:
- if(pddContext!=null && pddContext.containsKey(org.openspcoop2.core.constants.Costanti.CLIENT_IP_REMOTE_ADDRESS)) {
- condition = (String) pddContext.getObject(org.openspcoop2.core.constants.Costanti.CLIENT_IP_REMOTE_ADDRESS);
- }
- break;
-
- case INDIRIZZO_IP_FORWARDED:
- if(pddContext!=null && pddContext.containsKey(org.openspcoop2.core.constants.Costanti.CLIENT_IP_TRANSPORT_ADDRESS)) {
- condition = (String) pddContext.getObject(org.openspcoop2.core.constants.Costanti.CLIENT_IP_TRANSPORT_ADDRESS);
- }
- break;
-
- case TEMPLATE:
- if(patternSelettore.length()<50) {
- pattern = " ("+patternSelettore+")";
- }
- else {
- pattern = "";
- }
- msgDiag.addKeyword(CostantiPdD.KEY_PATTERN_SELETTORE, pattern);
- Map<String, Object> dynamicMap = new HashMap<>();
- ErrorHandler errorHandler = new ErrorHandler();
- DynamicUtils.fillDynamicMapRequest(log, dynamicMap, pddContext, urlInvocazione,
- message,
- messageContent,
- busta,
- pTrasporto,
- pQuery,
- pForm,
- errorHandler);
- condition = DynamicUtils.convertDynamicPropertyValue("ConditionalConfig.gwt", patternSelettore, dynamicMap, pddContext);
- if(condition!=null) {
- condition = ConditionalUtils.normalizeTemplateResult(condition);
- }
- break;
-
- case FREEMARKER_TEMPLATE:
- if(patternSelettore.length()<50) {
- pattern = " ("+patternSelettore+")";
- }
- else {
- pattern = "";
- }
- msgDiag.addKeyword(CostantiPdD.KEY_PATTERN_SELETTORE, pattern);
- dynamicMap = new HashMap<>();
- errorHandler = new ErrorHandler();
- DynamicUtils.fillDynamicMapRequest(log, dynamicMap, pddContext, urlInvocazione,
- message,
- messageContent,
- busta,
- pTrasporto,
- pQuery,
- pForm,
- errorHandler);
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- ConfigurazionePdDManager configurazionePdDManager = ConfigurazionePdDManager.getInstance(state);
- IDPortaApplicativa idPA = new IDPortaApplicativa();
- idPA.setNome(pa.getNome());
- Template template = configurazionePdDManager.getTemplateConnettoreMultiploSticky(idPA, patternSelettore.getBytes(), requestInfo);
- DynamicUtils.convertFreeMarkerTemplate(template, dynamicMap, bout);
- bout.flush();
- bout.close();
- condition = bout.toString();
- if(condition!=null) {
- condition = ConditionalUtils.normalizeTemplateResult(condition);
- }
- break;
-
- case VELOCITY_TEMPLATE:
- if(patternSelettore.length()<50) {
- pattern = " ("+patternSelettore+")";
- }
- else {
- pattern = "";
- }
- msgDiag.addKeyword(CostantiPdD.KEY_PATTERN_SELETTORE, pattern);
- dynamicMap = new HashMap<>();
- errorHandler = new ErrorHandler();
- DynamicUtils.fillDynamicMapRequest(log, dynamicMap, pddContext, urlInvocazione,
- message,
- messageContent,
- busta,
- pTrasporto,
- pQuery,
- pForm,
- errorHandler);
- bout = new ByteArrayOutputStream();
- configurazionePdDManager = ConfigurazionePdDManager.getInstance(state);
- idPA = new IDPortaApplicativa();
- idPA.setNome(pa.getNome());
- template = configurazionePdDManager.getTemplateConnettoreMultiploSticky(idPA, patternSelettore.getBytes(), requestInfo);
- DynamicUtils.convertVelocityTemplate(template, dynamicMap, bout);
- bout.flush();
- bout.close();
- condition = bout.toString();
- if(condition!=null) {
- condition = ConditionalUtils.normalizeTemplateResult(condition);
- }
- break;
- }
-
- if(condition==null || "".equals(condition)) {
- throw new Exception("Nessuna condizione estratta");
- }
- else {
- result.setCondition(condition);
- result.setFound(true);
-
- msgDiag.addKeyword(CostantiPdD.KEY_CONDIZIONE_STICKY, condition);
-
- msgDiag.logPersonalizzato(MsgDiagnosticiProperties.MSG_DIAG_CONSEGNA_CONTENUTI_APPLICATIVI,
- "connettoriMultipli.loadBalancer.sticky.identificazioneRiuscita");
-
- }
-
- }catch(Exception e) {
-
- msgDiag.addKeyword(CostantiPdD.KEY_ERRORE_PROCESSAMENTO, e.getMessage());
-
- msgDiag.logPersonalizzato(MsgDiagnosticiProperties.MSG_DIAG_CONSEGNA_CONTENUTI_APPLICATIVI,
- "connettoriMultipli.loadBalancer.sticky.identificazioneFallita");
- }
-
-
- if(result.isFound()) {
- if(config.getMaxAgeSeconds()!=null) {
- if(result.getMaxAgeSeconds()==null) {
- result.setMaxAgeSeconds(config.getMaxAgeSeconds());
- }
- }
- }
-
- return result;
- }
-
-
- public static boolean isConfigurazioneSticky(PortaApplicativa pa, Logger log) {
- if(pa.getBehaviour()==null || pa.getBehaviour().sizeProprietaList()<=0) {
- return false;
- }
- String type = null;
- for (Proprieta p : pa.getBehaviour().getProprietaList()) {
- if(StickyCostanti.STICKY.equals(p.getNome())) {
- type = p.getValore();
- break;
- }
- }
- if(type==null) {
- return false;
- }
- return "true".equals(type);
- }
-
- public static StickyConfigurazione read(PortaApplicativa pa, Logger log) throws BehaviourException {
- StickyConfigurazione config = new StickyConfigurazione();
- if(pa.getBehaviour()==null || pa.getBehaviour().sizeProprietaList()<=0) {
- throw new BehaviourException("Configurazione sticky non disponibile");
- }
-
- for (Proprieta p : pa.getBehaviour().getProprietaList()) {
-
- String nome = p.getNome();
- String valore = p.getValore().trim();
-
- try {
- if(StickyCostanti.STICKY.equals(nome)) {
- config.setStickyEnabled("true".equals(valore));
- }
- else if(StickyCostanti.STICKY_TIPO_SELETTORE.equals(nome)) {
- config.setTipoSelettore(StickyTipoSelettore.toEnumConstant(valore, true));
- }
- else if(StickyCostanti.STICKY_PATTERN.equals(nome)) {
- config.setPattern(valore);
- }
- else if(StickyCostanti.STICKY_EXPIRE.equals(nome)) {
- config.setMaxAgeSeconds(Integer.valueOf(valore));
- }
- }catch(Exception e) {
- throw new BehaviourException("Configurazione sticky non corretta (proprietà:"+p.getNome()+" valore:'"+p.getValore()+"'): "+e.getMessage(),e);
- }
-
- }
- return config;
- }
-
- public static void save(PortaApplicativa pa, StickyConfigurazione configurazione) throws BehaviourException {
-
- if(pa.getBehaviour()==null) {
- throw new BehaviourException("Configurazione behaviour non abilitata");
- }
- if(configurazione==null) {
- throw new BehaviourException("Configurazione condizionale non fornita");
- }
- BehaviourPropertiesUtils.addProprieta(pa.getBehaviour(),StickyCostanti.STICKY, configurazione.isStickyEnabled()+"");
-
- BehaviourPropertiesUtils.removeProprieta(pa.getBehaviour(),StickyCostanti.STICKY_TIPO_SELETTORE);
- BehaviourPropertiesUtils.removeProprieta(pa.getBehaviour(),StickyCostanti.STICKY_PATTERN);
- BehaviourPropertiesUtils.removeProprieta(pa.getBehaviour(),StickyCostanti.STICKY_EXPIRE);
-
- if(configurazione.isStickyEnabled()) {
- if(configurazione.getTipoSelettore()!=null) {
- BehaviourPropertiesUtils.addProprieta(pa.getBehaviour(),StickyCostanti.STICKY_TIPO_SELETTORE, configurazione.getTipoSelettore().getValue());
- }
-
- if(StringUtils.isNotEmpty(configurazione.getPattern())) {
- BehaviourPropertiesUtils.addProprieta(pa.getBehaviour(),StickyCostanti.STICKY_PATTERN, configurazione.getPattern());
- }
-
- if(configurazione.getMaxAgeSeconds()!=null && configurazione.getMaxAgeSeconds().intValue()>0) {
- BehaviourPropertiesUtils.addProprieta(pa.getBehaviour(),StickyCostanti.STICKY_EXPIRE, configurazione.getMaxAgeSeconds().intValue()+"");
- }
- }
-
- }
-
- }