@@ -8,10 +8,13 @@ xquery version "3.1";
8
8
: The parameter name `version` is retained for backward compatibility, even though it's
9
9
: `versions` in the EXPath Package spec.
10
10
:
11
- : The `info` parameter can be used for troubleshooting.
11
+ : The `info` parameter can be used for troubleshooting and to query package availability
12
12
:
13
13
: The `zip` parameter forces the EXPath Package to be returned with a .xar.zip file extension.
14
14
:
15
+ : A client can set application/json in its accept header to receive packge information and errors
16
+ : as JSON.
17
+ :
15
18
: @see http://expath.org/spec/pkg
16
19
:)
17
20
@@ -22,47 +25,149 @@ import module namespace versions="http://exist-db.org/apps/public-repo/versions"
22
25
declare namespace request="http://exist-db.org/xquery/request" ;
23
26
declare namespace response="http://exist-db.org/xquery/response" ;
24
27
25
- let $abbrev := request:get-parameter ("abbrev" , ())
26
- let $name := request:get-parameter ("name" , ())
27
- let $exist-version-semver := request:get-parameter ("processor" , $config:default-exist-version)
28
- let $versions := request:get-parameter ("version" , ())
29
- let $semver := request:get-parameter ("semver" , ())
30
- let $semver-min := request:get-parameter ("semver-min" , ())
31
- let $semver-max := request:get-parameter ("semver-max" , ())
32
- let $zip := request:get-parameter ("zip" , ())
33
- let $info := request:get-parameter ("info" , ())
34
- let $app-root-absolute-url := request:get-parameter ("app-root-absolute-url" , ())
35
-
36
- let $packages :=
37
- if ($name) then
28
+ (: TODO shouldn't we get $abs-public from $config? - joewiz :)
29
+ declare variable $app-root-absolute-url := request:get-parameter ("app-root-absolute-url" , ());
30
+ declare variable $abs-public := $app-root-absolute-url || "/public/" ;
31
+
32
+ declare variable $exist-version-semver := request:get-parameter ("processor" , $config:default-exist-version);
33
+ declare variable $abbrev := request:get-parameter ("abbrev" , ());
34
+ declare variable $name := request:get-parameter ("name" , ());
35
+ declare variable $versions := request:get-parameter ("version" , ());
36
+ declare variable $semver := request:get-parameter ("semver" , ());
37
+ declare variable $semver-min := request:get-parameter ("semver-min" , ());
38
+ declare variable $semver-max := request:get-parameter ("semver-max" , ());
39
+
40
+ declare variable $zip := request:get-parameter ("zip" , ());
41
+ declare variable $info := request:get-parameter ("info" , ());
42
+
43
+ declare variable $versions-or-version-range :=
44
+ exists ($versions)
45
+ or exists ($semver)
46
+ or exists ($semver-min)
47
+ or exists ($semver-max)
48
+ ;
49
+
50
+ (:
51
+ input: "text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8"
52
+ output: ("text/html", "application/json", "application/xml", "image/webp", "*/*")
53
+ :)
54
+ declare function local:parse-accept-header ($accept as xs:string) as xs:string* {
55
+ tokenize ($accept, "," )
56
+ ! normalize-space () (: trim value :)
57
+ ! tokenize (., ";" )[1 ] (: drop q :)
58
+ };
59
+
60
+ declare function local:prefers-json ($mime-types as xs:string*) as xs:boolean {
61
+ let $json-index := index-of ($mime-types, "application/json" )
62
+ let $xml-index := index-of ($mime-types, "application/xml" )
63
+ return
64
+ exists ($json-index) and (empty ($xml-index) or $xml-index > $json-index)
65
+ };
66
+
67
+ declare variable $json-preferred := local:prefers-json (local:parse-accept-header (request:get-header ("Accept" )));
68
+
69
+ declare function local:render-semver-range ($semver as xs:string?, $semver-min as xs:string?, $semver-max as xs:string?) as xs:string {
70
+ if (exists ($semver)) then (
71
+ $semver
72
+ ) else (
73
+ string-join ((
74
+ if (exists ($semver-min)) then ``[>=`{$semver-min}`]`` else (),
75
+ if (exists ($semver-max)) then ``[<=`{$semver-max}`]`` else ()
76
+ ))
77
+ )
78
+ };
79
+
80
+ declare function local:report-not-found ($message as xs:string) as item () {
81
+ response:set-status-code (404 ),
82
+ if ($json-preferred) then (
83
+ response:set-header ("content-type" , "application/json" ),
84
+ serialize (map { "error" : $message }, map{ "method" : "json" })
85
+ ) else (
86
+ (: could be changed to <error/> element :)
87
+ <p>{$message}</p>
88
+ )
89
+ };
90
+
91
+ declare function local:render-version-query () as xs:string {
92
+ if (exists ($versions))
93
+ then ("versions: " || string-join ($versions, ', ' ))
94
+ else if ($versions-or-version-range)
95
+ then ("semver-range: " || local:render-semver-range ($semver, $semver-min, $semver-max))
96
+ else ("compatible with processor version " || $exist-version-semver)
97
+ };
98
+
99
+ declare function local:render-package-query () as xs:string {
100
+ if (exists ($name)) then (
101
+ "name: " || $name
102
+ ) else (
103
+ "abbrev: " || $abbrev
104
+ )
105
+ };
106
+
107
+ declare variable $packages :=
108
+ if (exists ($name)) then (
38
109
doc ($config:package-groups-doc)//package-group [name eq $name]//package
39
- else
110
+ ) else (
40
111
doc ($config:package-groups-doc)//package-group [abbrev eq $abbrev]//package
112
+ )
113
+ ;
41
114
42
- let $package :=
43
- if (exists ($versions) or exists ($semver) or exists ($semver-min) or exists ($semver-max)) then
44
- versions:get-newest-package-satisfying-version-attributes ($packages, $versions, $semver, $semver-min, $semver-max)
45
- else
46
- versions:get-newest-package-satisfying-exist-version ($packages, $exist-version-semver)
47
-
48
- return
49
- if ($package) then
50
- (: TODO shouldn't we get $abs-public from $config? - joewiz :)
51
- let $abs-public := $app-root-absolute-url || "/public/"
52
- let $xar-filename := $package/@path
53
- return
54
- if ($info) then
55
- element found {
56
- $package/@sha256,
57
- $package/version ! attribute version {.},
58
- $package/@path
59
- }
60
- else if ($zip) then
61
- app:redirect-to ($abs-public || $xar-filename || ".zip" )
62
- else
63
- app:redirect-to ($abs-public || $xar-filename)
64
- else
65
- (
66
- response:set-status-code (404 ),
67
- <p>Package file not found!</p>
115
+ declare variable $package :=
116
+ try {
117
+ if ($versions-or-version-range) then (
118
+ versions:get-newest-package-satisfying-version-attributes (
119
+ $packages, $versions, $semver, $semver-min, $semver-max)
120
+ ) else (
121
+ versions:get-newest-package-satisfying-exist-version ($packages, $exist-version-semver)
68
122
)
123
+ } catch * {
124
+ util:log ("info" , "Error retrieving matching package in find.xq: " || $err:description)
125
+ }
126
+ ;
127
+
128
+ (: util:log("info", map {
129
+ "exist-version-semver" : $exist-version-semver,
130
+ "abbrev" : $abbrev,
131
+ "name" : $name,
132
+ "versions" : $versions,
133
+ "semver" : $semver,
134
+ "semver-min" : $semver-min,
135
+ "semver-max" : $semver-max,
136
+ "zip" : $zip,
137
+ "info" : $info,
138
+ "json-preferred": $json-preferred
139
+ }), :)
140
+ if (empty ($packages)) then (
141
+ local:report-not-found (``[No package with `{local:render-package-query ()}` found.]``)
142
+ ) else if (empty ($package)) then (
143
+ local:report-not-found (
144
+ ``[No matching version found for `{local:render-package-query ()}`; `{local:render-version-query ()}`.]``)
145
+ ) else if ($info and $json-preferred) then (
146
+ response:set-header ("content-type" , "application/json" ),
147
+ serialize (
148
+ map {
149
+ "sha256" : string ($package/@sha256),
150
+ "path" : string ($package/@path),
151
+ "size" : xs:integer ($package/@size),
152
+ "name" : string ($package/name),
153
+ "abbrev" : string ($package/abbrev),
154
+ "version" : string ($package/version ),
155
+ "url" : $abs-public || $package/@path
156
+ },
157
+ map { "method" : "json" }
158
+ )
159
+ ) else if ($info) then (
160
+ element found {
161
+ $package/@sha256,
162
+ $package/@path,
163
+ $package/@size,
164
+ attribute name { $package/name },
165
+ attribute abbrev { $package/abbrev },
166
+ attribute version { $package/version },
167
+ attribute url { $abs-public || $package/@path }
168
+ }
169
+ ) else if ($zip) then (
170
+ app:redirect-to ($abs-public || $package/@path || ".zip" )
171
+ ) else (
172
+ app:redirect-to ($abs-public || $package/@path)
173
+ )
0 commit comments