Skip to content
Permalink
Browse files

Add insecure mode to web:get and web:post, return status code, status…

… line
  • Loading branch information...
birchb1024 committed Apr 27, 2019
1 parent 8351055 commit 4ed262bae04f0dd0c1cbc12b03c52519969f35b8
@@ -9120,11 +9120,11 @@ Output:
\end_layout

\begin_layout Standard
~ '{"ip":"192.168.238.37"}'
~ '{"ip":"192.168.38.37"}'
\end_layout

\begin_layout Standard
~ '192.168.238.37'
~ '192.168.38.37'
\end_layout

\begin_layout Subsection
@@ -14866,7 +14866,7 @@ web:get


\emph default
<url> [<request headers> [<protocol version>]]
<url> [<request headers> [<protocol version> [^insecure]]]
\end_layout

\begin_layout Standard
@@ -14876,7 +14876,19 @@ web:get
\emph default
function.
This takes as input a URL string and an optional list of request headers.
The HTTP protocol can be specified as either '1.0' or '1.1' (default).
The HTTP protocol can be specified as either
\emph on
nil
\emph default
,
\emph on
'1.0'
\emph default
or
\emph on
'1.1'
\emph default
(default).
It sends the GET request to web server then returns a list containing the
response content in a
\emph on
@@ -14907,9 +14919,7 @@ Reader
\end_layout

\begin_layout Standard
The response must have the 200 'OK' status code otherwise an exception is
raised.
Example, fetching the root file from the localhost server on port 80, using
Example, fetching the root file from the localhost server on port 80, using
HTTP/1.0 and providing a 'Basic' authentication header.
\end_layout

@@ -14942,7 +14952,7 @@ web:post


\emph default
<url> [<params assoc>] [<request headers> [<protocol version>]]
<url> [<params assoc>] [<request headers> [<protocol version> [^insecure]]]
\end_layout

\begin_layout Standard
@@ -14984,9 +14994,7 @@ Reader
\end_layout

\begin_layout Standard
The response must have the 200 'OK' status code otherwise an exception is
raised.
For example, to send a HTTP/1.1 POST with two parameters, a basic auth login,
For example, to send a HTTP/1.1 POST with two parameters, a basic auth login,
and read the response to a string:
\end_layout

@@ -15034,6 +15042,89 @@ The response must have the 200 'OK' status code otherwise an exception is
.readAll
\end_layout

\begin_layout Subsubsection
Handling Responses
\end_layout

\begin_layout Standard
The web functions return a list of the following items:
\end_layout

\begin_layout Itemize
A Reader object wrapping the returned data,
\end_layout

\begin_layout Itemize
A Assoc list with HTTP response headers,
\end_layout

\begin_layout Itemize
A list containing the status code then the status line text string - usually

\emph on
(200 'OK')
\emph default

\end_layout

\begin_layout Standard
For example:
\end_layout

\begin_layout LyX-Code
[Exp: org.genyris.io.ReaderInStream@dd8ba08]
\end_layout

\begin_layout LyX-Code
(('Date' = 'Sat, 27 Apr 2019 09:44:10 GMT')
\end_layout

\begin_layout LyX-Code
('Server' = 'Apache/2.4.25 (Debian)')
\end_layout

\begin_layout LyX-Code
('Vary' = 'Accept-Encoding')
\end_layout

\begin_layout LyX-Code
('Keep-Alive' = 'timeout=5, max=100')
\end_layout

\begin_layout LyX-Code
('Connection' = 'Keep-Alive')
\end_layout

\begin_layout LyX-Code
('Content-Type' = 'text/html;charset=UTF-8'))
\end_layout

\begin_layout LyX-Code
200 'OK'
\end_layout

\begin_layout Subsubsection
Disabling SSL Security
\end_layout

\begin_layout Standard
If the optional
\emph on
insecure
\emph default
symbol is given as the last argument of these two functions, they ignore
HTTPS (SSL) issues which would normally generate an error.
SSL issues ignored include: Expired server certificates, self-signed certificat
es, mismatched hostname, revoked certificates, untrusted root CA and many
others.

