Not very pretty, but this seems to work:
xquery version "1.0-ml";
declare namespace html = "http://www.w3.org/1999/xhtml";
let $method := 'GET'
let $uri := '/web/scripts/d3js/crossfilter.v1.min.js'
let $path := $uri
return
xdmp:eval('
import module namespace conf =
"http://marklogic.com/rest-api/endpoints/config"
at "/MarkLogic/rest-api/endpoints/config.xqy";
import module namespace rest = "http://marklogic.com/appservices/rest"
at "/MarkLogic/appservices/utils/rest.xqy";
import module namespace eput = "http://marklogic.com/rest-api/lib/endpoint-util"
at "/MarkLogic/rest-api/lib/endpoint-util.xqy";
declare variable $method external;
declare variable $uri external;
declare variable $path external;
(: This is a hack, but allows us to maintain one rule set endpoints and
rewriter,
while pushing the finer-grained error handling to the endpoint level. :)
declare function conf:rewrite-rules(
) as map:map
{
let $old-rules := eput:get-rest-options()
return
if (exists($old-rules))
then $old-rules
else
let $all-methods := ("GET","POST","PUT","DELETE","HEAD","OPTIONS")
let $new-rules := map:map()
let $unsupported := map:map()
return (
for $rule in (
conf:get-default-request-rule(),
conf:get-config-indexes-request-rule(),
conf:get-config-namespaces-item-request-rule(),
conf:get-config-namespaces-request-rule(),
conf:get-config-properties-request-rule(),
conf:get-config-query-child-request-rule(),
conf:get-config-query-list-request-rule(),
conf:get-config-query-request-rule(),
conf:get-document-query-rule(),
conf:get-document-update-rule(),
conf:get-keyvalue-list-request-rule(),
conf:get-qbe-request-rule(),
conf:get-ping-request-rule(),
conf:get-rsrc-list-query-rule(),
conf:get-rsrc-item-query-rule(),
conf:get-rsrc-item-update-rule(),
conf:get-rsrc-exec-query-rule(),
conf:get-rsrc-exec-update-rule(),
conf:get-search-query-request-rule(),
conf:get-search-update-request-rule(),
conf:get-tfm-list-request-rule(),
conf:get-tfm-item-request-rule(),
conf:get-txn-request-rule(),
conf:get-values-request-rule(),
conf:get-sparql-protocol-rule(),
conf:get-graph-explore-rule(),
conf:get-graphstore-protocol-rule(),
conf:get-suggest-request-rule(),
conf:get-rules-list-rule(),
conf:get-alert-rules-item-rule(),
conf:get-alert-match-rule(),
conf:get-extlib-root-request-rule(),
conf:get-extlib-request-rule()
)
let $endpoint := $rule/@endpoint/string(.)
(: Note: depends on document order in rule :)
let $uri-params := $rule/rest:uri-param/@name/string(.)
let $methods := $rule/rest:http/@method/tokenize(string(.),"
")
for $match in $rule/@fast-match/tokenize(string(.), "\|")
return (
for $method in $methods
return map:put($new-rules, $method||$match,
($endpoint,$uri-params)),
let $candidates :=
let $candidate-methods := map:get($unsupported,$match)
return
if (exists($candidate-methods))
then $candidate-methods
else $all-methods
return map:put(
$unsupported, $match, $candidates[not(. = $methods)]
)
),
for $match in map:keys($unsupported)
for $method in map:get($unsupported,$match)
return map:put(
$new-rules,
$method||$match,
"/MarkLogic/rest-api/endpoints/unsupported-method.xqy"
),
eput:set-rest-options($new-rules),
$new-rules
)
};
declare function conf:rewrite(
$method as xs:string,
$uri as xs:string,
$old-path as xs:string
) as xs:string?
{
let $rules := conf:rewrite-rules()
(: skip the empty step before the initial / :)
let $raw-steps := subsequence(tokenize($old-path,"/"), 2)
let $raw-count := count($raw-steps)
(: check for an empty step after a trailing / :)
let $extra-step := (subsequence($raw-steps,$raw-count,1) eq "")
let $step-count :=
if ($extra-step)
then $raw-count - 1
else $raw-count
let $steps :=
if ($step-count eq 0)
then ()
else if ($extra-step)
then subsequence($raw-steps, 1, $step-count)
else $raw-steps
(: generate the key for lookup in the rules map :)
let $key :=
(: no rule :)
if ($step-count eq 1)
then ()
(: default rule :)
else if ($step-count eq 0)
then ""
else
let $first-step := subsequence($steps,1,1)
return
(: as in /content/help :)
if ($first-step eq "content")
then ($first-step,"*")
else if (not($first-step = ("v1","LATEST")))
(: no rule :)
then ()
else
let $second-step := subsequence($steps,2,1)
return
(: as in /v1/documents :)
if ($step-count eq 2)
then ("*",$second-step)
else
let $third-step := subsequence($steps,3,1)
return
if ($second-step = ("ext"))
then
("*",$second-step,"**")
else if ($second-step = ("config","alert","graphs")) then
(: as in /v1/config/namespaces :)
if ($step-count eq 3)
then ("*", $second-step, $third-step)
(: /v1/config/options/NAME or
/v1/config/options/NAME/SUBNAME :)
else if ($step-count le 5)
then ("*", $second-step, $third-step, (4 to
$step-count) ! "*")
else ()
(: as in /v1/transactions/TXID :)
else if ($step-count eq 3)
then ("*", $second-step, "*")
(: catch all :)
else if ($step-count le 5)
then ("*", $second-step, $third-step, (4 to $step-count) !
"*")
(: no rule :)
else ()
let $key-method :=
if ($method eq "POST" and starts-with(
head(xdmp:get-request-header("content-type")),
"application/x-www-form-urlencoded"
))
then "GET"
else $method
let $value :=
if (empty($key)) then ()
else map:get($rules, string-join(($key-method,$key), "/"))
let $value-count := count($value)
return
(: fallback :)
if ($value-count eq 0)
then $uri
else
let $old-length := string-length($old-path)
let $has-params := (string-length($uri) ne $old-length)
let $new-path :=
(: append parameters to the rewritten path :)
if ($has-params)
then subsequence($value,1,1)||substring($uri,$old-length+1)
else subsequence($value,1,1)
return
if ($value-count eq 1)
then $new-path
(: append parameters from rule to the rewritten path :)
else string-join(
(
$new-path,
let $step-names := subsequence($value,2)
for $step-value at $i in
for $j in 2 to count($key)
let $place-holder := subsequence($key,$j,1)
return
if ($place-holder eq "*")
then subsequence($steps,$j,1)
else if ($place-holder eq "**")
(: using raw-steps picks up trailing slash :)
then string-join(subsequence($raw-steps,$j),"/")
else ()
return (
if ($has-params or $i gt 1)
then "&"
else "?",
subsequence($step-names,$i,1),
"=",
$step-value
)
),
""
)
};
(conf:rewrite($method, $uri, $path), $uri)[1]',
(xs:QName("method"), $method,
xs:QName("uri"), $uri,
xs:QName("path"), $path))
In other words: replace the eval in roxy/rewrite.xqy with above one, and you
should be able to run against ML 8.0-2. Note though that this does not run
against 8.0-1.1, as it would try to redefine those functions which is not
allowed.
Cheers,
Geert
From: Geert Josten
<[email protected]<mailto:[email protected]>>
Reply-To: MarkLogic Developer Discussion
<[email protected]<mailto:[email protected]>>
Date: Tuesday, April 21, 2015 at 10:24 AM
To: MarkLogic Developer Discussion
<[email protected]<mailto:[email protected]>>
Subject: Re: [MarkLogic Dev General] Roxy ML8 Hybrid App throws Undefined
Function Error in /src/roxy/rewrite.qxy for conf:rewrite()
Hi Gary,
Could you create a ticket here:
https://github.com/marklogic/roxy<https://github.com/marklogic/roxy/blob/dev/src/roxy/rewrite.xqy>
A number of people have reported this issue which started to appear since
release 8.0-2. I’ll try to look into it. It looks like we will need to preserve
some code from the old rewrite module. Otherwise it should work..
Cheers,
Geert
From: Yinyan guy <[email protected]<mailto:[email protected]>>
Reply-To: MarkLogic Developer Discussion
<[email protected]<mailto:[email protected]>>
Date: Tuesday, April 21, 2015 at 5:23 AM
To: MarkLogic Developer Discussion
<[email protected]<mailto:[email protected]>>
Subject: Re: [MarkLogic Dev General] Roxy ML8 Hybrid App throws Undefined
Function Error in /src/roxy/rewrite.qxy for conf:rewrite()
Hi Gary,
I have seen this error a couple of days ago and I am aware that there are some
enhancements in ML8 with respect to rewrite function. Hence you can file a bug
request for this or switch to ML7.
Hope this helps.
regards,
Puneet
________________________________
From: [email protected]<mailto:[email protected]>
To: [email protected]<mailto:[email protected]>
Date: Mon, 20 Apr 2015 22:46:31 -0400
Subject: [MarkLogic Dev General] Roxy ML8 Hybrid App throws Undefined Function
Error in /src/roxy/rewrite.qxy for conf:rewrite()
I have a Roxy ML8 Hybrid App that’s throwing an Undefined Function Error in
/src/roxy/rewrite.qxy for conf:rewrite().
I see the error is on line 42 of /src/roxy/rewrite.xqy. =>
https://github.com/marklogic/roxy/blob/dev/src/roxy/rewrite.xqy
Unfortunately, I have no time to troubleshoot this.
It looks like the root cause is related to the new ML8 rewrite.xml file.
Has anyone seen this?
Also, I believe there’s an invalid reference to a global variable called @uri
on line 391 in /src/roxy/lib/request.xqy. =>
https://github.com/marklogic/roxy/blob/dev/src/roxy/lib/request.xqy
Gary Russo
Enterprise NoSQL Architect
http://garyrusso.wordpress.com<http://garyrusso.wordpress.com/>
_______________________________________________ General mailing list
[email protected]<mailto:[email protected]> Manage
your subscription at: http://developer.marklogic.com/mailman/listinfo/general
_______________________________________________
General mailing list
[email protected]
Manage your subscription at:
http://developer.marklogic.com/mailman/listinfo/general