Mercurial Hosting > luan
changeset 722:647602e8291a
add url options
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 03 Jun 2016 17:51:58 -0600 |
parents | 524ea0056573 |
children | eaf30d5aaf6a |
files | core/src/luan/modules/IoLuan.java core/src/luan/modules/LuanUrl.java core/src/luan/modules/PackageLuan.java core/src/luan/modules/Parsers.luan |
diffstat | 4 files changed, 244 insertions(+), 60 deletions(-) [+] |
line wrap: on
line diff
--- a/core/src/luan/modules/IoLuan.java Tue May 31 19:31:28 2016 -0600 +++ b/core/src/luan/modules/IoLuan.java Fri Jun 03 17:51:58 2016 -0600 @@ -27,8 +27,6 @@ import java.net.InetAddress; import java.net.MalformedURLException; import java.net.UnknownHostException; -import java.util.List; -import java.util.ArrayList; import java.util.Map; import java.util.zip.ZipOutputStream; import java.util.zip.ZipEntry; @@ -169,38 +167,38 @@ public static abstract class LuanIn { - abstract InputStream inputStream() throws IOException; + abstract InputStream inputStream() throws IOException, LuanException; public abstract String to_string(); public abstract String to_uri_string(); - public Reader reader() throws IOException { + public Reader reader() throws IOException, LuanException { return new InputStreamReader(inputStream()); } - public String read_text() throws IOException { + public String read_text() throws IOException, LuanException { Reader in = reader(); String s = Utils.readAll(in); in.close(); return s; } - public byte[] read_binary() throws IOException { + public byte[] read_binary() throws IOException, LuanException { InputStream in = inputStream(); byte[] a = Utils.readAll(in); in.close(); return a; } - public LuanFunction read_lines() throws IOException { + public LuanFunction read_lines() throws IOException, LuanException { return lines(new BufferedReader(reader())); } - public LuanFunction read_blocks(Integer blockSize) throws IOException { + public LuanFunction read_blocks(Integer blockSize) throws IOException, LuanException { int n = blockSize!=null ? blockSize : Utils.bufSize; return blocks(inputStream(),n); } - public boolean exists() throws IOException { + public boolean exists() throws IOException, LuanException { try { inputStream().close(); return true; @@ -397,42 +395,6 @@ } } - public static final class LuanUrl extends LuanIn { - private final URL url; - - private LuanUrl(URL url) { - this.url = url; - } - - @Override InputStream inputStream() throws IOException { - return url.openStream(); - } - - @Override public String to_string() { - return url.toString(); - } - - @Override public String to_uri_string() { - return url.toString(); - } - - public String post(String postS) throws IOException { - return new UrlCall(url).post(postS); - } - - @Override public LuanTable table() { - LuanTable tbl = super.table(); - try { - tbl.rawPut( "post", new LuanJavaFunction( - LuanUrl.class.getMethod( "post", String.class ), this - ) ); - } catch(NoSuchMethodException e) { - throw new RuntimeException(e); - } - return tbl; - } - } - public static final class LuanFile extends LuanIO { public final File file; @@ -581,21 +543,21 @@ } } if( url != null ) - return new LuanUrl(url).table(); + return new LuanUrl(luan,url,null).table(); return null; } - private static LuanTable url(String url) throws IOException { - return new LuanUrl(new URL(url)).table(); + private static LuanTable url(LuanState luan,String url,LuanTable options) throws IOException, LuanException { + return new LuanUrl(luan,new URL(url),options).table(); } - public static LuanTable http(String path) throws IOException { - return url("http:"+path); + public static LuanTable http(LuanState luan,String path,LuanTable options) throws IOException, LuanException { + return url(luan,"http:"+path,options); } - public static LuanTable https(String path) throws IOException { - return url("https:"+path); + public static LuanTable https(LuanState luan,String path,LuanTable options) throws IOException, LuanException { + return url(luan,"https:"+path,options); } public static LuanTable luan(LuanState luan,String path) throws LuanException { @@ -615,8 +577,8 @@ add( schemes, "file", LuanState.class, String.class ); add( schemes, "classpath", LuanState.class, String.class ); add( schemes, "socket", String.class ); - add( schemes, "http", String.class ); - add( schemes, "https", String.class ); + add( schemes, "http", LuanState.class, String.class, LuanTable.class ); + add( schemes, "https", LuanState.class, String.class, LuanTable.class ); add( schemes, "luan", LuanState.class, String.class ); add( schemes, "stdin", LuanState.class ); } catch(NoSuchMethodException e) { @@ -635,7 +597,7 @@ return t; } - public static LuanTable uri(LuanState luan,String name) throws LuanException { + public static LuanTable uri(LuanState luan,String name,LuanTable options) throws LuanException { int i = name.indexOf(':'); if( i == -1 ) throw new LuanException( "invalid Io.uri name '"+name+"', missing scheme" ); @@ -645,7 +607,7 @@ LuanFunction opener = (LuanFunction)schemes.get(luan,scheme); if( opener == null ) throw new LuanException( "invalid scheme '"+scheme+"' in '"+name+"'" ); - return (LuanTable)Luan.first(opener.call(luan,new Object[]{location})); + return (LuanTable)Luan.first(opener.call(luan,new Object[]{location,options})); } public static final class LuanSocket extends LuanIO { @@ -717,7 +679,7 @@ // files maps zip name to uri public static void zip(LuanState luan,String zipUri,LuanTable files) throws LuanException, IOException { - Object obj = uri(luan,zipUri).rawGet("java"); + Object obj = uri(luan,zipUri,null).rawGet("java"); if( !(obj instanceof LuanIO) ) throw new LuanException("invalid uri for zip"); LuanIO zipIo = (LuanIO)obj; @@ -732,7 +694,7 @@ throw new LuanException("zip file table values must be strings"); String uriStr = (String)obj; out.putNextEntry(new ZipEntry(fileName)); - obj = uri(luan,uriStr).rawGet("java"); + obj = uri(luan,uriStr,null).rawGet("java"); if( !(obj instanceof LuanIn) ) throw new LuanException("invalid uri for zip"); LuanIn zipIn = (LuanIn)obj;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/luan/modules/LuanUrl.java Fri Jun 03 17:51:58 2016 -0600 @@ -0,0 +1,222 @@ +package luan.modules; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Reader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLConnection; +import java.net.HttpURLConnection; +import java.net.URLEncoder; +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.Base64; +import luan.LuanState; +import luan.LuanTable; +import luan.LuanJavaFunction; +import luan.LuanException; + + +public final class LuanUrl extends IoLuan.LuanIn { + private static enum Method { GET, POST, DELETE } + + private URL url; + private Method method = Method.GET; + private Map headers; + private String content; + + LuanUrl(LuanState luan,URL url,LuanTable options) throws LuanException { + this.url = url; + if( options != null ) { + Map map = options.asMap(luan); + String methodStr = getString(map,"method"); + if( methodStr != null ) { + methodStr = methodStr.toUpperCase(); + try { + this.method = Method.valueOf(methodStr); + } catch(IllegalArgumentException e) { + throw new LuanException( "invalid method: "+methodStr ); + } + } + Map auth = getMap(luan,map,"authorization"); + if( auth != null ) { + String user = getString(auth,"user"); + String password = getString(auth,"password"); + if( !auth.isEmpty() ) + throw new LuanException( "unrecognized authorization options: "+auth ); + StringBuilder sb = new StringBuilder(); + if( user != null ) + sb.append(user); + sb.append(':'); + if( password != null ) + sb.append(password); + String val = "Basic " + Base64.getEncoder().encodeToString(sb.toString().getBytes()); + if( headers == null ) + headers = new HashMap(); + headers.put("Authorization",val); + } + Map params = getMap(luan,map,"parameters"); + if( params != null ) { + StringBuilder sb = new StringBuilder(); + for( Object hack : params.entrySet() ) { + Map.Entry entry = (Map.Entry)hack; + String key = (String)entry.getKey(); + Object val = entry.getValue(); + String keyEnc = encode(key); + if( val instanceof String ) { + and(sb); + sb.append( keyEnc ).append( '=' ).append( encode((String)val) ); + } else { + if( !(val instanceof LuanTable) ) + throw new LuanException( "parameter '"+key+"' must be string or table" ); + LuanTable t = (LuanTable)val; + if( !t.isList() ) + throw new LuanException( "parameter '"+key+"' table must be list" ); + for( Object obj : t.asList() ) { + if( !(obj instanceof String) ) + throw new LuanException( "parameter '"+key+"' values must be strings" ); + and(sb); + sb.append( keyEnc ).append( '=' ).append( encode((String)obj) ); + } + } + } + if( this.method==Method.DELETE ) + throw new LuanException( "the DELETE method cannot take parameters" ); + if( this.method==Method.POST ) { + content = sb.toString(); + } else { // GET + String urlS = url.toString(); + if( urlS.indexOf('?') == -1 ) { + urlS += '?'; + } else { + urlS += '&'; + } + urlS += sb; + try { + url = new URL(urlS); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + } + if( !map.isEmpty() ) + throw new LuanException( "unrecognized options: "+map ); + } + } + + private static void and(StringBuilder sb) { + if( sb.length() > 0 ) + sb.append('&'); + } + + private static String encode(String s) { + try { + return URLEncoder.encode(s,"UTF-8"); + } catch(UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + private static String getString(Map map,String key) throws LuanException { + Object val = map.remove(key); + if( val!=null && !(val instanceof String) ) + throw new LuanException( "parameter '"+key+"' must be a string" ); + return (String)val; + } + + private static LuanTable getTable(Map map,String key) throws LuanException { + Object val = map.remove(key); + if( val!=null && !(val instanceof LuanTable) ) + throw new LuanException( "parameter '"+key+"' must be a table" ); + return (LuanTable)val; + } + + private static Map getMap(LuanState luan,Map map,String key) throws LuanException { + LuanTable t = getTable(map,key); + return t==null ? null : t.asMap(luan); + } + + @Override InputStream inputStream() throws IOException, LuanException { + URLConnection con = url.openConnection(); + if( headers != null ) { + for( Object hack : headers.entrySet() ) { + Map.Entry entry = (Map.Entry)hack; + String key = (String)entry.getKey(); + Object val = entry.getValue(); + if( val instanceof String ) { + con.addRequestProperty(key,(String)val); + } else { + List list = (List)val; + for( Object obj : list ) { + con.addRequestProperty(key,(String)obj); + } + } + } + } + if( method==Method.GET ) { + return con.getInputStream(); + } + + HttpURLConnection httpCon = (HttpURLConnection)con; + + if( method==Method.DELETE ) { + httpCon.setRequestMethod("DELETE"); + return httpCon.getInputStream(); + } + + // POST + +// httpCon.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); + httpCon.setDoOutput(true); + httpCon.setRequestMethod("POST"); + + byte[] post = content.getBytes(); +// httpCon.setRequestProperty("Content-Length",Integer.toString(post.length)); + OutputStream out = httpCon.getOutputStream(); + out.write(post); + out.flush(); + try { + try { + return httpCon.getInputStream(); + } catch(IOException e) { + InputStream is = httpCon.getErrorStream(); + if( is == null ) + throw e; + Reader in = new InputStreamReader(is); + String msg = Utils.readAll(in); + in.close(); + throw new LuanException(msg,e); + } + } finally { + out.close(); + } + } + + @Override public String to_string() { + return url.toString(); + } + + @Override public String to_uri_string() { + return url.toString(); + } +/* + public String post(String postS) throws IOException { + return new UrlCall(url).post(postS); + } + + @Override public LuanTable table() { + LuanTable tbl = super.table(); + try { + tbl.rawPut( "post", new LuanJavaFunction( + LuanUrl.class.getMethod( "post", String.class ), this + ) ); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + return tbl; + } +*/ +}
--- a/core/src/luan/modules/PackageLuan.java Tue May 31 19:31:28 2016 -0600 +++ b/core/src/luan/modules/PackageLuan.java Fri Jun 03 17:51:58 2016 -0600 @@ -65,7 +65,7 @@ } static String read(LuanState luan,String uri) throws LuanException { - LuanTable t = IoLuan.uri(luan,uri); + LuanTable t = IoLuan.uri(luan,uri,null); if( t == null ) return null; LuanFunction existsFn = (LuanFunction)t.get(luan,"exists");
--- a/core/src/luan/modules/Parsers.luan Tue May 31 19:31:28 2016 -0600 +++ b/core/src/luan/modules/Parsers.luan Fri Jun 03 17:51:58 2016 -0600 @@ -9,7 +9,7 @@ M.bbcode_to_html = BBCode.toHtml M.bbcode_to_text = BBCode.toText M.csv_to_list = Csv.toList -M.parse_json = Json.parse +M.json_parse = Json.parse M.theme_to_luan = Theme.toLuan return M