Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 12 additions & 3 deletions src/api/__tests__/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,7 @@ test('Fallback to bootstrapping directly if the /api/user endpoint continuously

// the refresh header was added to force a new session
expect(onReq.mock.calls[1][0].headers.get('x-refresh-token')).toMatchInlineSnapshot('"1"');
expect(onReq.mock.calls[3][0].headers.get('authorization')).toMatchInlineSnapshot(
'"Bearer mocked-anonymous-token"',
);
expect(onReq.mock.calls[3][0].headers.get('authorization')).toMatchInlineSnapshot('"Bearer mocked-anonymous-token"');
});

test('passing token initially skips bootstrap', async ({ server }: TestContext) => {
Expand Down Expand Up @@ -298,6 +296,17 @@ test('request rejects if the refreshed user data is not valid', async ({ server
expect(onReq.mock.calls[1][0].headers.get('x-refresh-token')).toEqual('1');
});

test('request interceptor sets X-Ui-Tag header from ui_tag', async ({ server }: TestContext) => {
const { onRequest: onReq } = createServerListenerMocks(server);
server.use(testHandlerWith200);
api.setUserData(mockUserData);

await api.request({ method: 'GET', url: '/test', ui_tag: 'search/primary' } as ApiRequestConfig);

expect(onReq).toHaveBeenCalledOnce();
expect(onReq.mock.calls[0][0].headers.get('x-ui-tag')).toEqual('search/primary');
});

test('duplicate requests are provided the same promise', async ({ server }: TestContext) => {
const { onRequest: onReq } = createServerListenerMocks(server);
server.use(rest.get('*test', (_, res, ctx) => res(ctx.status(200), ctx.delay(100), ctx.json({ ok: true }))));
Expand Down
8 changes: 8 additions & 0 deletions src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ class Api {
}

private async init() {
this.service.interceptors.request.use((config) => {
if ((config as ApiRequestConfig).ui_tag) {
config.headers['X-Ui-Tag'] = (config as ApiRequestConfig).ui_tag;
delete (config as ApiRequestConfig).ui_tag;
}
return config;
});

this.service.interceptors.response.use(identity, (error: AxiosError & { canRefresh: boolean }) => {
// Use global error handler (skip Sentry as React Query will handle it)
handleAPIError(error, error.config?.url, {
Expand Down
9 changes: 7 additions & 2 deletions src/api/author-affiliation/author-affiliation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ export const authorAffiliationsKeys = {
export: (params: IAuthorAffiliationExportPayload) => ['authoraffiliation/export', params] as const,
};

type SearchQuery = ADSQuery<Parameters<typeof authorAffiliationsKeys['search']>[0], IAuthorAffiliationResponse['data']>;
type ExportQuery = ADSQuery<Parameters<typeof authorAffiliationsKeys['export']>[0], string>;
type SearchQuery = ADSQuery<
Parameters<(typeof authorAffiliationsKeys)['search']>[0],
IAuthorAffiliationResponse['data']
>;
type ExportQuery = ADSQuery<Parameters<(typeof authorAffiliationsKeys)['export']>[0], string>;

export const useAuthorAffiliationSearch: SearchQuery = (params, options) => {
const searchParams = getAuthorAffiliationSearchParams(params);
Expand Down Expand Up @@ -39,6 +42,7 @@ export const fetchAuthorAffiliationSearch: QueryFunction<IAuthorAffiliationRespo
method: 'POST',
url: ApiTargets.AUTHOR_AFFILIATION_SEARCH,
data: params,
ui_tag: 'author-affiliation/search',
};

const { data } = await api.request<IAuthorAffiliationResponse>(config);
Expand All @@ -53,6 +57,7 @@ export const fetchAuthorAffiliationExport: QueryFunction<string> = async ({ meta
method: 'POST',
url: ApiTargets.AUTHOR_AFFILIATION_EXPORT,
data: params,
ui_tag: 'author-affiliation/export',
};

const { data } = await api.request<string>(config);
Expand Down
16 changes: 16 additions & 0 deletions src/api/biblib/libraries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export const fetchLibraries: QueryFunction<IADSApiLibraryResponse> = async ({ me
method: 'GET',
url: ApiTargets.LIBRARIES,
params,
ui_tag: 'library/libraries',
};

return trackUserFlow(PERF_SPANS.LIBRARY_LIST_LOAD, async () => {
Expand All @@ -119,6 +120,7 @@ export const addLibrary: MutationFunction<IADSApiLibraryAddResponse, IADSApiLibr
method: 'POST',
url: `${ApiTargets.LIBRARIES}`,
data: params,
ui_tag: 'library/add',
};

return trackUserFlow(PERF_SPANS.LIBRARY_CREATE_TOTAL, async () => {
Expand All @@ -145,6 +147,7 @@ export const fetchLibraryEntity: QueryFunction<IADSApiLibraryEntityResponse> = a
method: 'GET',
url: `${ApiTargets.LIBRARIES}/${params.id}`,
params: omit(['id'], params),
ui_tag: 'library/library',
};

const { data } = await api.request<IADSApiLibraryEntityResponse>(config);
Expand All @@ -170,6 +173,7 @@ export const deleteLibrary: MutationFunction<IADSApiLibraryDeleteResponse, IADSA
const config: ApiRequestConfig = {
method: 'DELETE',
url: `${ApiTargets.DOCUMENTS}/${id}`,
ui_tag: 'library/delete',
};

const { data } = await api.request<IADSApiLibraryDeleteResponse>(config);
Expand All @@ -195,6 +199,7 @@ export const editLibraryMeta: MutationFunction<IADSApiLibraryEditMetaResponse, I
method: 'PUT',
url: `${ApiTargets.DOCUMENTS}/${params.id}`,
data: omit(['id'], params),
ui_tag: 'library/edit',
};

const { data } = await api.request<IADSApiLibraryEditMetaResponse>(config);
Expand All @@ -221,6 +226,7 @@ export const editLibraryDocuments: MutationFunction<
method: 'POST',
url: `${ApiTargets.DOCUMENTS}/${params.id}`,
data: omit(['id'], params),
ui_tag: 'library/document',
};

return trackUserFlow(PERF_SPANS.LIBRARY_ADD_TOTAL, async () => {
Expand Down Expand Up @@ -250,6 +256,7 @@ export const operation: MutationFunction<IADSApiLibraryOperationResponse, IADSAp
method: 'POST',
url: `${ApiTargets.LIBRARY_OPERATION}/${params.id}`,
data: omit(['id'], params),
ui_tag: 'library/operation',
};

const { data } = await api.request<IADSApiLibraryOperationResponse>(config);
Expand All @@ -276,6 +283,7 @@ export const addDocumentsByQuery: MutationFunction<IADSApiLibraryQueryResponse,
method: 'POST',
url: `${ApiTargets.LIBRARY_QUERY}/${params.id}`,
data: params,
ui_tag: 'library/query',
};

const { data } = await api.request<IADSApiLibraryQueryResponse>(config);
Expand All @@ -302,6 +310,7 @@ export const updateDocumentsByQuery: MutationFunction<
method: 'POST',
url: `${ApiTargets.LIBRARY_QUERY}/${params.id}`,
data: omit(['id'], params),
ui_tag: 'library/query-update',
};

const { data } = await api.request<IADSApiLibraryQueryUpdateResponse>(config);
Expand All @@ -327,6 +336,7 @@ export const getPermission: QueryFunction<IADSApiLibraryPermissionResponse> = as
const config: ApiRequestConfig = {
method: 'GET',
url: `${ApiTargets.PERMISSIONS}/${params.id}`,
ui_tag: 'library/permission',
};

const { data } = await api.request<IADSApiLibraryPermissionResponse>(config);
Expand All @@ -353,6 +363,7 @@ export const modifyPermission: MutationFunction<
method: 'POST',
url: `${ApiTargets.PERMISSIONS}/${params.id}`,
data: omit(['id'], params),
ui_tag: 'library/permission-update',
};

const { data } = await api.request<IADSApiLibraryPermissionUpdateResponse>(config);
Expand All @@ -379,6 +390,7 @@ export const transfer: MutationFunction<IADSApiLibraryTransferResponse, IADSApiL
method: 'POST',
url: `${ApiTargets.LIBRARY_TRANSFER}/${params.id}`,
data: omit(['id'], params),
ui_tag: 'library/transfer',
};

const { data } = await api.request<IADSApiLibraryTransferResponse>(config);
Expand Down Expand Up @@ -407,6 +419,7 @@ export const fetchAnnotation: QueryFunction<IADSApiLibraryGetAnnotationResponse>
const config: ApiRequestConfig = {
method: 'GET',
url: `${ApiTargets.LIBRARY_NOTES}/${params.library}/${params.bibcode}`,
ui_tag: 'library/get-annotation',
};

const { data } = await api.request<IADSApiLibraryGetAnnotationResponse>(config);
Expand Down Expand Up @@ -435,6 +448,7 @@ export const addAnnotation: MutationFunction<
method: 'POST',
url: `${ApiTargets.LIBRARY_NOTES}/${params.library}/${params.bibcode}`,
data: { content: params.content },
ui_tag: 'library/add-annotation',
};

const { data } = await api.request<IADSApiLibraryAddAnnotationResponse>(config);
Expand Down Expand Up @@ -463,6 +477,7 @@ export const updateAnnotation: MutationFunction<
method: 'PUT',
url: `${ApiTargets.LIBRARY_NOTES}/${params.library}/${params.bibcode}`,
data: { content: params.content },
ui_tag: 'library/update-annotation',
};

const { data } = await api.request<IADSApiLibraryAddAnnotationResponse>(config);
Expand Down Expand Up @@ -490,6 +505,7 @@ export const deleteAnnotation: MutationFunction<
const config: ApiRequestConfig = {
method: 'DELETE',
url: `${ApiTargets.LIBRARY_NOTES}/${params.library}/${params.bibcode}`,
ui_tag: 'library/delete-annotation',
};

const { data } = await api.request<IADSApiLibraryDeleteAnnotationResponse>(config);
Expand Down
1 change: 1 addition & 0 deletions src/api/citation_helper/citation_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const fetchCitationHelper: QueryFunction<ICitationHelperResponse> = async
method: 'POST',
url: ApiTargets.SERVICE_CITATION_HELPER,
data: params,
ui_tag: 'citation-helper/primary',
};

const { data } = await api.request<ICitationHelperResponse>(config);
Expand Down
2 changes: 2 additions & 0 deletions src/api/export/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const fetchExportFormats: QueryFunction<ExportFormatsApiResponse> = async
const config: ApiRequestConfig = {
method: 'GET',
url: ApiTargets.EXPORT_MANIFEST,
ui_tag: 'export/manifest',
};

const { data } = await api.request<ExportFormatsApiResponse>(config);
Expand All @@ -58,6 +59,7 @@ export const fetchExportCitation: QueryFunction<IExportApiResponse> = async ({ m
...params,
...(format === ExportApiFormatKey.custom ? { format: customFormat } : {}),
},
ui_tag: 'export/citation',
};

return trackUserFlow(PERF_SPANS.EXPORT_API_REQUEST, async () => {
Expand Down
1 change: 1 addition & 0 deletions src/api/feedback/feedback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const feedbackQueryFn: MutationFunction<IADSApiFeedbackResponse, Partial<IFeedba
method: 'POST',
url: ApiTargets.FEEDBACK,
data: params,
ui_tag: 'feedback/primary',
};

const { data } = await api.request<IADSApiFeedbackResponse>(config);
Expand Down
1 change: 1 addition & 0 deletions src/api/graphics/graphics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const fetchGraphics: QueryFunction<IADSApiGraphicsResponse> = async ({ me
const config: ApiRequestConfig = {
method: 'GET',
url: `${ApiTargets.GRAPHICS}/${params.bibcode}`,
ui_tag: 'graphics/primary',
};

const { data: graphics } = await api.request<IADSApiGraphicsResponse>(config);
Expand Down
3 changes: 3 additions & 0 deletions src/api/journals/journals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const fetchJournal: QueryFunction<IADSApiJournalsJournalResponse> = async
const config: ApiRequestConfig = {
method: 'GET',
url: `${ApiTargets.JOURNAL}/${params.term}`,
ui_tag: 'journals/journal',
};

const { data } = await api.request<IADSApiJournalsJournalResponse>(config);
Expand All @@ -71,6 +72,7 @@ export const fetchSummary: QueryFunction<IADSApiJournalsSummaryResponse> = async
const config: ApiRequestConfig = {
method: 'GET',
url: `${ApiTargets.JOURNAL_SUMMARY}/${params.bibstem}`,
ui_tag: 'journals/summary',
};

const { data } = await api.request<IADSApiJournalsSummaryResponse>(config);
Expand All @@ -91,6 +93,7 @@ export const fetchISSN: QueryFunction<IADSApiJournalsISSNResponse> = async ({ me
const config: ApiRequestConfig = {
method: 'GET',
url: `${ApiTargets.JOURNAL_ISSN}/${params.issn}`,
ui_tag: 'journals/issn',
};

const { data } = await api.request<IADSApiJournalsISSNResponse>(config);
Expand Down
9 changes: 5 additions & 4 deletions src/api/metrics/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const useHasMetrics: ADSQuery<Bibcode, IADSApiMetricsResponse, null, bool
queryKey: metricsKeys.primary([bibcode]),
queryFn: fetchMetrics,
retry: retryFn,
meta: { params, skipGlobalErrorHandler: true },
meta: { params, skipGlobalErrorHandler: true, ui_tag: 'metrics/primary' },
...options,
});

Expand Down Expand Up @@ -67,7 +67,7 @@ export const useGetMetrics: ADSQuery<Bibcode | Bibcode[], IADSApiMetricsResponse
queryKey: metricsKeys.primary(bibcodes),
queryFn: fetchMetrics,
retry: retryFn,
meta: { params },
meta: { params, ui_tag: 'metrics/primary' },
...options,
});
};
Expand All @@ -82,18 +82,19 @@ export const useGetMetricsTimeSeries: ADSQuery<Bibcode[], IADSApiMetricsResponse
queryKey: metricsKeys.timeSeries(bibcodes),
queryFn: fetchMetrics,
retry: retryFn,
meta: { params },
meta: { params, ui_tag: 'metrics/time-series' },
...options,
Comment thread
thostetler marked this conversation as resolved.
});
};

export const fetchMetrics: QueryFunction<IADSApiMetricsResponse> = async ({ meta }) => {
const { params } = meta as { params: IADSApiMetricsParams };
const { params, ui_tag } = meta as { params: IADSApiMetricsParams; ui_tag?: string };

const config: ApiRequestConfig = {
method: 'POST',
url: ApiTargets.SERVICE_METRICS,
data: params,
ui_tag,
};

const metrics = await trackUserFlow(PERF_SPANS.ABSTRACT_METRICS_REQUEST, async () => {
Expand Down
3 changes: 3 additions & 0 deletions src/api/objects/objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const resolveObjectQuery = async (params: IObjectsQueryApiParams) => {
url: ApiTargets.SERVICE_OBJECTS_QUERY,
method: 'POST',
data: { query: [query] },
ui_tag: 'objects/primary',
};

const { data } = await api.request<ObjectService['response']>(config);
Expand Down Expand Up @@ -86,6 +87,7 @@ export const resolveObjectQuerySSR = async (params: IObjectsQueryApiParams, ctx:
...defaultRequestConfig.headers,
...pickTracingHeaders(ctx.req.headers),
Authorization: `Bearer ${token}`,
'X-Ui-Tag': 'objects/primary',
},
};

Expand Down Expand Up @@ -114,6 +116,7 @@ export const resolveObjects = async (params: IObjectsApiParams) => {
url: ApiTargets.SERVICE_OBJECTS,
method: 'POST',
data: { identifiers },
ui_tag: 'objects/primary',
};

const { data } = await api.request<IObjectsApiResponse>(config);
Expand Down
Loading
Loading