Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
15e8379
Add external document tabs and fix related CSS/XPath regressions (#293)
namedgraph Apr 15, 2026
cf08c27
Fix disabled edit button triggering modal and move action buttons ins…
namedgraph Apr 16, 2026
18dd437
Ignore clicks on disabled edit button in modal click handler
namedgraph Apr 16, 2026
e34db78
Refactor external doc tabs: per-URI panes, data-* state, tab-pane-id …
namedgraph Apr 19, 2026
1e9cd8a
Simplified tab rendering
namedgraph Apr 19, 2026
3064f2a
(X)HTML response fix in the proxy filter
namedgraph Apr 19, 2026
ca0d4a4
Additional tests
namedgraph Apr 19, 2026
a47bc84
Restored (X)HTML workaround in the proxy filter
namedgraph Apr 20, 2026
c6a19b4
Add margin-top to .content-body to restore spacing after sticky actio…
namedgraph Apr 20, 2026
cff9deb
Simplify external doc tab rendering and add lapp:application Link header
namedgraph Apr 20, 2026
6001561
Remove services fetch, service dropdown, and refactor navbar into sep…
namedgraph Apr 21, 2026
5746914
Tab activation fixes
namedgraph Apr 22, 2026
91271da
Hide system resources in client-side XSLT
namedgraph Apr 23, 2026
6201014
Fix navbar/tab-bar/action-bar spacing and move sidebar into tab panes
namedgraph Apr 24, 2026
15e2757
Add document-body wrapper, introduce ldh:DocumentNavigate, fix conten…
namedgraph Apr 28, 2026
6dd53c5
Fix modal document edit error by closing modal and reloading document…
namedgraph Apr 29, 2026
f5b9257
Move abort controller and cursor into ldh:DocumentNavigate, simplify …
namedgraph Apr 29, 2026
14ea6d1
`bs2:DocumentBody` mode
namedgraph May 2, 2026
d02bc3a
Render signup form client-side, implement tab close
namedgraph May 4, 2026
1461dcd
Fixed relative URL
namedgraph May 4, 2026
2c9604a
`ldh:NavigationUpdate` call moved into `ldh:RenderTab`
namedgraph May 6, 2026
7e19ff5
Request URI fixes
namedgraph May 7, 2026
56f7730
Pipe proxied HTTP responses as InputStream instead of parsing/re-seri…
namedgraph May 7, 2026
fe336ee
Remove stale testNullVariantThrowsNotAcceptable test
namedgraph May 7, 2026
708edfc
Fixed client's accepted media types
namedgraph May 7, 2026
81cc34a
Proxied `ETag` header test
namedgraph May 7, 2026
f78880c
Proxied HTML `Accept` test
namedgraph May 7, 2026
8875687
Forward end-to-end response headers from proxied upstream
namedgraph May 8, 2026
c3cc24b
Use top-quality `Accept` value to decide HTML proxy bypass
namedgraph May 8, 2026
aca9825
Wrap XSLT `document()` URIs with `ldh:href` and clean up client templ…
namedgraph May 8, 2026
65e5f9f
Rework proxy `Accept` regression tests, simplify q-rank bypass
namedgraph May 9, 2026
f670533
Removed debug messages
namedgraph May 9, 2026
ec76099
Removed unused template
namedgraph May 9, 2026
62d6255
Revert "Removed unused template"
namedgraph May 9, 2026
e7f0fd4
Wire `bs2:SignUpComplete` into signup success path
namedgraph May 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions http-tests/proxy/GET-proxied-accept-forwarded.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -euo pipefail

initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL"
initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL"
purge_cache "$END_USER_VARNISH_SERVICE"
purge_cache "$ADMIN_VARNISH_SERVICE"
purge_cache "$FRONTEND_VARNISH_SERVICE"

# add agent to the readers group to be able to read documents

add-agent-to-group.sh \
-f "$OWNER_CERT_FILE" \
-p "$OWNER_CERT_PWD" \
--agent "$AGENT_URI" \
"${ADMIN_BASE_URL}acl/groups/readers/"

# Regression: ProxyRequestFilter must forward the client's Accept header verbatim to the
# upstream, NOT substitute its own readable-types list. Previously the filter built its
# outbound Accept from MediaTypes.getReadable(Model.class) + getReadable(ResultSet.class)
# (everything Jena could ingest, all q=1.0), discarding what the client actually asked for.
# The upstream then content-negotiated against that broad list and could legally pick any
# RDF format — e.g. application/rdf+thrift — even when the client (e.g. SaxonJS document())
# explicitly requested application/rdf+xml or application/xml.
#
# Verify by requesting one specific RDF type and asserting the response matches it.

for accept in 'application/rdf+xml' 'text/turtle' 'application/n-triples'; do
content_type=$(curl -k -f -s -G -w "%{content_type}" -o /dev/null \
-E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \
-H "Accept: $accept" \
--data-urlencode "uri=${END_USER_BASE_URL}" \
"$ADMIN_BASE_URL")

case "$content_type" in
"$accept"*) ;;
*) exit 1 ;;
esac
done
40 changes: 40 additions & 0 deletions http-tests/proxy/GET-proxied-accept-html-not-preferred.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
set -euo pipefail

initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL"
initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL"
purge_cache "$END_USER_VARNISH_SERVICE"
purge_cache "$ADMIN_VARNISH_SERVICE"
purge_cache "$FRONTEND_VARNISH_SERVICE"

# add agent to the readers group to be able to read documents

add-agent-to-group.sh \
-f "$OWNER_CERT_FILE" \
-p "$OWNER_CERT_PWD" \
--agent "$AGENT_URI" \
"${ADMIN_BASE_URL}acl/groups/readers/"

# Regression: when a client lists application/xhtml+xml (or text/html) in Accept at a
# LOWER q-value than another supported type, the proxy must treat the request as
# API-client intent and forward — not as browser navigation that wants the app shell.
# Previously, ProxyRequestFilter bypassed on anyMatch(HTML or XHTML in Accept) without
# checking q-rank, so it false-fired on any Accept that mentioned HTML at all and
# returned the local app shell instead of the proxied response.
#
# Discriminator is HTTP status — content-type cannot tell bypass from forward because
# admin and end-user share writer configs (same Accept → same negotiated type on both).
# A UUID-named path that doesn't exist on either origin disambiguates:
# - bypass: ApplicationFilter strips ?uri= → request URI becomes admin root → 200
# - forward: proxy forwards the actual UUID path to end-user → 404

accept_header='application/xml, text/xml;q=0.9, application/xhtml+xml;q=0.8, */*;q=0.7'
non_existing_uri="${END_USER_BASE_URL}$(cat /proc/sys/kernel/random/uuid 2>/dev/null || uuidgen)/"

status=$(curl -k -s -G -o /dev/null -w "%{http_code}" \
-E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \
-H "Accept: $accept_header" \
--data-urlencode "uri=${non_existing_uri}" \
"$ADMIN_BASE_URL")

[ "$status" = "$STATUS_NOT_FOUND" ] || exit 1
1 change: 1 addition & 0 deletions http-tests/proxy/GET-proxied-external-502.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ add-agent-to-group.sh \

curl -k -w "%{http_code}\n" -o /dev/null -s \
-G \
-H "Accept: application/n-triples" \
-E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \
--data-urlencode "uri=http://f1d2d4cf-90bb-4f5b-ae4b-921e584b6edd.org" \
"$END_USER_BASE_URL" \
Expand Down
42 changes: 42 additions & 0 deletions http-tests/proxy/HEAD-proxied-etag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
set -euo pipefail

initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL"
initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL"
purge_cache "$END_USER_VARNISH_SERVICE"
purge_cache "$ADMIN_VARNISH_SERVICE"
purge_cache "$FRONTEND_VARNISH_SERVICE"

# add agent to the readers group to be able to read documents

add-agent-to-group.sh \
-f "$OWNER_CERT_FILE" \
-p "$OWNER_CERT_PWD" \
--agent "$AGENT_URI" \
"${ADMIN_BASE_URL}acl/groups/readers/"

extract_etag() {
grep -i '^etag:' \
| tr -d '\r' \
| sed 's/^[Ee][Tt][Aa][Gg]:[[:space:]]*//'
}

# fetch the end-user root directly to capture its ETag

direct_etag=$(curl --head -k -f -s \
-E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \
-H 'Accept: application/n-triples' \
"$END_USER_BASE_URL" \
| extract_etag)

# fetch the same document via the admin proxy

proxied_etag=$(curl -G --head -k -f -s \
-E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \
-H 'Accept: application/n-triples' \
--data-urlencode "uri=${END_USER_BASE_URL}" \
"$ADMIN_BASE_URL" \
| extract_etag)

[ -n "$proxied_etag" ] || exit 1
[ "$proxied_etag" = "$direct_etag" ] || exit 1
1 change: 0 additions & 1 deletion src/main/java/com/atomgraph/linkeddatahub/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,6 @@ protected PasswordAuthentication getPasswordAuthentication()
xsltProc.registerExtensionFunction(new UUID());
xsltProc.registerExtensionFunction(new DecodeURI());
xsltProc.registerExtensionFunction(new com.atomgraph.linkeddatahub.writer.function.URLDecode());
xsltProc.registerExtensionFunction(new com.atomgraph.linkeddatahub.writer.function.Construct(xsltProc));
xsltProc.registerExtensionFunction(new com.atomgraph.linkeddatahub.writer.function.SendHTTPRequest(xsltProc, client));

Model mappingModel = locationMapper.toModel();
Expand Down
Loading
Loading