diff --git a/Cargo.lock b/Cargo.lock
index 9686837e0..8a94b3b44 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1041,9 +1041,9 @@ dependencies = [
[[package]]
name = "bit-vec"
-version = "0.7.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22"
+checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
[[package]]
name = "bitflags"
@@ -2786,9 +2786,9 @@ dependencies = [
[[package]]
name = "noodles"
-version = "0.78.0"
+version = "0.80.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81e0702ff73390d2b8f97751bc34cfedcd3f5d39b4e32875e4c64a32d8cc670b"
+checksum = "15ea7a4ffa2e3684ce476156d199e388b465d860d702b739f3e39257ded7d174"
dependencies = [
"noodles-bam",
"noodles-bcf",
@@ -2806,11 +2806,10 @@ dependencies = [
[[package]]
name = "noodles-bam"
-version = "0.65.0"
+version = "0.67.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "406d4768f21c73e3075c0c0d77a5b21bc8b8169c8f0963122607cc410427b727"
+checksum = "53bc69bd00891e3e1c5faffe4f55d00c94d9e53d4bdbe63ec8c7e2b881f3bc85"
dependencies = [
- "bit-vec",
"bstr",
"byteorder",
"bytes",
@@ -2825,9 +2824,9 @@ dependencies = [
[[package]]
name = "noodles-bcf"
-version = "0.58.0"
+version = "0.59.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1f217d811dde790866d3c4902ef713f9dc5c4b96e51935571ddf68399f97ad6"
+checksum = "3206eec367e12e38ff2efb9f11478be5d79a117870f804abc2dec8f27dd10d18"
dependencies = [
"byteorder",
"futures",
@@ -2841,9 +2840,9 @@ dependencies = [
[[package]]
name = "noodles-bgzf"
-version = "0.32.0"
+version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b2fba0f4a64cc897d9396d730a0c444d148daed7de31ad5904ecc673178fc9d"
+checksum = "3b50aaa8f0a3c8a0b738b641a6d1a78d9fd30a899ab2d398779ee3c4eb80f1c1"
dependencies = [
"byteorder",
"bytes",
@@ -2866,9 +2865,9 @@ dependencies = [
[[package]]
name = "noodles-cram"
-version = "0.66.0"
+version = "0.68.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c7f58d900eb9fa1f0ef1a4834a6f71bfa792b25b2fa3b02e582239089907909"
+checksum = "68d1ea4ae713b5e17321ebb20e2f5ca99cadbe2b9e08501a7043458f3a66406e"
dependencies = [
"async-compression",
"bitflags",
@@ -2891,9 +2890,9 @@ dependencies = [
[[package]]
name = "noodles-csi"
-version = "0.37.0"
+version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4bc8001c54f1d8e47e1ac6041a5f27edc99b68bacea3fade9c89059de285aea"
+checksum = "a69e79dbc09bd0cb86d29469ed29066e9a163bce6640527b343bdea458144618"
dependencies = [
"bit-vec",
"byteorder",
@@ -2905,9 +2904,9 @@ dependencies = [
[[package]]
name = "noodles-fasta"
-version = "0.41.0"
+version = "0.43.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7a1662ac3ace299515c982a322e378bbeb4c1bd90fb098d823ef0f3a6abcc00"
+checksum = "0634eec06d20e899a5d99922c40fa5186064d8c675c78690a461ccbb2edc60d1"
dependencies = [
"bstr",
"bytes",
@@ -2919,10 +2918,11 @@ dependencies = [
[[package]]
name = "noodles-fastq"
-version = "0.13.0"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1edf1f924acddeee36304c444e242b9bda52ef9383dc2d7f008fca190753207"
+checksum = "c596792c857f37e6a85e2cf1e68578f5b70f867cad028bf95c1e2b5d7c9c84eb"
dependencies = [
+ "bstr",
"futures",
"memchr",
"tokio",
@@ -2930,9 +2930,9 @@ dependencies = [
[[package]]
name = "noodles-gff"
-version = "0.35.0"
+version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adef59012090b5694b58cad0e4426cd18af404803f942d02e664af607d89ee28"
+checksum = "83d0a43629762ce799147e0d60f80293abe731b65740b7a6a92c1279ef88f0b5"
dependencies = [
"futures",
"indexmap 2.2.6",
@@ -2945,9 +2945,9 @@ dependencies = [
[[package]]
name = "noodles-sam"
-version = "0.62.0"
+version = "0.64.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b80efc627501962e2ff15411d1c011fa9cf3db1b47ddd13dceb1d1134068d5b7"
+checksum = "72da678e9332b32a916f8c5d5a7c4324da11891bc7148077744566981acaf00c"
dependencies = [
"bitflags",
"bstr",
@@ -2963,11 +2963,10 @@ dependencies = [
[[package]]
name = "noodles-tabix"
-version = "0.43.0"
+version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "545e16e229b7f8734b0a2a36bd4c98a5b70128663b16b5201ddadc0d09c28d4a"
+checksum = "263e63f58871224d0cd30ffc4a8531fb4f8f8ec686807febde8e19a69673fe01"
dependencies = [
- "bit-vec",
"byteorder",
"indexmap 2.2.6",
"noodles-bgzf",
@@ -2978,9 +2977,9 @@ dependencies = [
[[package]]
name = "noodles-vcf"
-version = "0.61.0"
+version = "0.63.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6372f1df57c1826d083370b6eac586f331509feed15fd80dda306ef3e7ac68d"
+checksum = "549043d6958379906b1e306804e3c463f24db880da9ab73bd7678592aafb9c89"
dependencies = [
"futures",
"indexmap 2.2.6",
diff --git a/deploy/Dockerfile b/deploy/Dockerfile
index 73edccfa0..4ef68edc4 100644
--- a/deploy/Dockerfile
+++ b/deploy/Dockerfile
@@ -1,4 +1,4 @@
-FROM rust:1.76-slim AS builder
+FROM rust:1.81-slim AS builder
LABEL org.opencontainers.image.source=https://github.com/umccr/htsget-rs
LABEL org.opencontainers.image.url=https://github.com/umccr/htsget-rs/pkgs/container/htsget-rs
@@ -17,9 +17,9 @@ RUN cargo build --all-features --release && \
FROM gcr.io/distroless/cc-debian12
-COPY --from=builder /build/target/release/htsget-actix /usr/local/bin/htsget-actix
+COPY --from=builder /build/target/release/htsget-axum /usr/local/bin/htsget-axum
ENV HTSGET_TICKET_SERVER_ADDR 0.0.0.0:8080
ENV HTSGET_DATA_SERVER_ADDR 0.0.0.0:8081
-CMD [ "htsget-actix" ]
+CMD [ "htsget-axum" ]
diff --git a/deploy/Dockerfile.dockerignore b/deploy/Dockerfile.dockerignore
index da4ac473c..8b535d547 100644
--- a/deploy/Dockerfile.dockerignore
+++ b/deploy/Dockerfile.dockerignore
@@ -1,10 +1,12 @@
*
!/htsget-actix
+!/htsget-axum
!/htsget-config
!/htsget-http
!/htsget-lambda
!/htsget-search
+!/htsget-storage
!/htsget-test
!/Cargo.toml
!/Cargo.lock
diff --git a/deploy/README.md b/deploy/README.md
index 98f18f27b..9fa71a32a 100644
--- a/deploy/README.md
+++ b/deploy/README.md
@@ -13,24 +13,29 @@ The CDK code in this directory constructs a CDK app from [`HtsgetLambdaStack`][h
[`bin/settings.ts`][htsget-settings]:
#### HtsgetSettings
+
These are general settings for the CDK deployment.
-| Name | Description | Type |
-|----------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|
-| `config` | The location of the htsget-rs server config. This must be specified. This config file configures the htsget-rs server. See [htsget-config] for a list of available server configuration options. | `string` |
-| `domain` | The domain name for the Route53 Hosted Zone that the htsget-rs server will be under. This must be specified. A hosted zone with this name will either be looked up or created depending on the value of [`lookupHostedZone?`](#lookupHostedZone). | `string` |
-| `authorizer` | Deployment options related to the authorizer. Note that this option allows specifying an AWS [JWT authorizer][jwt-authorizer]. The JWT authorizer automatically verifies tokens issued by a Cognito user pool. | [`HtsgetJwtAuthSettings`](#htsgetjwtauthsettings) |
-| `subDomain?` | The domain name prefix to use for the htsget-rs server. Together with the [`domain`](#domain), this specifies url that the htsget-rs server will be reachable under. Defaults to `"htsget"`. | `string` |
-| `s3BucketResources?` | The resources that are affected by the bucket policy with actions: `["s3:List*", "s3:Get*"]`. If this is not specified, it defaults to `["arn:aws:s3:::*"]`. This affects which buckets are allowed to be accessed with the policy. | `string[]` |
-| `lookupHostedZone?` | Whether to lookup the hosted zone with the domain name. Defaults to `true`. If `true`, attempts to lookup an existing hosted zone using the domain name. Set this to `false` if you want to create a new hosted zone with the domain name. | `boolean` |
+| Name | Description | Type |
+|--------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|
+| `config` | The location of the htsget-rs server config. This must be specified. This config file configures the htsget-rs server. See [htsget-config] for a list of available server configuration options. | `string` |
+| `domain` | The domain name for the Route53 Hosted Zone that the htsget-rs server will be under. This must be specified. A hosted zone with this name will either be looked up or created depending on the value of [`lookupHostedZone?`](#lookupHostedZone). | `string` |
+| `authorizer` | Deployment options related to the authorizer. Note that this option allows specifying an AWS [JWT authorizer][jwt-authorizer]. The JWT authorizer automatically verifies tokens issued by a Cognito user pool. | [`HtsgetJwtAuthSettings`](#htsgetjwtauthsettings) |
+| `subDomain?` | The domain name prefix to use for the htsget-rs server. Together with the [`domain`](#domain), this specifies url that the htsget-rs server will be reachable under. Defaults to `"htsget"`. | `string` |
+| `s3BucketResources` | The buckets to serve data from. If this is not specified, this defaults to `[]`. This affects which buckets are allowed to be accessed by the policy actions which are `["s3:List*", "s3:Get*"]`. Note that this option does not create buckets, it only gives permission to access them, see the `createS3Buckets` option. This option must be specified to allow `htsget-rs` to access data in buckets that are not created in this stack. | `string[]` |
+| `lookupHostedZone?` | Whether to lookup the hosted zone with the domain name. Defaults to `true`. If `true`, attempts to lookup an existing hosted zone using the domain name. Set this to `false` if you want to create a new hosted zone with the domain name. | `boolean` |
+| `createS3Bucket?` | Whether to create a test bucket. Defaults to true. Buckets are created with [`RemovalPolicy.RETAIN`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.RemovalPolicy.html). The correct access permissions are automatically added. | `boolean` |
+| `bucketName?` | The name of the bucket created using `createS3Bucket`. The name defaults to an automatically generated CDK name, use this option to override that. This option only has an affect is `createS3Buckets` is true. | `string` |
+| `copyTestData?` | Whether to copy test data into the bucket. Defaults to true. This copies the example data under the `data` directory to those buckets. This option only has an affect is `createS3Buckets` is true. | `boolean` |
#### HtsgetJwtAuthSettings
+
These settings are used to determine if the htsget API gateway endpoint is configured to have a JWT authorizer or not.
| Name | Description | Type |
-|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|------------|
+| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `public` | Whether this deployment is public. If this is `true` then no authorizer is present on the API gateway and the options below have no effect. | `boolean` |
-| `jwtAudience?` | A list of the intended recipients of the JWT. A valid JWT must provide an aud that matches at least one entry in this list. | `string[]` |
+| `jwtAudience?` | A list of the intended recipients of the JWT. A valid JWT must provide an aud that matches at least one entry in this list. | `string[]` |
| `cogUserPoolId?` | The cognito user pool id for the authorizer. If this is not set, then a new user pool is created. No user pool is created if [`public`](#public) is true. | `string` |
The [`HtsgetSettings`](#htsgetsettings) are passed into [`HtsgetLambdaStack`][htsget-lambda-stack] in order to change the deployment config. An example of a public instance deployment
@@ -49,7 +54,7 @@ After installing the basic dependencies, complete the following steps:
1. Login to AWS and define `CDK_DEFAULT_*` env variables (if not defined already). You must be authenticated with your AWS cloud to run this step.
2. Install [cargo-lambda], as it is used to compile artifacts that are uploaded to aws lambda.
-3. Define which configuration to use for htsget-rs as stated in the configuration section.
+3. Define which configuration to use for htsget-rs as stated in the configuration section.
Below is a summary of commands to run in this directory:
@@ -67,6 +72,11 @@ npm install
### Deploy to AWS
+> [!IMPORTANT]
+> The default deployment is designed to work out of the box. A bucket with a CDK-generated name is created with test
+> data from the [`data`][data] directory. All deployment settings can be tweaked using the [`settings.ts`][htsget-settings].
+> The only option that must be specified in the `domain`, which determines the domain name to serve htsget-rs at.
+
CDK should be bootstrapped once, if this hasn't been done before:
```sh
@@ -79,6 +89,10 @@ Then to deploy the stack, run:
npx cdk deploy
```
+> [!WARNING]
+> By default this deployment will create a public instance of htsget-rs. Anyone will be able to query the server
+> without authorizing unless you modify the `HtsgetJwtAuthSettings` settings.
+
### Testing the endpoint
When the deployment is finished, the htsget endpoint can be tested by querying it. If a JWT authorizer is configured,
@@ -173,3 +187,4 @@ and a [MinIO][minio] deployment.
[rust]: https://www.rust-lang.org/tools/install
[zig]: https://ziglang.org/
[zig-getting-started]: https://ziglang.org/learn/getting-started/
+[data]: ../data
diff --git a/deploy/bin/settings.ts b/deploy/bin/settings.ts
index 5f4f8a463..e28d44874 100644
--- a/deploy/bin/settings.ts
+++ b/deploy/bin/settings.ts
@@ -4,16 +4,18 @@ import { HtsgetSettings } from "../lib/htsget-lambda-stack";
* Settings to use for the htsget deployment.
*/
export const SETTINGS: HtsgetSettings = {
- config: "config/dev_umccr.toml",
+ config: "config/example_deploy.toml",
+ // Specify the domain to serve htsget-rs under.
domain: "dev.umccr.org",
subDomain: "htsget",
- s3BucketResources: [
- "arn:aws:s3:::org.umccr.demo.sbeacon-data/*",
- "arn:aws:s3:::org.umccr.demo.htsget-rs-data/*",
- ],
- lookupHostedZone: true,
+ s3BucketResources: [],
+ lookupHostedZone: false,
+ createS3Bucket: true,
+ copyTestData: true,
+ // Override the bucket name.
+ // bucketName: "bucket",
jwtAuthorizer: {
- // Set this to true if you want a public instance.
+ // Set this to false if you want a private instance.
public: false,
// jwtAudience: ["audience"],
// cogUserPoolId: "user-pool-id",
diff --git a/deploy/config/dev_umccr.toml b/deploy/config/dev_umccr.toml
index 43f97485d..b92035245 100644
--- a/deploy/config/dev_umccr.toml
+++ b/deploy/config/dev_umccr.toml
@@ -23,6 +23,11 @@ contact_url = "https://umccr.org/"
documentation_url = "https://github.com/umccr/htsget-rs"
environment = "dev"
+[[resolvers]]
+regex = '^(org.umccr.dev.htsget-rs-test-data)/(?P.*)$'
+substitution_string = '$key'
+storage = 'S3'
+
[[resolvers]]
regex = '^(umccr-10c-data-dev)/(?P.*)$'
substitution_string = '$key'
diff --git a/deploy/config/example_deploy.toml b/deploy/config/example_deploy.toml
new file mode 100644
index 000000000..6a487b47c
--- /dev/null
+++ b/deploy/config/example_deploy.toml
@@ -0,0 +1,20 @@
+ticket_server_cors_allow_headers = "All"
+ticket_server_cors_allow_origins = []
+ticket_server_cors_allow_methods = "All"
+ticket_server_cors_allow_credentials = true
+ticket_server_cors_max_age = 300
+
+data_server_enabled = false
+
+name = "umccr-htsget-rs"
+version = "0.1"
+organization_name = "UMCCR"
+organization_url = "https://umccr.org/"
+contact_url = "https://umccr.org/"
+documentation_url = "https://github.com/umccr/htsget-rs"
+environment = "dev"
+
+[[resolvers]]
+regex = '^(?P.*?)/(?P.*)$'
+substitution_string = '$key'
+storage = 'S3'
\ No newline at end of file
diff --git a/deploy/examples/local_storage/README.md b/deploy/examples/local_storage/README.md
index 699a22e98..25ce7d554 100644
--- a/deploy/examples/local_storage/README.md
+++ b/deploy/examples/local_storage/README.md
@@ -41,4 +41,4 @@ default settings, and `curl http://127.0.0.1:8080/reads/data/`, noting the e
[local]: ../../../htsget-config/README.md#resolvers
[compose]: compose.yml
-[data]: ../../../data
\ No newline at end of file
+[data]: ../../../data
diff --git a/deploy/examples/minio/README.md b/deploy/examples/minio/README.md
index a91cab184..97df6f08c 100644
--- a/deploy/examples/minio/README.md
+++ b/deploy/examples/minio/README.md
@@ -13,7 +13,7 @@ set on the MinIO server and DNS resolution must allow accessing the MinIO server
The caveats around the addressing style occur because there are two different addressing styles for S3 buckets, path style, e.g.
`http://minio:9000/bucket`, and virtual-hosted style, e.g. `http://bucket.minio:9000`. AWS has declared path style addressing
-as [deprecated][path-style-deprecated], so this example sets up virtual-hosted style addressing as the default.
+as [deprecated][path-style-deprecated], so this example sets up virtual-hosted style addressing as the default.
## Deployment using Docker
@@ -36,6 +36,7 @@ curl http://127.0.0.1:8080/reads/bam/htsnexus_test_NA12878
```
Outputs:
+
```sh
{
"htsget": {
@@ -68,4 +69,4 @@ docker exec -it minio curl -H "Range: bytes=0-2596770" "http://data.minio:9000/b
[virtual-addressing]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#virtual-hosted-style-access
[path-addressing]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#path-style-access
[compose]: compose.yml
-[data]: ../../../data
\ No newline at end of file
+[data]: ../../../data
diff --git a/deploy/lib/htsget-lambda-stack.ts b/deploy/lib/htsget-lambda-stack.ts
index 3f2164dba..fdd5b39b2 100644
--- a/deploy/lib/htsget-lambda-stack.ts
+++ b/deploy/lib/htsget-lambda-stack.ts
@@ -2,15 +2,22 @@ import { STACK_NAME } from "../bin/htsget-lambda";
import * as TOML from "@iarna/toml";
import { readFileSync } from "fs";
-import { Duration, Stack, StackProps, Tags } from "aws-cdk-lib";
+import {
+ CfnOutput,
+ Duration,
+ RemovalPolicy,
+ Stack,
+ StackProps,
+ Tags,
+} from "aws-cdk-lib";
import { Construct } from "constructs";
import { UserPool } from "aws-cdk-lib/aws-cognito";
import {
+ ManagedPolicy,
+ PolicyStatement,
Role,
ServicePrincipal,
- PolicyStatement,
- ManagedPolicy,
} from "aws-cdk-lib/aws-iam";
import { Architecture } from "aws-cdk-lib/aws-lambda";
import {
@@ -29,6 +36,12 @@ import {
HttpMethod,
} from "aws-cdk-lib/aws-apigatewayv2";
import { HttpJwtAuthorizer } from "aws-cdk-lib/aws-apigatewayv2-authorizers";
+import {
+ BlockPublicAccess,
+ Bucket,
+ BucketEncryption,
+} from "aws-cdk-lib/aws-s3";
+import { BucketDeployment, Source } from "aws-cdk-lib/aws-s3-deployment";
/**
* Settings related to the htsget lambda stack.
@@ -50,10 +63,13 @@ export type HtsgetSettings = {
subDomain?: string;
/**
- * Policies to add to the bucket. If this is not specified, this defaults to `["arn:aws:s3:::*"]`.
+ * The buckets to serve data from. If this is not specified, this defaults to `[]`.
* This affects which buckets are allowed to be accessed by the policy actions which are `["s3:List*", "s3:Get*"]`.
+ * Note that this option does not create buckets, it only gives permission to access them, see the `createS3Buckets`
+ * option. This option must be specified to allow `htsget-rs` to access data in buckets that are not created in
+ * this stack.
*/
- s3BucketResources?: string[];
+ s3BucketResources: string[];
/**
* Whether this deployment is gated behind a JWT authorizer, or if its public.
@@ -66,6 +82,25 @@ export type HtsgetSettings = {
* domain name.
*/
lookupHostedZone?: boolean;
+
+ /**
+ * Whether to create a test bucket. Defaults to true. Buckets are created with
+ * [`RemovalPolicy.RETAIN`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.RemovalPolicy.html).
+ * The correct access permissions are automatically added.
+ */
+ createS3Bucket?: boolean;
+
+ /**
+ * The name of the bucket created using `createS3Bucket`. The name defaults to an automatically generated CDK name,
+ * use this option to override that. This option only has an affect is `createS3Buckets` is true.
+ */
+ bucketName?: string;
+
+ /**
+ * Whether to copy test data into the bucket. Defaults to true. This copies the example data under the `data`
+ * directory to those buckets. This option only has an affect is `createS3Buckets` is true.
+ */
+ copyTestData?: boolean;
};
/**
@@ -151,9 +186,31 @@ export class HtsgetLambdaStack extends Stack {
const s3BucketPolicy = new PolicyStatement({
actions: ["s3:List*", "s3:Get*"],
- resources: settings.s3BucketResources ?? ["arn:aws:s3:::*"],
+ resources: settings.s3BucketResources ?? [],
});
+ if (settings.createS3Bucket) {
+ const bucket = new Bucket(this, "Bucket", {
+ blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
+ encryption: BucketEncryption.S3_MANAGED,
+ enforceSSL: true,
+ removalPolicy: RemovalPolicy.RETAIN,
+ bucketName: settings.bucketName,
+ });
+
+ if (settings.copyTestData) {
+ const dataDir = path.join(__dirname, "..", "..", "data");
+ new BucketDeployment(this, "DeployFiles", {
+ sources: [Source.asset(dataDir)],
+ destinationBucket: bucket,
+ });
+ }
+
+ s3BucketPolicy.addResources(`arn:aws:s3:::${bucket.bucketName}/*`);
+
+ new CfnOutput(this, "HtsgetBucketName", { value: bucket.bucketName });
+ }
+
lambdaRole.addManagedPolicy(
ManagedPolicy.fromAwsManagedPolicyName(
"service-role/AWSLambdaBasicExecutionRole",
@@ -207,6 +264,10 @@ export class HtsgetLambdaStack extends Stack {
jwtAudience: settings.jwtAuthorizer.jwtAudience ?? [],
},
);
+ } else {
+ console.warn(
+ "This will create an instance of htsget-rs that is public! Anyone will be able to query the server without authorization.",
+ );
}
let hostedZone;
diff --git a/deploy/package-lock.json b/deploy/package-lock.json
index c930155ff..fafd0a98c 100644
--- a/deploy/package-lock.json
+++ b/deploy/package-lock.json
@@ -9,46 +9,87 @@
"version": "1.0",
"dependencies": {
"@iarna/toml": "^3.0.0",
- "aws-cdk-lib": "^2.144.0",
+ "aws-cdk-lib": "^2.155.0",
"cargo-lambda-cdk": "^0.0.22",
- "constructs": "^10.1.148",
- "glob": "^10.3.10",
+ "constructs": "^10.3.0",
+ "glob": "^11.0.0",
"source-map-support": "^0.5.21"
},
"bin": {
"htsget_app": "bin/htsget-lambda.js"
},
"devDependencies": {
- "@types/node": "^18.11.18",
- "aws-cdk": "^2.148.1",
- "prettier": "2.8.3",
- "typescript": "^4.9.4"
+ "@types/node": "^22.5.4",
+ "aws-cdk": "^2.155.0",
+ "prettier": "^3.3.3",
+ "typescript": "^5.5.4"
}
},
"node_modules/@aws-cdk/asset-awscli-v1": {
"version": "2.2.202",
"resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.202.tgz",
- "integrity": "sha512-JqlF0D4+EVugnG5dAsNZMqhu3HW7ehOXm5SDMxMbXNDMdsF0pxtQKNHRl52z1U9igsHmaFpUgSGjbhAJ+0JONg=="
+ "integrity": "sha512-JqlF0D4+EVugnG5dAsNZMqhu3HW7ehOXm5SDMxMbXNDMdsF0pxtQKNHRl52z1U9igsHmaFpUgSGjbhAJ+0JONg==",
+ "license": "Apache-2.0"
},
"node_modules/@aws-cdk/asset-kubectl-v20": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.2.tgz",
- "integrity": "sha512-3M2tELJOxQv0apCIiuKQ4pAbncz9GuLwnKFqxifWfe77wuMxyTRPmxssYHs42ePqzap1LT6GDcPygGs+hHstLg=="
+ "integrity": "sha512-3M2tELJOxQv0apCIiuKQ4pAbncz9GuLwnKFqxifWfe77wuMxyTRPmxssYHs42ePqzap1LT6GDcPygGs+hHstLg==",
+ "license": "Apache-2.0"
},
"node_modules/@aws-cdk/asset-node-proxy-agent-v6": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.3.tgz",
- "integrity": "sha512-twhuEG+JPOYCYPx/xy5uH2+VUsIEhPTzDY0F1KuB+ocjWWB/KEDiOVL19nHvbPCB6fhWnkykXEMJ4HHcKvjtvg=="
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.1.0.tgz",
+ "integrity": "sha512-7bY3J8GCVxLupn/kNmpPc5VJz8grx+4RKfnnJiO1LG+uxkZfANZG3RMHhE+qQxxwkyQ9/MfPtTpf748UhR425A==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@aws-cdk/cloud-assembly-schema": {
+ "version": "36.0.24",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-36.0.24.tgz",
+ "integrity": "sha512-dHyb4lvd6nbNHLVvdyxVPgwc0MyzN3VzIJnWwGJWKOIwVqL7hvU2NkQQrktY9T2MtdhzUdDFm9qluxuLRV5Cfw==",
+ "bundleDependencies": [
+ "jsonschema",
+ "semver"
+ ],
+ "license": "Apache-2.0",
+ "dependencies": {
+ "jsonschema": "^1.4.1",
+ "semver": "^7.6.3"
+ },
+ "engines": {
+ "node": ">= 18.18.0"
+ }
+ },
+ "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/jsonschema": {
+ "version": "1.4.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/semver": {
+ "version": "7.6.3",
+ "inBundle": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
"node_modules/@iarna/toml": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-3.0.0.tgz",
- "integrity": "sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q=="
+ "integrity": "sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q==",
+ "license": "ISC"
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "license": "ISC",
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
@@ -65,21 +106,27 @@
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "license": "MIT",
"optional": true,
"engines": {
"node": ">=14"
}
},
"node_modules/@types/node": {
- "version": "18.13.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz",
- "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==",
- "dev": true
+ "version": "22.5.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz",
+ "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
},
"node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "license": "MIT",
"engines": {
"node": ">=12"
},
@@ -91,6 +138,7 @@
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "license": "MIT",
"engines": {
"node": ">=12"
},
@@ -99,10 +147,11 @@
}
},
"node_modules/aws-cdk": {
- "version": "2.148.1",
- "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.148.1.tgz",
- "integrity": "sha512-wiAi4vFJ52A42PpU3zRi2gVDqbTXSBVFrqKRqEd8wYL1mqa0qMv9FR35NsgbM1RL9s7g5ZljYvl+G2tXpcp5Eg==",
+ "version": "2.155.0",
+ "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.155.0.tgz",
+ "integrity": "sha512-AV7Ym/o7/xyDh6sqcGatWD6Bqa7Swe0OWJq+1srVww0MdBiy5yM3zYAA1+ZeqZNjFQThJPA+pYZQFTgojuaVBA==",
"dev": true,
+ "license": "Apache-2.0",
"bin": {
"cdk": "bin/cdk"
},
@@ -114,9 +163,9 @@
}
},
"node_modules/aws-cdk-lib": {
- "version": "2.144.0",
- "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.144.0.tgz",
- "integrity": "sha512-DpyIyTs8NHX6WgAyYM2mGorirIk+eTjWzXGQRfzAe40qkwcqsb5Ax4JEl5gz1OEo9QIJIgWDtmImgWN0tUbILA==",
+ "version": "2.155.0",
+ "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.155.0.tgz",
+ "integrity": "sha512-QGzDhLldBXsyOUmhgtZ98PiOUS2g1Mb5MO08FiOvQn3+KSyJjQdq0GoyxtDpCNGLaWmIfcyrtB9aDhod38fl9g==",
"bundleDependencies": [
"@balena/dockerignore",
"case",
@@ -130,10 +179,12 @@
"yaml",
"mime-types"
],
+ "license": "Apache-2.0",
"dependencies": {
"@aws-cdk/asset-awscli-v1": "^2.2.202",
"@aws-cdk/asset-kubectl-v20": "^2.1.2",
"@aws-cdk/asset-node-proxy-agent-v6": "^2.0.3",
+ "@aws-cdk/cloud-assembly-schema": "^36.0.5",
"@balena/dockerignore": "^1.0.2",
"case": "1.6.3",
"fs-extra": "^11.2.0",
@@ -142,7 +193,7 @@
"mime-types": "^2.1.35",
"minimatch": "^3.1.2",
"punycode": "^2.3.1",
- "semver": "^7.6.0",
+ "semver": "^7.6.2",
"table": "^6.8.2",
"yaml": "1.10.2"
},
@@ -159,7 +210,7 @@
"license": "Apache-2.0"
},
"node_modules/aws-cdk-lib/node_modules/ajv": {
- "version": "8.13.0",
+ "version": "8.16.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
@@ -319,17 +370,6 @@
"inBundle": true,
"license": "MIT"
},
- "node_modules/aws-cdk-lib/node_modules/lru-cache": {
- "version": "6.0.0",
- "inBundle": true,
- "license": "ISC",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/aws-cdk-lib/node_modules/mime-db": {
"version": "1.52.0",
"inBundle": true,
@@ -377,12 +417,9 @@
}
},
"node_modules/aws-cdk-lib/node_modules/semver": {
- "version": "7.6.0",
+ "version": "7.6.2",
"inBundle": true,
"license": "ISC",
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
"bin": {
"semver": "bin/semver.js"
},
@@ -461,11 +498,6 @@
"punycode": "^2.1.0"
}
},
- "node_modules/aws-cdk-lib/node_modules/yallist": {
- "version": "4.0.0",
- "inBundle": true,
- "license": "ISC"
- },
"node_modules/aws-cdk-lib/node_modules/yaml": {
"version": "1.10.2",
"inBundle": true,
@@ -477,12 +509,14 @@
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
},
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
@@ -490,7 +524,8 @@
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "license": "MIT"
},
"node_modules/cargo-lambda-cdk": {
"version": "0.0.22",
@@ -499,6 +534,7 @@
"bundleDependencies": [
"js-toml"
],
+ "license": "MIT",
"dependencies": {
"js-toml": "^0.1.1"
},
@@ -607,6 +643,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -617,20 +654,23 @@
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
},
"node_modules/constructs": {
- "version": "10.1.246",
- "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.1.246.tgz",
- "integrity": "sha512-2U2hnAuA4tCGGjHk/TulZfSlPobTyokEh+Azuch9nivv2yGI7/5nXDHC14i2MU/K7HFnnkQOHRSrwKSmOZkT/w==",
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.3.0.tgz",
+ "integrity": "sha512-vbK8i3rIb/xwZxSpTjz3SagHn1qq9BChLEfy5Hf6fB3/2eFbrwt2n9kHwQcS0CPTRBesreeAcsJfMq2229FnbQ==",
+ "license": "Apache-2.0",
"engines": {
- "node": ">= 14.17.0"
+ "node": ">= 16.14.0"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@@ -643,17 +683,20 @@
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "license": "MIT"
},
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "license": "MIT"
},
"node_modules/foreground-child": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
- "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+ "license": "ISC",
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
@@ -671,6 +714,7 @@
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
+ "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -680,21 +724,23 @@
}
},
"node_modules/glob": {
- "version": "10.3.10",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
- "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
+ "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
+ "license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
- "jackspeak": "^2.3.5",
- "minimatch": "^9.0.1",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
- "path-scurry": "^1.10.1"
+ "jackspeak": "^4.0.1",
+ "minimatch": "^10.0.0",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -704,6 +750,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -711,17 +758,19 @@
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
},
"node_modules/jackspeak": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
- "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz",
+ "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==",
+ "license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
- "node": ">=14"
+ "node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -731,68 +780,80 @@
}
},
"node_modules/lru-cache": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz",
- "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==",
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz",
+ "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==",
+ "license": "ISC",
"engines": {
- "node": "14 || >=16.14"
+ "node": "20 || >=22"
}
},
"node_modules/minimatch": {
- "version": "9.0.3",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
- "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
+ "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
+ "license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minipass": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
- "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
+ "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
+ "license": "BlueOak-1.0.0"
+ },
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/path-scurry": {
- "version": "1.10.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
- "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
+ "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
+ "license": "BlueOak-1.0.0",
"dependencies": {
- "lru-cache": "^9.1.1 || ^10.0.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/prettier": {
- "version": "2.8.3",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
- "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
+ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"dev": true,
+ "license": "MIT",
"bin": {
- "prettier": "bin-prettier.js"
+ "prettier": "bin/prettier.cjs"
},
"engines": {
- "node": ">=10.13.0"
+ "node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
@@ -802,6 +863,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
},
@@ -813,6 +875,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -821,6 +884,7 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
"engines": {
"node": ">=14"
},
@@ -832,6 +896,7 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
@@ -840,6 +905,7 @@
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
@@ -849,6 +915,7 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
@@ -866,6 +933,7 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -879,6 +947,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -886,12 +955,14 @@
"node_modules/string-width-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
},
"node_modules/string-width-cjs/node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -903,6 +974,7 @@
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
@@ -918,6 +990,7 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -929,27 +1002,37 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/typescript": {
- "version": "4.9.5",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
- "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "version": "5.5.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
+ "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
"dev": true,
+ "license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
- "node": ">=4.2.0"
+ "node": ">=14.17"
}
},
+ "node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
},
@@ -964,6 +1047,7 @@
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
@@ -981,6 +1065,7 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -997,6 +1082,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -1005,6 +1091,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -1018,12 +1105,14 @@
"node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
},
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -1037,6 +1126,7 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
diff --git a/deploy/package.json b/deploy/package.json
index e73a4ed62..f8def646f 100644
--- a/deploy/package.json
+++ b/deploy/package.json
@@ -10,17 +10,17 @@
"cdk": "cdk"
},
"devDependencies": {
- "@types/node": "^18.11.18",
- "aws-cdk": "^2.148.1",
- "prettier": "2.8.3",
- "typescript": "^4.9.4"
+ "@types/node": "^22.5.4",
+ "aws-cdk": "^2.155.0",
+ "prettier": "^3.3.3",
+ "typescript": "^5.5.4"
},
"dependencies": {
"@iarna/toml": "^3.0.0",
- "aws-cdk-lib": "^2.144.0",
+ "aws-cdk-lib": "^2.155.0",
"cargo-lambda-cdk": "^0.0.22",
- "constructs": "^10.1.148",
- "glob": "^10.3.10",
+ "constructs": "^10.3.0",
+ "glob": "^11.0.0",
"source-map-support": "^0.5.21"
}
}
diff --git a/htsget-actix/src/lib.rs b/htsget-actix/src/lib.rs
index 9d12a28f0..98ea64c20 100644
--- a/htsget-actix/src/lib.rs
+++ b/htsget-actix/src/lib.rs
@@ -175,8 +175,16 @@ mod tests {
struct ActixTestRequest(T);
impl TestRequest for ActixTestRequest {
- fn insert_header(self, header: TestHeader>) -> Self {
- Self(self.0.insert_header(header.into_tuple()))
+ fn insert_header(
+ self,
+ header: TestHeader, impl Into>,
+ ) -> Self {
+ let (name, value) = header.into_tuple();
+ Self(
+ self
+ .0
+ .insert_header((name.to_string(), value.to_str().unwrap())),
+ )
}
fn set_payload(self, payload: impl Into) -> Self {
@@ -187,11 +195,15 @@ mod tests {
Self(self.0.uri(&uri.into()))
}
- fn method(self, method: impl Into) -> Self {
+ fn method(self, method: impl Into) -> Self {
Self(
- self
- .0
- .method(method.into().parse().expect("expected valid method")),
+ self.0.method(
+ method
+ .into()
+ .to_string()
+ .parse()
+ .expect("expected valid method"),
+ ),
)
}
}
@@ -224,7 +236,7 @@ mod tests {
&self.config
}
- fn get_request(&self) -> ActixTestRequest {
+ fn request(&self) -> ActixTestRequest {
ActixTestRequest(test::TestRequest::default())
}
diff --git a/htsget-actix/src/main.rs b/htsget-actix/src/main.rs
index 1f8a60193..b71c5b0a0 100644
--- a/htsget-actix/src/main.rs
+++ b/htsget-actix/src/main.rs
@@ -8,9 +8,7 @@ use htsget_config::command;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
- if let Some(path) =
- Config::parse_args_with_command(command!()).expect("expected valid command parsing")
- {
+ if let Some(path) = Config::parse_args_with_command(command!())? {
let config = Config::from_path(&path)?;
config.setup_tracing()?;
diff --git a/htsget-axum/src/server/data.rs b/htsget-axum/src/server/data.rs
index bdadfed1f..ff641c816 100644
--- a/htsget-axum/src/server/data.rs
+++ b/htsget-axum/src/server/data.rs
@@ -88,7 +88,7 @@ mod tests {
use async_trait::async_trait;
use http::header::HeaderName;
- use http::{HeaderMap, HeaderValue, Method};
+ use http::{HeaderMap, Method};
use reqwest::{Client, ClientBuilder, RequestBuilder};
use tempfile::{tempdir, TempDir};
use tokio::fs::{create_dir, File};
@@ -118,11 +118,11 @@ mod tests {
}
impl TestRequest for DataTestRequest {
- fn insert_header(mut self, header: Header>) -> Self {
- self.headers.insert(
- HeaderName::from_str(&header.name.into()).unwrap(),
- HeaderValue::from_str(&header.value.into()).unwrap(),
- );
+ fn insert_header(
+ mut self,
+ header: Header, impl Into>,
+ ) -> Self {
+ self.headers.insert(header.name.into(), header.value.into());
self
}
@@ -136,8 +136,8 @@ mod tests {
self
}
- fn method(mut self, method: impl Into) -> Self {
- self.method = method.into().parse().unwrap();
+ fn method(mut self, method: impl Into) -> Self {
+ self.method = method.into();
self
}
}
@@ -186,7 +186,7 @@ mod tests {
&self.config
}
- fn get_request(&self) -> DataTestRequest {
+ fn request(&self) -> DataTestRequest {
DataTestRequest::default()
}
@@ -294,8 +294,8 @@ mod tests {
let test_server = DataTestServer::default();
let request = test_server
- .get_request()
- .method(Method::GET.to_string())
+ .request()
+ .method(Method::GET)
.uri(format!("{scheme}://localhost:{port}/data/key1"));
let response = test_server.test_server(request, "".to_string()).await;
diff --git a/htsget-axum/src/server/ticket.rs b/htsget-axum/src/server/ticket.rs
index 79eaa8ff7..5abb5cbc1 100644
--- a/htsget-axum/src/server/ticket.rs
+++ b/htsget-axum/src/server/ticket.rs
@@ -105,7 +105,6 @@ mod tests {
use std::convert::Infallible;
use std::path::Path;
use std::result;
- use std::str::FromStr;
use super::*;
use async_trait::async_trait;
@@ -119,7 +118,7 @@ mod tests {
TestRequest, TestServer,
};
use http::header::HeaderName;
- use http::Request;
+ use http::{Method, Request};
use tempfile::TempDir;
use tower::ServiceExt;
@@ -130,15 +129,14 @@ mod tests {
struct AxumTestRequest(T);
impl TestRequest for AxumTestRequest> {
- fn insert_header(mut self, header: Header>) -> Self {
- self.0.headers_mut().insert(
- HeaderName::from_str(&header.name.into()).expect("expected valid header name"),
- header
- .value
- .into()
- .parse()
- .expect("expected valid header value"),
- );
+ fn insert_header(
+ mut self,
+ header: Header, impl Into>,
+ ) -> Self {
+ self
+ .0
+ .headers_mut()
+ .insert(header.name.into(), header.value.into());
self
}
@@ -153,8 +151,8 @@ mod tests {
self
}
- fn method(mut self, method: impl Into) -> Self {
- *self.0.method_mut() = method.into().parse().expect("expected valid method");
+ fn method(mut self, method: impl Into) -> Self {
+ *self.0.method_mut() = method.into();
self
}
}
@@ -187,7 +185,7 @@ mod tests {
&self.config
}
- fn get_request(&self) -> AxumTestRequest> {
+ fn request(&self) -> AxumTestRequest> {
AxumTestRequest(Request::default())
}
@@ -306,4 +304,9 @@ mod tests {
async fn cors_preflight_request() {
cors::test_cors_preflight_request(&AxumTestServer::default()).await;
}
+
+ #[tokio::test]
+ async fn test_errors() {
+ server::test_errors(&AxumTestServer::default()).await;
+ }
}
diff --git a/htsget-config/Cargo.toml b/htsget-config/Cargo.toml
index d783817db..87a0e26e4 100644
--- a/htsget-config/Cargo.toml
+++ b/htsget-config/Cargo.toml
@@ -18,7 +18,7 @@ default = []
[dependencies]
thiserror = "1"
async-trait = "0.1"
-noodles = { version = "0.78", features = ["core"] }
+noodles = { version = "0.80", features = ["core"] }
serde = { version = "1", features = ["derive"] }
serde_with = "3"
serde_regex = "1"
diff --git a/htsget-lambda/README.md b/htsget-lambda/README.md
index cb69330be..881ab236c 100644
--- a/htsget-lambda/README.md
+++ b/htsget-lambda/README.md
@@ -38,8 +38,8 @@ See [htsget-search] for details on how to structure files.
### As a library
-There shouldn't be any need to interact with this crate as a library, however some functions which deal with
-routing queries are exposed in the public API.
+There is no need to interact with this crate as a library. Note that the Lambda function itself doesn't have any
+library code, and it instead uses `htsget-axum`. Please use that crate for functionality related to routing.
#### Feature flags
diff --git a/htsget-lambda/src/handlers/get.rs b/htsget-lambda/src/handlers/get.rs
deleted file mode 100644
index 2a95e0ad7..000000000
--- a/htsget-lambda/src/handlers/get.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use std::collections::HashMap;
-use std::sync::Arc;
-
-use lambda_http::http;
-use lambda_http::http::HeaderMap;
-use tracing::info;
-use tracing::instrument;
-
-use htsget_config::types::Request;
-use htsget_http::{get as htsget_get, Endpoint};
-use htsget_search::HtsGet;
-
-use crate::handlers::handle_response;
-use crate::{Body, Response};
-
-/// Get request reads endpoint
-#[instrument(skip(searcher))]
-pub async fn get(
- id: String,
- searcher: Arc,
- query: HashMap,
- headers: HeaderMap,
- endpoint: Endpoint,
-) -> http::Result> {
- let request = Request::new(id, query, headers);
-
- info!(request = ?request, "GET request");
-
- handle_response(htsget_get(searcher, request, endpoint).await)
-}
diff --git a/htsget-lambda/src/handlers/mod.rs b/htsget-lambda/src/handlers/mod.rs
deleted file mode 100644
index 16a4e4a46..000000000
--- a/htsget-lambda/src/handlers/mod.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-//! Module primarily providing http response functionality for the htsget endpoints.
-//!
-
-use lambda_http::http;
-use lambda_http::http::{header, StatusCode};
-use serde::Serialize;
-use serde_json::Error;
-
-use htsget_config::types::JsonResponse;
-use htsget_http::{HtsGetError, Result};
-
-use crate::{Body, Response};
-
-pub mod get;
-pub mod post;
-pub mod service_info;
-
-/// New type used for formatting a http response.
-pub struct FormatJson(T);
-
-impl FormatJson {
- pub fn into_inner(self) -> T {
- self.0
- }
-}
-
-impl TryFrom> for Response {
- type Error = http::Error;
-
- fn try_from(value: FormatJson) -> http::Result {
- let mut body = match serde_json::to_string_pretty(&value.into_inner()) {
- Ok(body) => body,
- Err(e) => return Ok(FormatJson::try_from(e)?.into_inner()),
- };
- body.push('\n');
-
- Response::builder()
- .status(StatusCode::OK)
- .header(header::CONTENT_TYPE, mime::APPLICATION_JSON.as_ref())
- .body(Body::from(body))
- }
-}
-
-impl TryFrom for FormatJson> {
- type Error = http::Error;
-
- fn try_from(error: Error) -> http::Result {
- Ok(Self(
- Response::builder()
- .status(StatusCode::INTERNAL_SERVER_ERROR)
- .header(header::CONTENT_TYPE, mime::TEXT_PLAIN_UTF_8.as_ref())
- .body(Body::from(error.to_string()))?,
- ))
- }
-}
-
-impl TryFrom for FormatJson> {
- type Error = http::Error;
-
- fn try_from(error: HtsGetError) -> http::Result {
- let (json, status_code) = error.to_json_representation();
- let mut response: Response = FormatJson(json).try_into()?;
- *response.status_mut() = status_code;
- Ok(Self(response))
- }
-}
-
-/// Handles a response, converting errors to json and using the proper HTTP status code.
-fn handle_response(response: Result) -> http::Result> {
- match response {
- Err(error) => Ok(FormatJson::try_from(error)?.into_inner()),
- Ok(json) => FormatJson(json).try_into(),
- }
-}
-
-#[cfg(test)]
-mod tests {
- use lambda_http::http::{header, HeaderMap, Response, StatusCode};
- use lambda_http::Body;
- use mime::Mime;
- use serde::ser::Error;
- use serde::{Serialize, Serializer};
- use serde_json::{json, Value};
-
- use crate::handlers::FormatJson;
-
- struct TestError;
-
- impl Serialize for TestError {
- fn serialize(&self, _: S) -> Result
- where
- S: Serializer,
- {
- Err(Error::custom(json!({"value": "1"})))
- }
- }
-
- #[test]
- fn into_response() {
- let expected_body = json!({"value": "1"});
- let json = FormatJson(expected_body.clone());
- test_into_response(
- json.try_into().unwrap(),
- expected_body,
- StatusCode::OK,
- mime::APPLICATION_JSON,
- );
- }
-
- #[test]
- fn into_response_error() {
- let json = FormatJson(TestError);
- test_into_response(
- json.try_into().unwrap(),
- json!({"value": "1"}),
- StatusCode::INTERNAL_SERVER_ERROR,
- mime::TEXT_PLAIN_UTF_8,
- );
- }
-
- fn test_into_response(
- response: Response,
- expected_body: Value,
- expected_status_code: StatusCode,
- expected_content_type: Mime,
- ) {
- let mut expected_headers = HeaderMap::new();
- expected_headers.insert(
- header::CONTENT_TYPE,
- expected_content_type.as_ref().parse().unwrap(),
- );
-
- assert_eq!(response.status(), expected_status_code);
- assert_eq!(response.headers(), &expected_headers);
-
- let bytes: &[u8] = response.body().as_ref();
- let value: Value = serde_json::from_slice(bytes).unwrap();
- assert_eq!(value, expected_body);
- }
-}
diff --git a/htsget-lambda/src/handlers/post.rs b/htsget-lambda/src/handlers/post.rs
deleted file mode 100644
index 2babde158..000000000
--- a/htsget-lambda/src/handlers/post.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-use std::collections::HashMap;
-use std::sync::Arc;
-
-use lambda_http::http;
-use lambda_http::http::HeaderMap;
-use tracing::info;
-use tracing::instrument;
-
-use htsget_config::types::Request;
-use htsget_http::{post as htsget_post, Endpoint, PostRequest};
-use htsget_search::HtsGet;
-
-use crate::handlers::handle_response;
-use crate::{Body, Response};
-
-/// Post request reads endpoint
-#[instrument(skip(searcher))]
-pub async fn post(
- id: String,
- searcher: Arc,
- query: HashMap,
- body: PostRequest,
- headers: HeaderMap,
- endpoint: Endpoint,
-) -> http::Result> {
- let request = Request::new(id, query, headers);
-
- info!(body = ?body, "POST request");
-
- handle_response(htsget_post(searcher, body, request, endpoint).await)
-}
diff --git a/htsget-lambda/src/handlers/service_info.rs b/htsget-lambda/src/handlers/service_info.rs
deleted file mode 100644
index f3d3c300a..000000000
--- a/htsget-lambda/src/handlers/service_info.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-use std::sync::Arc;
-
-use lambda_http::http;
-use tracing::info;
-use tracing::instrument;
-
-use htsget_http::get_service_info_json as get_base_service_info_json;
-use htsget_http::Endpoint;
-use htsget_search::HtsGet;
-
-use crate::handlers::FormatJson;
-use crate::ServiceInfo;
-use crate::{Body, Response};
-
-/// Service info endpoint.
-#[instrument(skip(searcher))]
-pub fn get_service_info_json(
- searcher: Arc,
- endpoint: Endpoint,
- config: &ServiceInfo,
-) -> http::Result> {
- info!(endpoint = ?endpoint, "service info request");
- FormatJson(get_base_service_info_json(endpoint, searcher, config)).try_into()
-}
diff --git a/htsget-lambda/src/lib.rs b/htsget-lambda/src/lib.rs
index 9dc249223..5456a94e7 100644
--- a/htsget-lambda/src/lib.rs
+++ b/htsget-lambda/src/lib.rs
@@ -1,781 +1,3 @@
-//! Library providing the routing and http responses for aws lambda requests.
+//! htsget-lambda no longer has any library functions. Please use `htsget-axum` for similar
+//! functionality on routers and logic.
//!
-
-use std::collections::HashMap;
-use std::future::Future;
-use std::sync::Arc;
-
-use lambda_http::ext::RequestExt;
-use lambda_http::http::{Method, StatusCode, Uri};
-use lambda_http::tower::ServiceBuilder;
-use lambda_http::{http, service_fn, Body, Request, RequestPayloadExt, Response};
-use lambda_runtime::Error;
-use tracing::instrument;
-use tracing::{debug, info};
-
-use htsget_axum::server::configure_cors;
-use htsget_config::config::cors::CorsConfig;
-pub use htsget_config::config::{Config, DataServerConfig, ServiceInfo, TicketServerConfig};
-pub use htsget_config::storage::Storage;
-use htsget_http::{Endpoint, PostRequest};
-use htsget_search::HtsGet;
-
-use crate::handlers::get::get;
-use crate::handlers::post::post;
-use crate::handlers::service_info::get_service_info_json;
-
-pub mod handlers;
-
-/// A request route, with a method, endpoint and route type.
-#[derive(Debug, PartialEq, Eq)]
-pub struct Route {
- method: HtsgetMethod,
- endpoint: Endpoint,
- route_type: RouteType,
-}
-
-/// Valid htsget http request methods.
-#[derive(Debug, PartialEq, Eq, Clone, Copy)]
-pub enum HtsgetMethod {
- Get,
- Post,
-}
-
-/// A route type, which is either the service info endpoint, or an id represented by a string.
-#[derive(Debug, PartialEq, Eq)]
-pub enum RouteType {
- ServiceInfo,
- Id(String),
-}
-
-impl Route {
- pub fn new(method: HtsgetMethod, endpoint: Endpoint, route_type: RouteType) -> Self {
- Self {
- method,
- endpoint,
- route_type,
- }
- }
-
- /// Gets the Route if the request is valid, otherwise returns an error with a response.
- pub fn get_route(method: &Method, uri: &Uri) -> Result>> {
- let with_endpoint = |endpoint: Endpoint, endpoint_type: &str| {
- if endpoint_type.is_empty() {
- Err(
- Response::builder()
- .status(StatusCode::NOT_FOUND)
- .body(Body::Empty),
- )
- } else {
- let method = match *method {
- Method::GET => Ok(HtsgetMethod::Get),
- Method::POST => Ok(HtsgetMethod::Post),
- _ => Err(
- Response::builder()
- .status(StatusCode::METHOD_NOT_ALLOWED)
- .body(Body::Empty),
- ),
- }?;
- if endpoint_type == "service-info" {
- Ok(Route::new(method, endpoint, RouteType::ServiceInfo))
- } else {
- Ok(Route::new(
- method,
- endpoint,
- RouteType::Id(endpoint_type.to_string()),
- ))
- }
- }
- };
-
- uri.path().strip_prefix("/reads/").map_or_else(
- || {
- uri.path().strip_prefix("/variants/").map_or_else(
- || {
- Err(
- Response::builder()
- .status(StatusCode::NOT_FOUND)
- .body(Body::Empty),
- )
- },
- |variants| with_endpoint(Endpoint::Variants, variants),
- )
- },
- |reads| with_endpoint(Endpoint::Reads, reads),
- )
- }
-
- pub fn method(&self) -> HtsgetMethod {
- self.method
- }
-
- pub fn endpoint(&self) -> &Endpoint {
- &self.endpoint
- }
-
- pub fn route_type(&self) -> &RouteType {
- &self.route_type
- }
-}
-
-impl TryFrom<&Request> for Route {
- type Error = http::Result>;
-
- fn try_from(request: &Request) -> Result {
- Self::get_route(
- request.method(),
- &request
- .raw_http_path()
- .parse::()
- .map_err(|err| Err(err.into()))?,
- )
- }
-}
-
-/// A Router is a struct which handles routing any htsget requests to the htsget search, using the config.
-pub struct Router<'a, H> {
- searcher: Arc,
- config_service_info: &'a ServiceInfo,
-}
-
-impl<'a, H: HtsGet + Send + Sync + 'static> Router<'a, H> {
- pub fn new(searcher: Arc, config_service_info: &'a ServiceInfo) -> Self {
- Self {
- searcher,
- config_service_info,
- }
- }
-
- /// Routes the request to the relevant htsget search endpoint using the lambda request and route.
- pub async fn route_request_with_route(
- &self,
- request: Request,
- route: Route,
- ) -> http::Result> {
- match route {
- Route {
- endpoint,
- route_type: RouteType::ServiceInfo,
- ..
- } => get_service_info_json(self.searcher.clone(), endpoint, self.config_service_info),
- Route {
- method: HtsgetMethod::Get,
- endpoint,
- route_type: RouteType::Id(id),
- } => {
- get(
- id,
- self.searcher.clone(),
- Self::extract_query(&request),
- request.headers().clone(),
- endpoint,
- )
- .await
- }
- Route {
- method: HtsgetMethod::Post,
- endpoint,
- route_type: RouteType::Id(id),
- } => match Self::extract_query_from_payload(&request) {
- None => Ok(
- Response::builder()
- .status(StatusCode::UNSUPPORTED_MEDIA_TYPE)
- .body(Body::Empty)?,
- ),
- Some(query) => {
- post(
- id,
- self.searcher.clone(),
- Self::extract_query(&request),
- query,
- request.headers().clone(),
- endpoint,
- )
- .await
- }
- },
- }
- }
-
- /// Routes the request to the relevant htsget search endpoint using the lambda request, returning a http response.
- pub async fn route_request(&self, request: Request) -> http::Result> {
- match Route::try_from(&request) {
- Ok(route) => self.route_request_with_route(request, route).await,
- Err(err) => err,
- }
- }
-
- /// Extracts post request query parameters.
- #[instrument(level = "debug", ret)]
- fn extract_query_from_payload(request: &Request) -> Option {
- if request.body().is_empty() {
- Some(PostRequest::default())
- } else {
- let payload = request.payload::();
- debug!(payload = ?payload, "POST request payload");
- // Allows null/empty bodies.
- payload.ok()?
- }
- }
-
- /// Extract get request query parameters.
- #[instrument(level = "debug", ret)]
- fn extract_query(request: &Request) -> HashMap {
- let mut query = HashMap::new();
- // Silently ignores all but the last query key, for keys that are present more than once.
- // This is the way actix-web does it, but should we return an error instead if a key is present
- // more than once?
- for (key, value) in request.query_string_parameters().iter() {
- query.insert(key.to_string(), value.to_string());
- }
- debug!(query = ?query, "GET request query");
- query
- }
-}
-
-pub async fn handle_request_service_fn(cors: CorsConfig, service: F) -> Result<(), Error>
-where
- F: FnMut(Request) -> Fut,
- Fut: Future