Hi all, I'm currently using a pattern where I POST to a rather generic restxq function that performs some pre-validation on the POST body. At that point, according to information I get from the request (path, headers) I call a subsequent more specific function through the <forward/> construct. It works nicely up to the access to the POST content which appears to be consumed defintely by the first function. Actually I get the following error at the called function:
[BASX0003] Input could not be converted: "POST.xml" (Line 1): No input found.
I don't see in the docs any way I can get forward to pass ahead the bost body and I thought it should be natural ... what am I missing?
Regards, Marco Lettere.
P.S. I'm using basex 7.7.
Hello all, sorry for being pedantic but I'm really stuck with this. I've tried to pass the post body through the session mechanism to the called function. It works but it's not a viable solution since I have to change the annotations removing the %rest:POST("{$postbody}") annotation because otherwise I get the BASX0003 error before entering the function. But the called function needs to remain a "lower level" REST entrypoint so it definitely needs to keep the rest annotations as they are. Moreover there is no possibility of stating that the postbody may possibly be empty, is it? Could anyone please let me know if I'm going a wrong way with architectural design? Thanks a lot. Marco.
On 01/13/2014 11:48 AM, Marco Lettere wrote:
Hi all, I'm currently using a pattern where I POST to a rather generic restxq function that performs some pre-validation on the POST body. At that point, according to information I get from the request (path, headers) I call a subsequent more specific function through the <forward/> construct. It works nicely up to the access to the POST content which appears to be consumed defintely by the first function. Actually I get the following error at the called function:
[BASX0003] Input could not be converted: "POST.xml" (Line 1): No input found.
I don't see in the docs any way I can get <forward/> to pass ahead the post body and I thought it should be natural ... what am I missing?
Regards, Marco Lettere.
P.S. I'm using basex 7.7. _______________________________________________ BaseX-Talk mailing list BaseX-Talk@mailman.uni-konstanz.de https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk
Hi Marco,
an introductory question: what’s your particular reason for splitting the operation in two parts? Do you perform database updates in the pre-validation step?
It works nicely up to the access to the POST content which appears to be consumed defintely by the first function.
That’s right: POST bodies can only be consumed once. We could think about extending the rest:forward-Syntax in order to construct a new body, but that’s just an idea (and I’m not sure if this is supported by the Java request dispatcher).
Moreover there is no possibility of stating that the postbody may possibly be empty, is it?
This should generally be possible. I have tried the following RESTXQ function:
declare %rest:path("/post") %rest:POST("{$x}") function rest:main($x) { $x };
It doesn’t trigger an error when calling it with:
curl -XPOST -i "http://localhost:8984/post"
Could you provide me with a little example of your code that causes the problem? Christian
Hi Christian, I have a set of RESTXQ functions both updating and not, defined by a low-level REST specification, and this is my original configuration. Now I have to wrap them with equivalent SOAP calls that come from another specification but the native functions need to remain accessible through REST. I'd like to do the WSDL queries, the validation of the SOAP request and finally the routing to the native functions by just adding only one single generic RESTXQ function. This code will access only filesystem resources and it won't be updating for sure. Since I don't want to make everything "updating", because I dont want to introduce unnecessary synchronization, I'd like to just call the native functions through the forwarding mechanism passing ahead the POST content of the request and exploiting the nice declarative way of routing with parametric path annotations. According to the optionality of the postbody parameter it works when I call a RESTXQ function directly. It also works when forwarding if the orignal HTTP request doesn't have any postbody. But when the postbody is there in the original request, the subsequent function (where I forward to) yields the error.
Of course I'm also ready to accept architectural suggestions if this can satisfy my needs ;-)
Here is a code snippet that should reproduce the error on 7.7.2. Both the plain version plus the one that uses the session trick. Hope this helps. Regards.
module namespace soapskel = 'urn:myns'; import module namespace session = "http://basex.org/modules/session"; declare %rest:path("test") %rest:POST("{$postbody}") %output:method("xml") function soapskel:test($postbody){ (: do all SOAP related work here :) rest:forward{ "test/impl" }</rest:forward> }; declare %rest:path("test2") %rest:POST("{$postbody}") %output:method("xml") function soapskel:test2($postbody){ (: do all SOAP related work here :) let $id := (session:id(), session:set('data',$postbody)) return rest:forward{ "test/impl" }</rest:forward> }; declare %rest:path("test/impl") %rest:POST("{$postbody}") %output:method("xml") function soapskel:impl($postbody){ if (empty($postbody)) then session:get('data') else $postbody };
On 01/14/2014 01:38 PM, Christian Grün wrote:
Hi Marco,
an introductory question: what’s your particular reason for splitting the operation in two parts? Do you perform database updates in the pre-validation step?
It works nicely up to the access to the POST content which appears to be consumed defintely by the first function.
That’s right: POST bodies can only be consumed once. We could think about extending the rest:forward-Syntax in order to construct a new body, but that’s just an idea (and I’m not sure if this is supported by the Java request dispatcher).
Moreover there is no possibility of stating that the postbody may possibly be empty, is it?
This should generally be possible. I have tried the following RESTXQ function:
declare %rest:path("/post") %rest:POST("{$x}") function rest:main($x) { $x };
It doesn’t trigger an error when calling it with:
curl -XPOST -i "http://localhost:8984/post"
Could you provide me with a little example of your code that causes the problem? Christian
Since I don't want to make everything "updating", because I dont want to introduce unnecessary synchronization, I'd like to just call the native functions through the forwarding mechanism passing ahead the POST content of the request and exploiting the nice declarative way of routing with parametric path annotations. […]
I guess I should spend more time on understanding your use case, but due to my lazyness, I’m just asking why you don’t directly call the functions instead of using redirects? À la…
OLD: (: do all SOAP related work here :) rest:forward{ "test/impl" }</rest:forward>
NEW: (: do all SOAP related work here :) soapskel:impl($postbody)
If it makes sense.. Do you have an example that demonstrates why this isn’t possible?
According to the optionality of the postbody parameter it works when I call a RESTXQ function directly. It also works when forwarding if the orignal HTTP request doesn't have any postbody. But when the postbody is there in the original request, the subsequent function (where I forward to) yields the error.
I just tried your example with the following curl call. As expected, it returns nothing, but it doesn’t raise an error either:
curl -i -XPOST -d"<a/>" "localhost:8984/test"
HTTP/1.1 200 OK Content-Type: application/xml; charset=UTF-8 Content-Length: 0 Server: Jetty(8.1.11.v20130520)
Do you see what I did wrong? Christian
Of course I'm also ready to accept architectural suggestions if this can satisfy my needs ;-)
Here is a code snippet that should reproduce the error on 7.7.2. Both the plain version plus the one that uses the session trick. Hope this helps. Regards.
module namespace soapskel = 'urn:myns'; import module namespace session = "http://basex.org/modules/session"; declare %rest:path("test") %rest:POST("{$postbody}") %output:method("xml") function soapskel:test($postbody){ (: do all SOAP related work here :) rest:forward{ "test/impl" }</rest:forward> }; declare %rest:path("test2") %rest:POST("{$postbody}") %output:method("xml") function soapskel:test2($postbody){ (: do all SOAP related work here :) let $id := (session:id(), session:set('data',$postbody)) return rest:forward{ "test/impl" }</rest:forward> }; declare %rest:path("test/impl") %rest:POST("{$postbody}") %output:method("xml") function soapskel:impl($postbody){ if (empty($postbody)) then session:get('data') else $postbody };
On 01/14/2014 01:38 PM, Christian Grün wrote:
Hi Marco,
an introductory question: what’s your particular reason for splitting the operation in two parts? Do you perform database updates in the pre-validation step?
It works nicely up to the access to the POST content which appears to be consumed defintely by the first function.
That’s right: POST bodies can only be consumed once. We could think about extending the rest:forward-Syntax in order to construct a new body, but that’s just an idea (and I’m not sure if this is supported by the Java request dispatcher).
Moreover there is no possibility of stating that the postbody may possibly be empty, is it?
This should generally be possible. I have tried the following RESTXQ function:
declare %rest:path("/post") %rest:POST("{$x}") function rest:main($x) { $x };
It doesn’t trigger an error when calling it with:
curl -XPOST -i "http://localhost:8984/post"
Could you provide me with a little example of your code that causes the problem? Christian
On 01/14/2014 03:10 PM, Christian Grün wrote:
Since I don't want to make everything "updating", because I dont want to introduce unnecessary synchronization, I'd like to just call the native functions through the forwarding mechanism passing ahead the POST content of the request and exploiting the nice declarative way of routing with parametric path annotations. […]
I guess I should spend more time on understanding your use case, but due to my lazyness, I’m just asking why you don’t directly call the functions instead of using redirects? À la…
OLD: (: do all SOAP related work here :) rest:forward{ "test/impl" }</rest:forward>
NEW: (: do all SOAP related work here :) soapskel:impl($postbody)
If it makes sense.. Do you have an example that demonstrates why this isn’t possible?
Sorry, for sure this is possible. But suppose I have different impl functions where few of them are updating and few are not. I necessarily have to declare the soap entry point as updating too. Thus introducing particular syntax like db:output or synchronizations in places where it's not supposed to be needed. Isn't it like that?
According to the optionality of the postbody parameter it works when I call a RESTXQ function directly. It also works when forwarding if the orignal HTTP request doesn't have any postbody. But when the postbody is there in the original request, the subsequent function (where I forward to) yields the error.
I just tried your example with the following curl call. As expected, it returns nothing, but it doesn’t raise an error either:
curl -i -XPOST -d"<a/>" "localhost:8984/test"
HTTP/1.1 200 OK Content-Type: application/xml; charset=UTF-8 Content-Length: 0 Server: Jetty(8.1.11.v20130520)
I think it depends on the content type. I'm trying with firefox poster and it works if I force application/x-www-form-urlencoded. Conversely it stops working with
curl -i -XPOST -d"<a/>" -H "Content-Type: application/xml; charset=UTF-8" "localhost:8984/test"
Thanks a lot anyway. M.
functions where few of them are updating and few are not. I necessarily have to declare the soap entry point as updating too. Thus introducing particular syntax like db:output or synchronizations in places where it's not supposed to be needed. Isn't it like that?
Yes, I think I see the point. I would like to get completely rid of the db:output statements, as it can statically be deteted if a query is updating or not anyway. XQuery Update 3.1 might provide some ways out of the current situation.
I think it depends on the content type. I'm trying with firefox poster and it works if I force application/x-www-form-urlencoded. Conversely it stops working with
curl -i -XPOST -d"<a/>" -H "Content-Type: application/xml; charset=UTF-8" "localhost:8984/test"
Ok. If it’s requests are sent without a content type, the received value could be cast to XML via fn:parse-xml; but that may not be helpful in your case.
I’ll have some more thoughts if there are chances to also forward the request content. It may take while, though..
Christian
Hi, Just wanted to say that we have a very similar use case (though not SOAP) of a standard requiring having one endpoint to receive all incoming requests. Some of these requests are updating and some are not.
At the moment, it seems like the only solution will be to have two endpoints (one for updating, one for not) and another service sitting in-front of BaseX that peers into the incoming message to determine which ones are updating or not before forwarding them onto the correct service.
Should we go ahead and setup something like this? Or does anyone have a more elegant suggestion?
Cheers, -carl
On Jan 14, 2014, at 9:49 AM, Christian Grün christian.gruen@gmail.com wrote:
functions where few of them are updating and few are not. I necessarily have to declare the soap entry point as updating too. Thus introducing particular syntax like db:output or synchronizations in places where it's not supposed to be needed. Isn't it like that?
Yes, I think I see the point. I would like to get completely rid of the db:output statements, as it can statically be deteted if a query is updating or not anyway. XQuery Update 3.1 might provide some ways out of the current situation.
I think it depends on the content type. I'm trying with firefox poster and it works if I force application/x-www-form-urlencoded. Conversely it stops working with
curl -i -XPOST -d"<a/>" -H "Content-Type: application/xml; charset=UTF-8" "localhost:8984/test"
Ok. If it’s requests are sent without a content type, the received value could be cast to XML via fn:parse-xml; but that may not be helpful in your case.
I’ll have some more thoughts if there are chances to also forward the request content. It may take while, though..
Christian _______________________________________________ BaseX-Talk mailing list BaseX-Talk@mailman.uni-konstanz.de https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk
For our case study we fixed creating two bindings in the wsdl exporting two services one for the query only operations and the other for the updating operations. This implied the editing of two restxq entry points that are actually clones of each other except for the "updating" and "db:output" details. I already had a frontend service acting as a bridge but for deployment and manageability reasons I wanted to avoid this. I'm not very happy of having to change wsdls because this alters the views for the clients but I've no other solution yet. <forward> supporting post content would have been defintely the best solution. I still hope there will be a way of realizing it in the near future. Regards, Marco.
On 19/01/2014 14:52, Carl Leitner wrote:
Hi, Just wanted to say that we have a very similar use case (though not SOAP) of a standard requiring having one endpoint to receive all incoming requests. Some of these requests are updating and some are not.
At the moment, it seems like the only solution will be to have two endpoints (one for updating, one for not) and another service sitting in-front of BaseX that peers into the incoming message to determine which ones are updating or not before forwarding them onto the correct service.
Should we go ahead and setup something like this? Or does anyone have a more elegant suggestion?
Cheers, -carl
On Jan 14, 2014, at 9:49 AM, Christian Grün christian.gruen@gmail.com wrote:
functions where few of them are updating and few are not. I necessarily have to declare the soap entry point as updating too. Thus introducing particular syntax like db:output or synchronizations in places where it's not supposed to be needed. Isn't it like that?
Yes, I think I see the point. I would like to get completely rid of the db:output statements, as it can statically be deteted if a query is updating or not anyway. XQuery Update 3.1 might provide some ways out of the current situation.
I think it depends on the content type. I'm trying with firefox poster and it works if I force application/x-www-form-urlencoded. Conversely it stops working with
curl -i -XPOST -d"<a/>" -H "Content-Type: application/xml; charset=UTF-8" "localhost:8984/test"
Ok. If it’s requests are sent without a content type, the received value could be cast to XML via fn:parse-xml; but that may not be helpful in your case.
I’ll have some more thoughts if there are chances to also forward the request content. It may take while, though..
Christian _______________________________________________ BaseX-Talk mailing list BaseX-Talk@mailman.uni-konstanz.de https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk
basex-talk@mailman.uni-konstanz.de