Skip to content

Commit c6d06b1

Browse files
committed
test: add more robust start/end range tests and document suppressed errors with diagrams.
1 parent 7ae918c commit c6d06b1

File tree

3 files changed

+535
-76
lines changed

3 files changed

+535
-76
lines changed

htsget-axum/src/middleware/auth.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,43 +9,44 @@ use htsget_http::middleware::auth::Auth;
99
use std::task::{Context, Poll};
1010
use tower::{Layer, Service};
1111

12-
impl From<Auth> for AuthLayer {
12+
impl From<Auth> for AuthenticationLayer {
1313
fn from(auth: Auth) -> Self {
1414
Self { inner: auth }
1515
}
1616
}
1717

1818
/// A wrapper around the authentication layer.
1919
#[derive(Clone)]
20-
pub struct AuthLayer {
20+
pub struct AuthenticationLayer {
2121
inner: Auth,
2222
}
2323

24-
impl AuthLayer {
24+
impl AuthenticationLayer {
2525
/// Get the inner auth layer.
2626
pub fn inner(&self) -> &Auth {
2727
&self.inner
2828
}
2929
}
3030

31-
impl<S> Layer<S> for AuthLayer {
32-
type Service = AuthMiddleware<S>;
31+
impl<S> Layer<S> for AuthenticationLayer {
32+
type Service = AuthenticationMiddleware<S>;
3333

3434
fn layer(&self, inner: S) -> Self::Service {
35-
AuthMiddleware::new(inner, self.clone())
35+
AuthenticationMiddleware::new(inner, self.clone())
3636
}
3737
}
3838

39-
/// A wrapper around the auth middleware.
39+
/// A wrapper around the authentication middleware. This middleware only handles
40+
/// authentication of a JWT token.
4041
#[derive(Clone)]
41-
pub struct AuthMiddleware<S> {
42+
pub struct AuthenticationMiddleware<S> {
4243
inner: S,
43-
layer: AuthLayer,
44+
layer: AuthenticationLayer,
4445
}
4546

46-
impl<S> AuthMiddleware<S> {
47+
impl<S> AuthenticationMiddleware<S> {
4748
/// Create a new middleware auth.
48-
pub fn new(inner: S, layer: AuthLayer) -> Self {
49+
pub fn new(inner: S, layer: AuthenticationLayer) -> Self {
4950
Self { inner, layer }
5051
}
5152

@@ -55,12 +56,12 @@ impl<S> AuthMiddleware<S> {
5556
}
5657

5758
/// Get the layer.
58-
pub fn layer(&self) -> &AuthLayer {
59+
pub fn layer(&self) -> &AuthenticationLayer {
5960
&self.layer
6061
}
6162
}
6263

63-
impl<S> Service<Request> for AuthMiddleware<S>
64+
impl<S> Service<Request> for AuthenticationMiddleware<S>
6465
where
6566
S: Service<Request, Response = Response> + Clone + Send + 'static + Sync,
6667
S::Future: Send + 'static,

htsget-config/README.md

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -422,8 +422,8 @@ following JSON structure, indicating whether the request is allowed, and any reg
422422
{
423423
"name": "chr1",
424424
"format": "BAM",
425-
"start": 100,
426-
"end": 1000
425+
"start": 1000,
426+
"end": 2000
427427
}
428428
]
429429
}
@@ -439,18 +439,18 @@ An [example][auth-example] configuration file is available in the examples direc
439439
With this authorization logic, the server will respond with a `403 Forbidden` error if any of the requested reference
440440
names are not allowed according to the restrictions. For example, if using the above JSON restrictions, a user
441441
requesting `?referenceName=chr1&format=BAM&start=500&end=1500` will receive a `403` error, even though part of the range
442-
is satisfiable (i.e. according to the restrictions, from `start=500` to `end=1000`). In order to address this issue, the
442+
is satisfiable (i.e. according to the restrictions, from `start=1000` to `end=1500`). In order to address this issue, the
443443
following flag can be enabled under the `auth` table:
444444

445445
| Option | Description | Type | Default |
446446
|-------------------|--------------------------------------------------------------------------------------------------|---------|---------|
447447
| `suppress_errors` | Return any available regions according to restrictions, even if the full request is not allowed. | Boolean | `false` |
448448
| `add_hint` | Add a hint to the ticket response that indicates which regions the client is allowed to view. | Boolean | `true` |
449449

450-
To enable this option, htsget-rs needs to be compiled with `--features experimental` as suppressed errors may lead to
451-
less regions being returned than requested, which may not follow the htsget protocol. When this option is used, the
452-
above example with the request: `?referenceName=chr1&format=BAM&start=500&end=1500`, would return reads between `start=500`
453-
and `end=1000` for the reference name. Additionally, there will be another field present in the JSON response which hints
450+
To enable this option, htsget-rs needs to be compiled with `--features experimental` as suppressed errors lead to as
451+
many regions as possible being returned, which may not follow the htsget protocol. When this option is used, the
452+
above example with the request: `?referenceName=chr1&format=BAM&start=500&end=1500`, would return reads between `start=1000`
453+
and `end=1500` for the reference name. Additionally, there will be another field present in the JSON response which hints
454454
to clients that the full range was not satisfied because of authorization restrictions:
455455

456456
```json
@@ -462,22 +462,43 @@ to clients that the full range was not satisfied because of authorization restri
462462
{
463463
"name": "chr1",
464464
"format": "BAM",
465-
"start": 100,
466-
"end": 1000
465+
"start": 1000,
466+
"end": 2000
467467
}
468468
]
469469
}
470470
}
471471
```
472472

473473
The `allowed` field echos the rule defined in the restrictions, and allows clients to plan for a partially returned
474-
response. This field can be removed by setting `add_hint = false` in the `auth` table.
474+
response. This field can be removed by setting `add_hint = false` in the `auth` table.
475+
476+
The following diagram shows how the suppressed response behaves given restrictions based on the start and end restrictions
477+
and the requested range. The response shows the data that the user will receive.
478+
479+
```
480+
Restriction: 1000----------2000
481+
Request: 500------------1500
482+
Resulting response: 1000---1500
483+
484+
Restriction: 1000----------2000
485+
Request: 1500------------2500
486+
Resulting response: 1500---2000
487+
488+
Restriction: 1000----------2000
489+
Request: 500-----1000
490+
Resulting response: empty header only
491+
```
492+
493+
If `suppress_errors = true` was not used, all the above requests would result in an error instead.
475494

476495
Note that when using `suppress_errors = true`, when a client is not authorization to view any of the requested regions,
477-
a non-error response is still returned with an empty reads/variants set. For example, if the client was not authorized
478-
to view `chr1` at all, the response would return urls that correspond to a valid file (with the file header and EOF block),
479-
but no actual reads data. Authorization error responses are still returned if the JWT is invalid or the client is not
480-
allowed to view the requested `<id>` path.
496+
a non-error response is still returned with an empty response containing the file header. For example, if the
497+
client was not authorized to view `chr1` at all, the response would return urls that correspond to a valid file
498+
(with the file header and EOF block), but no actual reads data. Authorization error responses are still returned if the
499+
JWT is invalid or the client is not allowed to view the requested `<id>` path. Parameters are only checked for validity
500+
after authorizing the request, so invalid requests may return an unauthorized or forbidden response instead of a bad
501+
request if the user lacks authorization.
481502

482503
[auth-json]: docs/schemas/auth.schema.json
483504
[auth-example]: docs/examples/auth.toml

0 commit comments

Comments
 (0)