A Java library to parse and validate HTTP Link headers according to RFC 8288 -
turning raw header values into a usable in-memory model.
This repository is in an early and experimental stage.
- APIs may change or be removed without prior notice
- Documentation may be incomplete or outdated
- Backward compatibility is not guaranteed
Use at your own risk, but provide feedback and suggestions in an issue or contribution in form of a pull-request.
| Without Linksmith ❌ | With Linksmith ✅ |
|---|---|
Raw HTTP Link header |
Raw HTTP Link header |
| Manual string parsing | Linksmith |
| Custom, ad-hoc code | Stable core API |
| Hard to extend | Configurable components |
| Error-prone results | Structured WebLinks |
Linksmith replaces ad-hoc parsing of HTTP Link headers with a stable, configurable, standards-compliant WebLink API.
<!-- You might want to check for the latest version -->
<groupId>life.qbic</groupId>
<artifactId>linksmith</artifactId>
<version>1.0.0</version>Check the latest component version on Maven Central.
curl -I https://zenodo.org/records/17179862A simple HTTP GET request to the Zenodo record will result in the following HTTP header:
HTTP/1.1 200 OK
server: nginx
date: Mon, 01 Dec 2025 12:14:33 GMT
content-type: text/html; charset=utf-8
content-length: 85404
vary: Accept-Encoding
link: <https://orcid.org/0009-0006-0929-9338> ; rel="author" , <https://ror.org/00v34f693> ; rel="author" , <https://ror.org/03a1kwz48> ; rel="author" , <https://doi.org/10.5281/zenodo.17179862> ; rel="cite-as" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/dcat+xml" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/json" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/ld+json" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/ld+json;profile="https://datapackage.org/profiles/2.0/datapackage.json"" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/marcxml+xml" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/vnd.citationstyles.csl+json" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/vnd.datacite.datacite+json" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/vnd.datacite.datacite+xml" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/vnd.geo+json" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/vnd.inveniordm.v1+json" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/vnd.inveniordm.v1.full+csv" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/vnd.inveniordm.v1.simple+csv" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/x-bibtex" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="application/x-dc+xml" , <https://zenodo.org/api/records/17179862> ; rel="describedby" ; type="text/x-bibliography" , <https://zenodo.org/records/17179862/files/22-09-2025_13-National-Biobanken-Symposium_FAIR-IN-Biobanking_SG.pdf> ; rel="item" ; type="application/pdf" , <https://zenodo.org/records/17179862/files/22-09-2025_13-National-Biobanken-Symposium_FAIR-IN-Biobanking_SG.odp> ; rel="item" ; type="application/octet-stream" , <https://zenodo.org/records/17179862/files/22-09-2025_13-National-Biobanken-Symposium_FAIR-IN-Biobanking_SG.pptx> ; rel="item" ; type="application/octet-stream" , <https://creativecommons.org/licenses/by/4.0/legalcode> ; rel="license" , <https://schema.org/PresentationDigitalDocument> ; rel="type" , <https://schema.org/AboutPage> ; rel="type" , <https://zenodo.org/api/records/17179862> ; rel="linkset" ; type="application/linkset+json"For the sake of simplicity, we just take the first two link entries, which points to the actual
author and the organisation.
import life.qbic.linksmith.core.WebLinkProcessor;
import life.qbic.linksmith.spi.WebLinkValidator.ValidationResult;
// Raw header of an HTTP response with link attribute
// 'link: <https://orcid.org/0009-0006-0929-9338> ; rel="author" , <https://ror.org/00v34f693> ; rel="author"'
String rawHeader =
'<https://orcid.org/0009-0006-0929-9338> ; rel="author" , <https://ror.org/00v34f693> ; rel="author"';
WebLinkProcessor webLinkProcessor = new WebLinkProcessor.Builder().build();
ValidationResult result = webLinkProcessor.process(rawHeader);
if (result.hasIssues()) {
// Retrieve the report
var report = result.report();
// Investigate the report
// ...
return;
}
result.weblinks().stream()
.filter(link -> link.rel().contains("author"))
.forEach(link -> System.out.println(link.target()))This will result in the following printout:
// The expected printout of the previous code example
https://orcid.org/0009-0006-0929-9338
https://ror.org/00v34f693Compass is an open-source research software project and welcomes contributions from the community.
You can contribute by:
- reporting bugs or unexpected behavior,
- improving documentation or examples,
- proposing new validation rules or features,
- submitting code improvements or fixes.
Please read the Contribution Guidelines before opening an issue or pull request.
All contributions are reviewed, and design discussions are encouraged — especially for changes affecting validation semantics or public APIs.
Compass implements the community standards behind Web Linking.
- RFC 8288 — Web Linking: https://datatracker.ietf.org/doc/html/rfc8288
We thank the authors and contributors of these specifications for their work. Linksmith is an independent implementation and is not affiliated with or endorsed by the specification authors.
The Linksmith name and logo are not covered by the AGPL-3.0 license.
Logo design © 2025 Sven Fillinger and Shraddha Pawar. Used with permission. All rights reserved.