Добавлен модуль http

This commit is contained in:
Victor 2016-01-12 21:14:05 +02:00
parent 89d48f7737
commit 28c7b38025
11 changed files with 241 additions and 1 deletions

BIN
libs/commons-codec-1.6.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
libs/httpclient-4.3.5.jar Normal file

Binary file not shown.

BIN
libs/httpcore-4.3.2.jar Normal file

Binary file not shown.

View File

@ -124,4 +124,15 @@ nums = [1,2,3,4,5,6,7,8,9,10]
nums = filter(nums, def(x) = x % 2 == 0) nums = filter(nums, def(x) = x % 2 == 0)
squares = map(nums, def(x) = x * x) squares = map(nums, def(x) = x * x)
foreach(squares, ::echo) foreach(squares, ::echo)
println "Sum: " + reduce(squares, 0, def(x, y) = x + y) println "Sum: " + reduce(squares, 0, def(x, y) = x + y)
use "http"
http("http://jsonplaceholder.typicode.com/users", "POST", {"name": "OwnLang", "versionCode": 10}, def(v) {
println "Added: " + v
http("http://jsonplaceholder.typicode.com/users/2", "PATCH", {"name": "Patched Name"}, ::http_get_demo)
})
def http_get_demo(v) {
println "Updated: " + v
http("http://jsonplaceholder.typicode.com/users", ::echo)
}

View File