\emph on
This mode is useful for testing but should not be used for real data.

\emph default

\end_layout

\begin_layout Section
Programming in the Large
\end_layout
@@ -4,19 +4,22 @@
@prefix u "http://www.genyris.org/lang/utilities#"
@prefix web "http://www.genyris.org/lang/web#"

var response (left (web:get 'https://api.ipify.org/?format=json'))
var theJSON (response(.readAll))
print theJSON
print (theJSON(.fromJSON))!ip
def get-response-body(url)
var response (web:get url)
assert response
assert (equal? 200 ((nth 2 response)(.left)))
response
.left
.readAll

var theJSON (get-response-body 'https://api.ipify.org/?format=json')
u:format "My IP is %a\n" (theJSON(.fromJSON))!ip

var response (left (web:get 'https://api.squiggle.com.au/?q=games;year=2018;complete=100'))
var decode (response(.readAll))
var decode (get-response-body 'https://api.squiggle.com.au/?q=games;year=2018;complete=100')
for game in ((decode(.fromJSON)).games)
u:format "%a %a winner: %a %a %a\n" game!venue game!round game!winner game!ateam game!hteam

# http://www.bom.gov.au/fwo/IDV60901/IDV60901.95936.json
var response (left (web:get 'http://www.bom.gov.au/fwo/IDV60901/IDV60901.95936.json'))
var decode (response(.readAll))
var decode (get-response-body 'http://www.bom.gov.au/fwo/IDV60901/IDV60901.95936.json')
for location in (((decode(.fromJSON)).observations).data)
u:format "%a %a\n" location!local_date_time (scale (location!air_temp) 2)

@@ -120,4 +120,24 @@ protected void checkFormalArgumentSyntax(Exp formals) throws GenyrisException {
}
}

public Exp getArg(Exp[] arguments, int index, Class klass, boolean mandatory) throws GenyrisException {
Exp retval = NIL;
if( arguments.length <= index ) {
if (mandatory) {
throw new GenyrisException("Missing argument " + klass + " at arg " + index);
}
}
else {
retval = arguments[index];
if( ! klass.isInstance(retval) ) {
throw new GenyrisException("Expecting type " + klass + " at arg " + index);
}
}
return retval;
}

public Exp getArg(Exp[] arguments, int index, Class klass) throws GenyrisException {
return getArg(arguments, index, klass, false);
}

}
@@ -2,13 +2,25 @@

import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpMessage;
import org.apache.http.HttpVersion;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.genyris.core.Bignum;
import org.genyris.core.Exp;
import org.genyris.core.Pair;
import org.genyris.core.StrinG;
@@ -29,6 +41,32 @@ public HTTPclientFunction(Interpreter interp, String name, boolean eager) {
super(interp, name, eager);
}

protected static CloseableHttpClient getCloseableHttpClient(Exp options) {
CloseableHttpClient httpclient = HttpClients.createDefault();

if (options.toString().equals("insecure")) {
// https://stackoverflow.com/questions/19517538/ignoring-ssl-certificate-in-apache-httpclient-4-3
try {
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
return true;
}
});
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
}
return httpclient;
}

public abstract Exp bindAndExecute(Closure proc, Exp[] arguments, Environment envForBindOperations)
throws GenyrisException;

@@ -43,8 +81,10 @@ protected Exp processResponse(String URI, CloseableHttpResponse response) throws
new StrinG(responseHeaders[i].getName()), new StrinG(
responseHeaders[i].getValue())), headerList);
}
return Pair.cons2(new ReaderStream( new InputStreamReader(entity.getContent()), URI),
headerList, NIL);

return Pair.cons3(new ReaderStream( new InputStreamReader(entity.getContent()), URI),
headerList, Pair.cons2(new Bignum(response.getStatusLine().getStatusCode()),
new StrinG(response.getStatusLine().getReasonPhrase()),NIL), NIL);
} finally {
response.close();
}
@@ -63,9 +103,11 @@ protected void addHeadersToRequest(Exp headers, String charset, HttpMessage http
}

