diff --git a/haxe_libraries/tink_json.hxml b/haxe_libraries/tink_json.hxml index 2e1fca2..4370bdd 100644 --- a/haxe_libraries/tink_json.hxml +++ b/haxe_libraries/tink_json.hxml @@ -1,5 +1,4 @@ -# @install: lix --silent download "gh://github.com/haxetink/tink_json#f3ca174cc9edd226c2fcdba0d4a86a3818c2a84b" into tink_json/0.8.0/github/f3ca174cc9edd226c2fcdba0d4a86a3818c2a84b --D tink_json=0.8.0 --cp ${HAXE_LIBCACHE}/tink_json/0.8.0/github/f3ca174cc9edd226c2fcdba0d4a86a3818c2a84b/src - --lib tink_typecrawler \ No newline at end of file +-D tink_json=0.9.0 +# @install: lix --silent download "gh://github.com/haxetink/tink_json#2b78279cd6a1b01f0e7a7def6f08238596a7cfc0" into tink_json/0.9.0/github/2b78279cd6a1b01f0e7a7def6f08238596a7cfc0 +-lib tink_typecrawler +-cp ${HAXE_LIBCACHE}/tink_json/0.9.0/github/2b78279cd6a1b01f0e7a7def6f08238596a7cfc0/src diff --git a/src/tink/web/macros/MimeType.hx b/src/tink/web/macros/MimeType.hx index bb249d1..405cabf 100644 --- a/src/tink/web/macros/MimeType.hx +++ b/src/tink/web/macros/MimeType.hx @@ -56,20 +56,28 @@ abstract MimeType(String) from String to String { static public var readers(default, null) = new Registry('reader', [ 'application/json' => function (type:Type, pos:Position) { var ct = type.toComplex({ direct: true }); - return macro @:pos(pos) new tink.json.Parser<$ct>().tryParse; - } + return function(e) return macro @:pos(pos) new tink.json.Parser<$ct>().tryParse($e); + }, ]); static public var writers(default, null) = new Registry('writer', [ 'application/json' => function (type:Type, pos:Position) { var ct = type.toComplex( { direct: true } ); - return macro @:pos(pos) new tink.json.Writer<$ct>().write; - } + return function(e) return macro @:pos(pos) new tink.json.Writer<$ct>().write($e); + }, + 'application/octet-stream' => function (type:Type, pos:Position) { + if(type.unifiesWith(Context.getType('tink.io.Source.RealSource'))) + return function(e) return macro @:pos(pos) tink.io.Source.RealSourceTools.idealize($e, function(_) return tink.io.Source.EMPTY); + else if (type.unifiesWith(Context.getType('tink.Chunk'))) + return function(e) return macro @:pos(pos) ($e:tink.Chunk); + else + throw 'Unsupported body type ${type.getID()} for application/octet-stream'; + }, ]); } private class Registry { - var map:MapPosition->Expr>; + var map:MapPosition->(Expr->Expr)>; var kind:String; public function new(kind, map) { diff --git a/src/tink/web/macros/Proxify.hx b/src/tink/web/macros/Proxify.hx index e53ba87..658956f 100644 --- a/src/tink/web/macros/Proxify.hx +++ b/src/tink/web/macros/Proxify.hx @@ -96,7 +96,6 @@ class Proxify { kind: FFun({ args: [for (arg in f.signature) if(arg.name != 'user') { name: arg.name, type: arg.type.toComplex(), opt: arg.optional }], expr: { - var call = []; switch f.kind { @@ -112,56 +111,59 @@ class Proxify { var contentType = None; var body = combine(f.field.pos, RouteSyntax.getPayload(f, PBody), function (expr, type) { - var writer = + var ret = switch f.consumes { case ['application/x-www-form-urlencoded']: contentType = Some('application/x-www-form-urlencoded'); - macro new tink.querystring.Builder<$type>().stringify; + macro new tink.querystring.Builder<$type>().stringify(expr); case v: var w = MimeType.writers.get(v, type.toType().sure(), f.field.pos); contentType = Some(w.type); - w.generator; + w.generator(expr); } - return macro @:pos(expr.pos) ${writer}($expr); + return macro @:pos(expr.pos) $ret; }).or(macro ''); var endPoint = makeEndpoint(v.path, f); switch contentType { case Some(v): - endPoint = macro $endPoint.sub({ headers: [ - new tink.http.Header.HeaderField('content-type', $v{v}), - new tink.http.Header.HeaderField('content-length', __body__.length), - ]}); + var headers = [macro new tink.http.Header.HeaderField('content-type', $v{v})]; + if(v != 'application/octet-stream') headers.push(macro new tink.http.Header.HeaderField('content-length', (__body__:Chunk).length)); + endPoint = macro $endPoint.sub({ headers: $a{headers} }); case None: } + var bodyType = contentType == None ? macro:tink.io.RealSource : macro:tink.Chunk; + macro @:pos(f.field.pos) { - var __body__:tink.Chunk = $body; + var __body__ = $body; return $endPoint.request( this.client, cast $v{method}, __body__, ${switch call.response { - case RData(_.reduce() => TEnum(_.get() => {pack: ['tink', 'core'], name: 'Noise'}, _)): - macro function(header, body):tink.core.Promise { + case RData(t) if(t.unifiesWith(Context.getType('tink.io.Source.RealSource'))): + macro function (header, body):tink.core.Promise { return if(header.statusCode >= 400) tink.io.Source.RealSourceTools.all(body) .next(function(chunk) return new tink.core.Error(header.statusCode, chunk)) else - tink.core.Promise.NOISE; + tink.core.Future.sync(tink.core.Outcome.Success(body)); } + case RData(_.reduce() => TEnum(_.get() => {pack: ['tink', 'core'], name: 'Noise'}, _)): + macro function(_) return Noise; case RData(t): switch RouteSyntax.asWebResponse(t) { case Some(t): macro function(header, body) return tink.io.Source.RealSourceTools.all(body) - .next(function(chunk) return ${MimeType.readers.get(f.produces, t, f.field.pos).generator}(chunk)) + .next(function(chunk) return ${MimeType.readers.get(f.produces, t, f.field.pos).generator(macro chunk)}) .next(function(parsed) return new tink.web.Response(header, parsed)); - case None: - MimeType.readers.get(f.produces, t, f.field.pos).generator; + case None: + macro function(e) return ${MimeType.readers.get(f.produces, t, f.field.pos).generator(macro e)}; } case ROpaque(t): if (Context.getType('tink.http.Response.IncomingResponse').unifiesWith(t)) { diff --git a/src/tink/web/macros/Routing.hx b/src/tink/web/macros/Routing.hx index bdb3b50..8251183 100644 --- a/src/tink/web/macros/Routing.hx +++ b/src/tink/web/macros/Routing.hx @@ -422,15 +422,21 @@ class Routing { formats.push( macro @:pos(pos) if (ctx.accepts($v{fmt})) return ${ switch RouteSyntax.asWebResponse(t) { - case Some(t): + case Some(w): macro new tink.http.Response.OutgoingResponse( __data__.header.concat([new tink.http.Header.HeaderField(CONTENT_TYPE, $v{fmt})]), - ${MimeType.writers.get([fmt], t, pos).generator}(__data__.body) + ${MimeType.writers.get([fmt], w, pos).generator(macro __data__.body)} ); + case None if(t.unifiesWith(Context.getType('tink.io.Source.RealSource'))): + macro new tink.http.Response.OutgoingResponse( + new tink.http.Response.ResponseHeader($statusCode, $statusCode, [new tink.http.Header.HeaderField(CONTENT_TYPE, 'application/octet-stream')]), + tink.io.Source.RealSourceTools.idealize(__data__, function(_) return Source.EMPTY) + ); + case None: var e = macro tink.web.routing.Response.textual( $statusCode, - $v{fmt}, ${MimeType.writers.get([fmt], t, pos).generator}(__data__) + $v{fmt}, ${MimeType.writers.get([fmt], t, pos).generator(macro __data__)} ); if(headers.length > 0) @@ -441,7 +447,8 @@ class Routing { e; } - }); + } + ); macro @:pos(pos) tink.core.Promise.lift($result).next( function (__data__:$ct):tink.core.Promise { @@ -633,7 +640,7 @@ class Routing { cases.push({ values: [macro $v{type}], expr: macro @:pos(pos) ctx.allRaw().next( - function (b) return ${MimeType.readers.get([type], payload.toType(pos).sure(), pos).generator}(b.toString()) + function (b) return ${MimeType.readers.get([type], payload.toType(pos).sure(), pos).generator(macro b.toString())} ) }); } diff --git a/tests/Fake.hx b/tests/Fake.hx index 903989a..e05fe19 100644 --- a/tests/Fake.hx +++ b/tests/Fake.hx @@ -38,8 +38,9 @@ class Fake { @:get public function complex(query: Complex, ?bar:String) return query; - // @:post public function streaming(body:RealSource) - // return body.all(); + @:consumes('application/octet-stream') + @:post public function streaming(body:RealSource):RealSource + return body; @:post public function buffered(body:Bytes) return body; diff --git a/tests/ProxyTest.hx b/tests/ProxyTest.hx index c234c9d..eedaef9 100644 --- a/tests/ProxyTest.hx +++ b/tests/ProxyTest.hx @@ -36,6 +36,10 @@ class ProxyTest { return proxy.complex(c).map(function (o) return assert(compare(c, o.sure()))); } + public function streaming() { + return proxy.streaming('foo').next(function (o) return o.all()).next(function(o) return assert(o.toString() == 'foo')); + } + public function typed() { return proxy.typed() .next(function (o) {