ZEPPELIN-2443

This commit is contained in:
dlukyanov 2017-04-26 09:38:05 +03:00
parent 6eecdecb5d
commit 4baa22e2b4
2 changed files with 136 additions and 24 deletions

View file

@ -39,7 +39,8 @@ def r = HTTP.get(
headers: [
'Accept':'application/json',
//'Authorization:' : g.getProperty('search_auth'),
]
],
ssl : g.getProperty('search_ssl') // assume groovy interpreter property search_ssl = HTTP.getNaiveSSLContext()
)
//check response code
if( r.response.code==200 ) {
@ -76,41 +77,62 @@ g.table(
* `g.angular(String name)`
Returns angular object by name. Look up notebook scope first and then global scope.
Returns angular object by name. Look up notebook scope first and then global scope.
* `g.angularBind(String name, Object value)`
Assign a new `value` into angular object `name`
Assign a new `value` into angular object `name`
* `java.util.Properties g.getProperties()`
returns all properties defined for this interpreter
returns all properties defined for this interpreter
* `String g.getProperty('PROPERTY_NAME')`
```groovy
g.PROPERTY_NAME
g.'PROPERTY_NAME'
g['PROPERTY_NAME']
g.getProperties().getProperty('PROPERTY_NAME')
```
```groovy
g.PROPERTY_NAME
g.'PROPERTY_NAME'
g['PROPERTY_NAME']
g.getProperties().getProperty('PROPERTY_NAME')
```
All above the accessor to named property defined in groovy interpreter.
In this case with name `PROPERTY_NAME`
All above the accessor to named property defined in groovy interpreter.
In this case with name `PROPERTY_NAME`
* `groovy.xml.MarkupBuilder g.html()`
Starts or continues rendering of `%angular` to output and returns [groovy.xml.MarkupBuilder](http://groovy-lang.org/processing-xml.html#_markupbuilder)
MarkupBuilder is usefull to generate html (xml)
Starts or continues rendering of `%angular` to output and returns [groovy.xml.MarkupBuilder](http://groovy-lang.org/processing-xml.html#_markupbuilder)
MarkupBuilder is usefull to generate html (xml)
* `void g.table(obj)`
starts or continues rendering table rows.
starts or continues rendering table rows.
obj: List(rows) of List(columns) where first line is a header
obj: List(rows) of List(columns) where first line is a header
* `g.input(name, value )`
Creates `text` input with value specified. The parameter `value` is optional.
* `g.select(name, default, Map<Object, String> options)`
Creates `select` input with defined options. The parameter `default` is optional.
```g.select('sex', 'm', ['m':'man', 'w':'woman'])```
* `g.checkbox(name, Collection checked, Map<Object, String> options)`
Creates `checkbox` input.
* `g.get(name, default)`
Returns interpreter-based variable. Visibility depends on interpreter scope. The parameter `default` is optional.
* `g.put(name, value)`
Stores new value into interpreter-based variable. Visibility depends on interpreter scope.

View file

@ -17,6 +17,16 @@
import groovy.json.JsonOutput
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import java.security.SecureRandom;
import javax.net.ssl.HttpsURLConnection;
/**
* simple http rest client for groovy
* by dlukyanov@ukr.net
@ -44,6 +54,11 @@ public class HTTP{
return send(ctx);
}
public static Map<String,Object> head(Map<String,Object> ctx)throws IOException{
ctx.put('method','HEAD');
return send(ctx);
}
public static Map<String,Object> post(Map<String,Object> ctx)throws IOException{
ctx.put('method','POST');
return send(ctx);
@ -59,6 +74,16 @@ public class HTTP{
return send(ctx);
}
/**
* @param url string where to send request
* @param query Map parameters to append to url
* @param method http method to be used in request. standard methods: GET, POST, PUT, DELETE, HEAD
* @param headers key-value map with headers that should be sent with request
* @param body request body/data to send to url (InputStream, CharSequence, or Map for json and x-www-form-urlencoded context types)
* @param encoding encoding name to use to send/receive data - default UTF-8
* @param receiver Closure that will be called to receive data from server. Defaults: `HTTP.JSON_RECEIVER` for json content-type and `HTTP.TEXT_RECEIVER` otherwise. Available: `HTTP.FILE_RECEIVER(File)` - stores response to file.
* @param ssl javax.net.ssl.SSLContext or String that evaluates the javax.net.ssl.SSLContext. example: send( url:..., ssl: "HTTP.getKeystoreSSLContext('./keystore.jks', 'testpass')" )
*/
public static Map<String,Object> send(Map<String,Object> ctx)throws IOException{
String url = ctx.url;
Map<String,String> headers = (Map<String,String>)ctx.headers;
@ -67,6 +92,7 @@ public class HTTP{
String encoding = ctx.encoding?:"UTF-8";
Closure receiver = (Closure)ctx.receiver;
Map<String,String> query = (Map<String,String>)ctx.query;
Object sslCtxObj= ctx.ssl;
//copy context and set default values
ctx = [:] + ctx;
@ -78,14 +104,28 @@ public class HTTP{
}
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
if(sslCtxObj!=null && connection instanceof HttpsURLConnection){
SSLContext sslCtx = null;
if(sslCtxObj instanceof SSLContext){
sslCtx = (SSLContext)sslCtxObj;
}else if(sslCtxObj instanceof CharSequence){
//assume this is a groovy code to get ssl context
sslCtx = evaluateSSLContext((CharSequence)sslCtxObj);
}else{
throw new IllegalArgumentException("Unsupported ssl parameter ${sslCtxObj.getClass()}")
}
((HttpsURLConnection)connection).setSSLSocketFactory(sslCtx.getSocketFactory());
}
connection.setDoOutput(true);
connection.setRequestMethod(method);
if ( headers!=null && !headers.isEmpty() ) {
//add headers
for (Map.Entry<String, String> entry : headers.entrySet()) {
connection.addRequestProperty(entry.getKey(), entry.getValue());
if("content-type".equals(entry.getKey().toLowerCase()))contentType=entry.getValue();
if(entry.getValue()){
connection.addRequestProperty(entry.getKey(), entry.getValue());
if("content-type".equals(entry.getKey().toLowerCase()))contentType=entry.getValue();
}
}
}
@ -97,18 +137,20 @@ public class HTTP{
}else if(body instanceof InputStream){
out << (InputStream)body;
}else if(body instanceof Map){
if( contentType.matches("(?i)[^/]+/json") ){
if( contentType =~ "(?i)[^/]+/json" ) {
out.withWriter((String)ctx.encoding){
it.append( JsonOutput.toJson((Map)body) );
it.flush();
}
}else{
throw new IOException("Map body type supported only for */json content-type");
} else if( contentType =~ "(?i)[^/]+/x-www-form-urlencoded" ) {
out.withWriter((String)ctx.encoding) {
it.append( ((Map)body).collect{k,v-> ""+k+"="+URLEncoder.encode((String)v,'UTF-8') }.join('&') )
}
} else {
throw new IOException("Map body type supported only for */json of */x-www-form-urlencoded content-type");
}
}else if(body instanceof CharSequence){
out.withWriter((String)ctx.encoding){
it.append((CharSequence)body);
it.flush();
}
}else{
throw new IOException("Unsupported body type: "+body.getClass());
@ -151,4 +193,52 @@ public class HTTP{
}
return ctx;
}
@groovy.transform.Memoized
public static SSLContext getKeystoreSSLContext(String keystorePath, String keystorePass, String keystoreType="JKS", String keyPass = null){
if(keyPass == null) keyPass=keystorePass;
KeyStore clientStore = KeyStore.getInstance(keystoreType);
clientStore.load(new File( keystorePath ).newInputStream(), keystorePass.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientStore, keyPass.toCharArray());
KeyManager[] kms = kmf.getKeyManagers();
//init TrustCerts
TrustManager[] trustCerts = new TrustManager[1];
trustCerts[0] = new X509TrustManager() {
public void checkClientTrusted( final X509Certificate[] chain, final String authType ) { }
public void checkServerTrusted( final X509Certificate[] chain, final String authType ) { }
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kms, trustCerts, new SecureRandom());
return sslContext;
}
@groovy.transform.Memoized
public static SSLContext getNaiveSSLContext(){
System.err.println("HTTP.getNaiveSSLContext() used. Must be disabled on prod!");
KeyManager[] kms = new KeyManager[0];
TrustManager[] trustCerts = new TrustManager[1];
trustCerts[0] = new X509TrustManager() {
public void checkClientTrusted( final X509Certificate[] chain, final String authType ) { }
public void checkServerTrusted( final X509Certificate[] chain, final String authType ) { }
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustCerts, new SecureRandom());
return sslContext;
}
/**
* evaluates code that should return SSLContext
*/
@groovy.transform.Memoized
public static SSLContext evaluateSSLContext(CharSequence code) {
Object ssl = new GroovyShell( HTTP.class.getClassLoader() ).evaluate( code as String );
return (SSLContext) ssl;
}
}