CDN endpoints with and without /artifact-type part (#4484)

This commit is contained in:
Kamil Kisiela 2024-04-11 09:00:31 +02:00 committed by GitHub
parent 32a4f5f6f6
commit 7ddf063984
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 51 additions and 15 deletions

View file

@ -0,0 +1,5 @@
---
"@graphql-hive/client": minor
---
Accepts now CDN endpoint without /services /supergraph etc subdirectories

View file

@ -8,21 +8,24 @@ import type {
HivePluginOptions,
SupergraphSDLFetcherOptions,
} from './internal/types.js';
import { isHiveClient } from './internal/utils.js';
import { isHiveClient, joinUrl } from './internal/utils.js';
import { version } from './version.js';
export function createSupergraphSDLFetcher({ endpoint, key }: SupergraphSDLFetcherOptions) {
export function createSupergraphSDLFetcher(options: SupergraphSDLFetcherOptions) {
let cacheETag: string | null = null;
let cached: {
id: string;
supergraphSdl: string;
} | null = null;
const endpoint = options.endpoint.endsWith('/supergraph')
? options.endpoint
: joinUrl(options.endpoint, 'supergraph');
return function supergraphSDLFetcher() {
const headers: {
[key: string]: string;
} = {
'X-Hive-CDN-Key': key,
'X-Hive-CDN-Key': options.key,
'User-Agent': `hive-client/${version}`,
};
@ -44,7 +47,7 @@ export function createSupergraphSDLFetcher({ endpoint, key }: SupergraphSDLFetch
const fetchWithRetry = (): Promise<{ id: string; supergraphSdl: string }> => {
return axios
.get(endpoint + '/supergraph', {
.get(endpoint, {
headers,
})
.then(response => {

View file

@ -1,6 +1,7 @@
import { createHash } from 'node:crypto';
import axios from 'axios';
import type { SchemaFetcherOptions, ServicesFetcherOptions } from './internal/types.js';
import { joinUrl } from './internal/utils.js';
import { version } from './version.js';
interface Schema {
@ -9,18 +10,22 @@ interface Schema {
name: string;
}
function createFetcher({ endpoint, key }: SchemaFetcherOptions & ServicesFetcherOptions) {
function createFetcher(options: SchemaFetcherOptions & ServicesFetcherOptions) {
let cacheETag: string | null = null;
let cached: {
id: string;
supergraphSdl: string;
} | null = null;
const endpoint = options.endpoint.endsWith('/services')
? options.endpoint
: joinUrl(options.endpoint, 'services');
return function fetcher(): Promise<readonly Schema[] | Schema> {
const headers: {
[key: string]: string;
} = {
'X-Hive-CDN-Key': key,
'X-Hive-CDN-Key': options.key,
accept: 'application/json',
'User-Agent': `hive-client/${version}`,
};
@ -43,7 +48,7 @@ function createFetcher({ endpoint, key }: SchemaFetcherOptions & ServicesFetcher
const fetchWithRetry = (): Promise<readonly Schema[] | Schema> => {
return axios
.get(endpoint + '/services', {
.get(endpoint, {
headers,
responseType: 'json',
})
@ -81,8 +86,8 @@ function createFetcher({ endpoint, key }: SchemaFetcherOptions & ServicesFetcher
};
}
export function createSchemaFetcher({ endpoint, key }: SchemaFetcherOptions) {
const fetcher = createFetcher({ endpoint, key });
export function createSchemaFetcher(options: SchemaFetcherOptions) {
const fetcher = createFetcher(options);
return function schemaFetcher() {
return fetcher().then(schema => {
@ -108,8 +113,8 @@ export function createSchemaFetcher({ endpoint, key }: SchemaFetcherOptions) {
};
}
export function createServicesFetcher({ endpoint, key }: ServicesFetcherOptions) {
const fetcher = createFetcher({ endpoint, key });
export function createServicesFetcher(options: ServicesFetcherOptions) {
const fetcher = createFetcher(options);
return function schemaFetcher() {
return fetcher().then(services => {

View file

@ -129,3 +129,12 @@ export function logIf(condition: boolean, message: string, logFn: (message: stri
logFn(message);
}
}
export function joinUrl(url: string, subdirectory: string) {
const normalizedUrl = url.endsWith('/') ? url.slice(0, -1) : url;
const normalizedSubdirectory = subdirectory.startsWith('/')
? subdirectory.slice(1)
: subdirectory;
return normalizedUrl + '/' + normalizedSubdirectory;
}

View file

@ -1,3 +1,7 @@
# 10.04.2024
- `HIVE_CDN_ENDPOINT` and `endpoint` accept an URL with and without the `/supergraph` part
# 09.01.2024
- Introduce `HIVE_CDN_SCHEMA_FILE_PATH` environment variable to specify where to download the supergraph schema (default is `./supergraph-schema.graphql`)

View file

@ -33,7 +33,7 @@ impl HiveRegistry {
key: None,
poll_interval: None,
accept_invalid_certs: Some(true),
schema_file_path: None
schema_file_path: None,
};
// Pass values from user's config
@ -86,7 +86,7 @@ impl HiveRegistry {
}
// Resolve values
let endpoint = config.endpoint.unwrap_or_else(|| "".to_string());
let mut endpoint = config.endpoint.unwrap_or_else(|| "".to_string());
let key = config.key.unwrap_or_else(|| "".to_string());
let poll_interval: u64 = match config.poll_interval {
Some(value) => value,
@ -110,6 +110,14 @@ impl HiveRegistry {
return Err(anyhow!("environment variable HIVE_CDN_ENDPOINT not found",));
}
if !endpoint.ends_with("/supergraph") {
if endpoint.ends_with("/") {
endpoint.push_str("supergraph")
} else {
endpoint.push_str("/supergraph")
}
}
// Throw if key is empty
if key.is_empty() {
return Err(anyhow!("environment variable HIVE_CDN_KEY not found"));
@ -118,7 +126,9 @@ impl HiveRegistry {
// A hacky way to force the router to use GraphQL Hive CDN as the source of schema.
// Our plugin does the polling and saves the supergraph to a file.
// It also enables hot-reloading to makes sure Apollo Router watches the file.
let file_name = config.schema_file_path.unwrap_or("supergraph-schema.graphql".to_string());
let file_name = config
.schema_file_path
.unwrap_or("supergraph-schema.graphql".to_string());
env::set_var("APOLLO_ROUTER_SUPERGRAPH_PATH", file_name.clone());
env::set_var("APOLLO_ROUTER_HOT_RELOAD", "true");
@ -172,7 +182,7 @@ impl HiveRegistry {
}
let resp = client
.get(format!("{}/supergraph", self.endpoint))
.get(self.endpoint.as_str())
.headers(headers)
.send()
.map_err(|e| e.to_string())?;