protected HttpVersion parseProtocol(Exp protocol) {
String protocolstring = protocol.toString();
HttpVersion httpVersion = HttpVersion.HTTP_1_1;
if ( protocolstring.equals("1.0") ) {
if( protocol == NIL )
return httpVersion;

if ( protocol.toString().equals("1.0") ) {
httpVersion = HttpVersion.HTTP_1_0;
}
return httpVersion;
@@ -11,10 +11,8 @@
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.genyris.core.Constants;
import org.genyris.core.Exp;
import org.genyris.core.StrinG;

import org.genyris.core.*;
import org.genyris.exception.GenyrisException;
import org.genyris.interp.Closure;
import org.genyris.interp.Environment;
@@ -26,23 +24,17 @@ public HTTPgetFunction(Interpreter interp) {
super(interp, Constants.WEB + "get", true);
}


public Exp bindAndExecute(Closure proc, Exp[] arguments,
Environment envForBindOperations) throws GenyrisException {
checkArguments(arguments, 1, 3);
Class[] types = {StrinG.class};
checkArgumentTypes(types, arguments);
String URI = arguments[0].toString();
Exp headers = (arguments.length >= 2 ? arguments[1] : NIL);
if( ! (headers == NIL || headers instanceof org.genyris.core.Pair) ) {
throw new GenyrisException("Headers must be a list.");
}
Exp protocol = (arguments.length >= 3 ? arguments[2] : NIL);
if( ! (protocol == NIL || protocol instanceof org.genyris.core.StrinG) ) {
throw new GenyrisException("Protocol must be a String.");
}
HttpVersion httpVersion = parseProtocol(protocol);

CloseableHttpClient httpclient = HttpClients.createDefault();
String URI = getArg(arguments, 0, StrinG.class, true).toString();
Exp headers = getArg(arguments, 1, Exp.class);
Exp protocol = getArg(arguments, 2, Exp.class);
Exp options = getArg(arguments, 3, Symbol.class);

CloseableHttpClient httpclient = getCloseableHttpClient(options);
HttpVersion httpVersion = parseProtocol(protocol);

try {

@@ -68,4 +60,5 @@ public Exp bindAndExecute(Closure proc, Exp[] arguments,
}

}

}
@@ -20,6 +20,7 @@
import org.genyris.core.Constants;
import org.genyris.core.Exp;
import org.genyris.core.StrinG;
import org.genyris.core.Symbol;
import org.genyris.exception.GenyrisException;
import org.genyris.interp.Closure;
import org.genyris.interp.Environment;
@@ -35,21 +36,14 @@ public HTTPpostFunction(Interpreter interp) {
public Exp bindAndExecute(Closure proc, Exp[] arguments,
Environment envForBindOperations) throws GenyrisException {

checkArguments(arguments, 1, 4);
Class[] types = { StrinG.class };
checkArgumentTypes(types, arguments);
String URI = arguments[0].toString();
Exp params = (arguments.length >= 2 ? arguments[1] : NIL);
Exp headers = (arguments.length >= 3 ? arguments[2] : NIL);
if( ! (headers == NIL || headers instanceof org.genyris.core.Pair) ) {
throw new GenyrisException("Headers must be a list.");
}
Exp protocol = (arguments.length >= 4 ? arguments[3] : NIL);
if( ! (protocol == NIL || protocol instanceof org.genyris.core.StrinG) ) {
throw new GenyrisException("Protocol must be a String.");
}
String URI = getArg(arguments, 0, StrinG.class, true).toString();
Exp params = getArg(arguments, 1, Exp.class);
Exp headers = getArg(arguments, 2, Exp.class);
Exp protocol = getArg(arguments, 3, Exp.class);
Exp options = getArg(arguments, 4, Symbol.class);

CloseableHttpClient httpclient = getCloseableHttpClient(options);
HttpVersion httpVersion = parseProtocol(protocol);
CloseableHttpClient httpclient = HttpClients.createDefault();

try {

0 comments on commit 4ed262b

Please sign in to comment.
You can’t perform that action at this time.