@ -7,6 +7,8 @@ import java.util.Objects;
* @author aNNiMON * @author aNNiMON
*/ */
public final class FunctionValue implements Value { public final class FunctionValue implements Value {
public static final FunctionValue EMPTY = new FunctionValue(args -> NumberValue.ZERO);
private final Function value; private final Function value;

View File

@ -11,6 +11,8 @@ import java.util.Objects;
*/ */
public class MapValue implements Value, Iterable<Map.Entry<Value, Value>> { public class MapValue implements Value, Iterable<Map.Entry<Value, Value>> {
public static final MapValue EMPTY = new MapValue(1);
private final Map<Value, Value> map; private final Map<Value, Value> map;
public MapValue(int size) { public MapValue(int size) {
@ -29,6 +31,10 @@ public class MapValue implements Value, Iterable<Map.Entry<Value, Value>> {
public int size() { public int size() {
return map.size(); return map.size();
} }
public boolean containsKey(Value key) {
return map.containsKey(key);
}
public Value get(Value key) { public Value get(Value key) {
return map.get(key); return map.get(key);

View File

@ -14,6 +14,10 @@ public final class StringValue implements Value {
this.value = value; this.value = value;
} }
public int length() {
return value.length();
}
@Override @Override
public int type() { public int type() {
return Types.STRING; return Types.STRING;

View File

@ -0,0 +1,173 @@
package com.annimon.ownlang.lib.modules.functions;
import com.annimon.ownlang.lib.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
public final class http_http implements Function {
private static final Value
HEADER_KEY = new StringValue("header"),
CHARSET_KEY = new StringValue("charset");
@Override
public Value execute(Value... args) {
String url, method;
switch (args.length) {
case 1: // http(url)
url = args[0].asString();
return process(url, "GET");
case 2: // http(url, method) || http(url, callback)
url = args[0].asString();
if (args[1].type() == Types.FUNCTION) {
return process(url, "GET", (FunctionValue) args[1]);
}
return process(url, args[1].asString());
case 3: // http(url, method, params) || http(url, method, callback)
url = args[0].asString();
method = args[1].asString();
if (args[2].type() == Types.FUNCTION) {
return process(url, method, (FunctionValue) args[2]);
}
return process(url, method, args[2], FunctionValue.EMPTY);
case 4: // http(url, method, params, callback)
if (args[3].type() != Types.FUNCTION) {
throw new RuntimeException("Fourth arg must be a function callback");
}
url = args[0].asString();
method = args[1].asString();
return process(url, method, args[2], (FunctionValue) args[3]);
case 5: // http(url, method, params, headerParams, callback)
if (args[3].type() != Types.MAP) {
throw new RuntimeException("Third arg must be a map");
}
if (args[4].type() != Types.FUNCTION) {
throw new RuntimeException("Fifth arg must be a function callback");
}
url = args[0].asString();
method = args[1].asString();
return process(url, method, args[2], (MapValue) args[3], (FunctionValue) args[4]);
default:
throw new RuntimeException("Wrong number of arguments");
}
}
private Value process(String url, String method) {
return process(url, method, FunctionValue.EMPTY);
}
private Value process(String url, String method, FunctionValue function) {
return process(url, method, MapValue.EMPTY, function);
}
private Value process(String url, String method, Value params, FunctionValue function) {
return process(url, method, params, MapValue.EMPTY, function);
}
private Value process(String url, String method, Value requestParams, MapValue options, FunctionValue function) {
final Function callback = function.getValue();
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
HttpRequestBase httpMethod;
switch (method.toUpperCase()) {
case "POST":
httpMethod = new HttpPost(url);
break;
case "PUT":
httpMethod = new HttpPut(url);
break;
case "DELETE":
httpMethod = new HttpDelete(url);
break;
case "PATCH":
httpMethod = new HttpPatch(url);
break;
case "HEAD":
httpMethod = new HttpHead(url);
break;
case "OPTIONS":
httpMethod = new HttpOptions(url);
break;
case "TRACE":
httpMethod = new HttpTrace(url);
break;
case "GET":
default:
httpMethod = new HttpGet(url);
break;
}
if (options.containsKey(HEADER_KEY)) {
applyHeaderParams((MapValue) options.get(HEADER_KEY), httpMethod);
}
if (httpMethod instanceof HttpEntityEnclosingRequestBase) {
final HttpEntityEnclosingRequestBase heerb = (HttpEntityEnclosingRequestBase) httpMethod;
if (requestParams.type() == Types.MAP) {
applyMapRequestParams(heerb, (MapValue) requestParams, options);
} else {
applyStringRequestParams(heerb, requestParams, options);
}
}
final HttpResponse httpResponse = httpClient.execute(httpMethod);
final String response = new BasicResponseHandler().handleResponse(httpResponse);
callback.execute(new StringValue(response));
return NumberValue.fromBoolean(true);
} catch (IOException ex) {
return NumberValue.fromBoolean(false);
}
}
private void applyHeaderParams(MapValue headerParams, HttpRequestBase httpMethod) {
for (Map.Entry<Value, Value> p : headerParams) {
httpMethod.addHeader(p.getKey().asString(), p.getValue().asString());
}
}
private void applyMapRequestParams(HttpEntityEnclosingRequestBase h, MapValue params, MapValue options)
throws UnsupportedEncodingException {
final List<NameValuePair> entityParams = new ArrayList<>(params.size());
for (Map.Entry<Value, Value> param : params) {
final String name = param.getKey().asString();
final String value = param.getValue().asString();
entityParams.add(new BasicNameValuePair(name, value));
}
HttpEntity entity;
if (options.containsKey(CHARSET_KEY)) {
entity = new UrlEncodedFormEntity(entityParams, options.get(CHARSET_KEY).asString());
} else {
entity = new UrlEncodedFormEntity(entityParams);
}
h.setEntity(entity);
}
private void applyStringRequestParams(final HttpEntityEnclosingRequestBase heerb, Value requestParams, MapValue options) throws UnsupportedEncodingException, UnsupportedCharsetException {
HttpEntity entity;
if (options.containsKey(CHARSET_KEY)) {
entity = new StringEntity(requestParams.asString(), options.get(CHARSET_KEY).asString());
} else {
entity = new StringEntity(requestParams.asString());
}
heerb.setEntity(entity);
}
}

View File

@ -0,0 +1,27 @@
package com.annimon.ownlang.lib.modules.functions;
import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
import java.io.IOException;
import java.net.URLEncoder;
public final class http_urlencode implements Function {
@Override
public Value execute(Value... args) {
if (args.length == 0) throw new RuntimeException("At least one arg expected");
String charset = "UTF-8";
if (args.length >= 2) {
charset = args[1].asString();
}
try {
final String result = URLEncoder.encode(args[0].asString(), charset);
return new StringValue(result);
} catch (IOException ex) {
return args[0];
}
}
}

View File

@ -0,0 +1,17 @@
package com.annimon.ownlang.lib.modules;
import com.annimon.ownlang.lib.*;
import com.annimon.ownlang.lib.modules.functions.*;
/**
*
* @author aNNiMON
*/
public final class http implements Module {
@Override
public void init() {
Functions.set("urlencode", new http_urlencode());
Functions.set("http", new http_http());
}
}