Fabrizio Russo Custom Mediator per una chiamata HTTP Post


2017/01/25   Custom Mediator per una chiamata HTTP Post

Questo custom mediator implementa una chiamata ad un URL in modalita' POST passando una serie di parametri e ignorando la validita' del certificato SSL nel caso in cui la chiamata fosse in HTTPS.

Il mediator per prendere i parametri da passare al server utilizza un prefisso da usare per verificare quali, tra i parametri nel contesto attuale, e' da inviare. Quindi se il come prefisso si utilizza "xyz" allora tutti i parametri del tipo "xyzParamName" saranno inviati (con chiave "ParamName"). Il mediator prevede alcuni parametri:

  • url : URL a cui effettuare la chiamata POST
  • paramPrefix : Prefisso per cercare i parametri nel contesto
  • userAgent : (facoltativo) Lo userAgent con il quale presentarsi al server
  • output : (facoltativo) variabile da inserire nel contesto con l'output del servizio

Implementazione del mediator

L'implementazione del custom mediator e' la seguente:


public class HttpPost extends AbstractMediator {
	
	private String url = "";		// Endpoint da richiamare
	private String payload = null;	// Payload da passare (eventualmente) nel body della chiamata POST
	private String paramPrefix = "";	// Prefisso dei parametri da passare in POST
	private String output = null;			// Nome della variabile dove memorizzare l'output
	private String userAgent = null;
	
	// Mappa dove parcheggiare i parametri della POST
	private Properties httpParams = new Properties();
	
	@SuppressWarnings("unchecked")
	public boolean mediate(MessageContext mc) {
		
		log.info("Calling " + getClass().getName() + " mediator: URL=" + getUrl());
		String payload = (String) mc.getProperty(getPayload());
		Set<String> keySet = mc.getPropertyKeySet();
		for (String key : keySet) {
			if (key.startsWith(paramPrefix)) {
				String paramKey = key.substring(1 + paramPrefix.length());
				String paramVal = (String)mc.getProperty(key);
				httpParams.put(paramKey, paramVal);
				log.info(" -- Param " + paramKey + " = "  + paramVal);
			}
		}
		
		log.info(" --> Body payload: " + (payload == null ? "empty" : payload));
		
		if (httpParams.size() == 0) {
			log.warn(" -- NO PARAMETERS FOUND FOR POST REQUEST !!");
		}
		
		try {
			HttpClient httpClient = null;
			
			if (url.toLowerCase().startsWith("https")) httpClient = getHttpClient();
			else httpClient = new DefaultHttpClient();
			
			org.apache.http.client.methods.HttpPost post = new org.apache.http.client.methods.HttpPost(url);
			
			if (userAgent != null) post.setHeader("User-Agent", userAgent);
	
			List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
			for (Object pName : httpParams.keySet()) {
				String pKey = (String) pName.toString();
				urlParameters.add(new BasicNameValuePair(pKey, httpParams.getProperty(pKey)));
			}
		
		
			post.setEntity(new UrlEncodedFormEntity(urlParameters));
			HttpResponse response = httpClient.execute(post);
			HttpEntity result = response.getEntity();
			log.info("Called endpoint - status : " + response.getStatusLine());
			
			
			BufferedReader rd = new BufferedReader(new InputStreamReader(result.getContent()));

			StringBuffer res = new StringBuffer();
			String line = "";
			while ((line = rd.readLine()) != null) {
				res.append(line);
			}
			log.info(" HTTP Response : " + res.toString());
			if (output != null) {
				mc.setProperty(output, res.toString());
			}
			
			
		} catch (Exception e) {
			e.printStackTrace();
			log.error("Exception invoking POST to " + url + ": " + e.getMessage());
		}
		
		return true;
	}

	
	
	
	private HttpClient getHttpClient() throws Exception {
		SSLContextBuilder builder = SSLContexts.custom();
		builder.loadTrustMaterial(null, new TrustStrategy() {
			@Override
			public boolean isTrusted(X509Certificate[] chain, String authType)
					throws CertificateException {
				return true;
			}
		});

		SSLContext sslContext = builder.build();
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
			sslContext, new X509HostnameVerifier() {
				@Override
				public void verify(String host, SSLSocket ssl) 
					throws java.io.IOException {}

				@Override
				public void verify(String host, X509Certificate cert) 
					throws SSLException {} 

				@Override
				public void verify(String host, String[] cns, String[] subjectAlts) 
					throws SSLException {}

				@Override
				public boolean verify(String s, SSLSession sslSession) {
					return true;
				}
			});

		Registry socketFactoryRegistry = 
			RegistryBuilder. create()
			.register("https", sslsf).build();

		PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
		CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
		return httpClient;
	}
	
	public String getUrl() { return url; }
	public void setUrl(String url) { this.url = url; }
	
	public String getPayload() { return payload; }
	public void setPayload(String payload) { this.payload = payload; }

	public String getParamPrefix() { return paramPrefix; }
	public void setParamPrefix(String paramPrefix) { this.paramPrefix = paramPrefix; }
	
	public void setOutput(String output) {	this.output = output; }
	public String getOutput() {	return output; }

	
	
}

Un esempio di invocazione del mediator e' la seguente:


 
<property name="myTag.serviceName" scope="default" type="STRING" value="login"/>
<property name="myTag.userName" scope="default" type="STRING" value="frusso" />
<property name="myTag.password" scope="default" type="STRING" value="s3cret" />

<class name="it.frusso.wso2.HttpPost">
    <property name="output" value="myTagOutput" />
    <property name="paramPrefix" value="myTag." />
    <property name="url" value="http://SERVER_ENDPOINT" />
</class>

Che effettuera' l'invocazione del servizio passando in POST i parametri serviceName , userNmae e password
ed inserira' l'output della chiamata nella variabile myTagOutput (senza prefisso)