Skip to content

Commit

Permalink
refactor: clean up fetch from api function
Browse files Browse the repository at this point in the history
  • Loading branch information
yoshinorin committed Jun 15, 2024
1 parent 9087b42 commit b7da094
Show file tree
Hide file tree
Showing 16 changed files with 163 additions and 76 deletions.
14 changes: 5 additions & 9 deletions __tests__/unit/api/api.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { expect, test } from "vitest";
import { fetchFromApi } from "../../../src/api/request";
import { RequestOptions, fetchFromApi } from "../../../src/api/request";

test("should returns 404 if path contains ignore chars", async () => {
const response = await fetchFromApi(
"https://example.com/hoge.svg",
"",
null,
{
interceptIfContainsIgnorePaths: true
}
);
const options: RequestOptions = {
interceptIfContainsIgnorePaths: true
};
const response = await fetchFromApi("https://example.com/hoge.svg", options);
expect(response.status).toEqual(404);
});
32 changes: 17 additions & 15 deletions src/api/request.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import { RequestContext } from "../models/models";
import { isMatch } from "../utils/match";

export type RequestOptions = {
headers?: object;
queryParams?: string;
interceptIfContainsIgnorePaths?: boolean;
};

// TODO: write test code
// TODO: more simply
export async function fetchFromApi(
endpoint: string,
queryParams: string = "",
ctx: RequestContext | null,
options: {
interceptIfContainsIgnorePaths: boolean;
} | null = null
{
headers = {},
queryParams = "",
interceptIfContainsIgnorePaths = false
}: RequestOptions = {}
): Promise<Response> {
// TODO: extract to function & write test code
if (options) {
if (options.interceptIfContainsIgnorePaths) {
if (!endpoint || (endpoint && isMatch(endpoint))) {
return new Response(null, { status: 404 });
}
if (interceptIfContainsIgnorePaths) {
if (!endpoint || (endpoint && isMatch(endpoint))) {
return new Response(null, { status: 404 });
}
}

const q = queryParams ?? "";
const url = buildRequestUrl(endpoint, q);
const header = ctx ? { header: requestHeaderFrom(ctx) } : {};
const url = buildRequestUrl(endpoint, queryParams);
const header = headers ? { header: headers } : {};

return fetch(url, {
method: "GET",
Expand All @@ -37,7 +39,7 @@ export function buildRequestUrl(url: string, queryParams: string): string {
return new URL(u).href;
}

function requestHeaderFrom(rq: RequestContext): Object {
export function requestHeaderFrom(rq: RequestContext): Object {
return {
"Content-Type": "application/json",
"x-forwarded-for": rq.ipAddress,
Expand Down
14 changes: 10 additions & 4 deletions src/app/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { headers } from "next/headers";
import { permanentRedirect } from "next/navigation";
import { cache } from "react";
import { api } from "../../../config";
import { fetchFromApi } from "../../api/request";
import {
RequestOptions,
fetchFromApi,
requestHeaderFrom
} from "../../api/request";
import {
Content,
ContentResponse,
Expand All @@ -20,13 +24,15 @@ import { Renderer } from "./renderer";

// TODO: move somewhere if possible
const cachedFindByPath = cache(async (path: string) => {
const ctx = requestContextFrom(headers());
// TODO: devide into another `function` and move `api` dir.
const slug = sluggize(["v1", "contents", path]);
const url = buildUrl(api.url, slug, true);
const response = await fetchFromApi(url, null, ctx, {
const ctx = requestContextFrom(headers());
const options: RequestOptions = {
headers: requestHeaderFrom(ctx),
interceptIfContainsIgnorePaths: true
});
};
const response = await fetchFromApi(url, options);
throwIfError(response);
const content = (await response.json()) as ContentResponse;
return {
Expand Down
13 changes: 10 additions & 3 deletions src/app/archives/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import { headers } from "next/headers";
import { api } from "../../../config";
import { fetchFromApi } from "../../api/request";
import {
RequestOptions,
fetchFromApi,
requestHeaderFrom
} from "../../api/request";
import { Archive, ArchiveResponse } from "../../models/models";
import { requestContextFrom } from "../../utils/requestContext";
import { buildUrl } from "../../utils/url";
Expand All @@ -19,10 +23,13 @@ async function run(req: any): Promise<any> {
}

async function handler(req: any) {
const ctx = requestContextFrom(headers());
// TODO: devide into another `function` and move `api` dir.
const url = buildUrl(api.url, "v1/archives", true);
const response: Response = await fetchFromApi(url, null, ctx, null);
const ctx = requestContextFrom(headers());
const options: RequestOptions = {
headers: requestHeaderFrom(ctx)
};
const response: Response = await fetchFromApi(url, options);
throwIfError(response);

const archiveResponse: Array<ArchiveResponse> =
Expand Down
14 changes: 10 additions & 4 deletions src/app/articles/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { headers } from "next/headers";
import { notFound } from "next/navigation";
import { cache } from "react";
import { api } from "../../../../config";
import { fetchFromApi } from "../../../api/request";
import {
RequestOptions,
fetchFromApi,
requestHeaderFrom
} from "../../../api/request";
import {
Content,
ContentResponse,
Expand All @@ -23,13 +27,15 @@ const PREFIX_URL = "articles";

// TODO: move somewhere if possible
const cachedFindByPath = cache(async (path: string) => {
const ctx = requestContextFrom(headers());
// TODO: devide into another `function` and move `api` dir.
const slug = sluggize(["v1", "contents", path]);
const url = buildUrl(api.url, slug, true);
const response = await fetchFromApi(url, null, ctx, {
const ctx = requestContextFrom(headers());
const options: RequestOptions = {
headers: requestHeaderFrom(ctx),
interceptIfContainsIgnorePaths: true
});
};
const response = await fetchFromApi(url, options);
throwIfError(response);
const content = (await response.json()) as ContentResponse;
return {
Expand Down
19 changes: 13 additions & 6 deletions src/app/articles/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import { headers } from "next/headers";
import { api } from "../../../config";
import { fetchFromApi } from "../../api/request";
import {
RequestOptions,
fetchFromApi,
requestHeaderFrom
} from "../../api/request";
import { Article, ArticleResponseWithCount } from "../../models/models";
import { requestContextFrom } from "../../utils/requestContext";
import { buildQueryParams, buildUrl } from "../../utils/url";
Expand All @@ -20,13 +24,16 @@ async function run(req: any): Promise<any> {

async function handler(req: any) {
const currentPage = req.searchParams["p"] ? req.searchParams["p"] : 1;
const ctx = requestContextFrom(headers());
// TODO: devide into another `function` and move `api` dir.
const url = buildUrl(api.url, "v1/articles", true);
const queryParams = buildQueryParams({
pagination: { page: currentPage, limit: 10 }
});
const response: Response = await fetchFromApi(url, queryParams, ctx, null);
const ctx = requestContextFrom(headers());
const options: RequestOptions = {
headers: requestHeaderFrom(ctx),
queryParams: buildQueryParams({
pagination: { page: currentPage, limit: 10 }
})
};
const response: Response = await fetchFromApi(url, options);
throwIfError(response);

const articlesResponseWithCount: ArticleResponseWithCount =
Expand Down
13 changes: 10 additions & 3 deletions src/app/feeds/index.xml/route.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import { headers } from "next/headers";
import { api, mainAuthor, siteName, url } from "../../../../config";
import { fetchFromApi } from "../../../api/request";
import {
RequestOptions,
fetchFromApi,
requestHeaderFrom
} from "../../../api/request";
import { Feed } from "../../../models/models";
import { generateFeedsString } from "../../../services/feeds";
import { requestContextFrom } from "../../../utils/requestContext";
import { buildUrl, sluggize } from "../../../utils/url";

//export async function get(ctx: any) {
export async function GET() {
const ctx = requestContextFrom(headers());
// TODO: devide into another `function` and move `api` dir.
const apiUrl = buildUrl(api.url, sluggize(["v1", "feeds", "index"]), false);
const response: Response = await fetchFromApi(apiUrl, null, ctx, null);
const ctx = requestContextFrom(headers());
const options: RequestOptions = {
headers: requestHeaderFrom(ctx)
};
const response: Response = await fetchFromApi(apiUrl, options);

if (response.status !== 200) {
/* NOTE:
Expand Down
15 changes: 11 additions & 4 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import { headers } from "next/headers";
import { api } from "../../config";
import { fetchFromApi } from "../api/request";
import {
RequestOptions,
fetchFromApi,
requestHeaderFrom
} from "../api/request";
import { Article, ArticleResponseWithCount } from "../models/models";
import { requestContextFrom } from "../utils/requestContext";
import { buildQueryParams, buildUrl } from "../utils/url";
Expand All @@ -19,11 +23,14 @@ async function run(req: any): Promise<any> {
}

async function handler(req: any) {
const ctx = requestContextFrom(headers());
// TODO: devide into another `function` and move `api` dir.
const url = buildUrl(api.url, "v1/articles", true);
const queryParams = buildQueryParams({ pagination: { page: 1, limit: 5 } });
const response: Response = await fetchFromApi(url, queryParams, ctx, null);
const ctx = requestContextFrom(headers());
const options: RequestOptions = {
headers: requestHeaderFrom(ctx),
queryParams: buildQueryParams({ pagination: { page: 1, limit: 5 } })
};
const response: Response = await fetchFromApi(url, options);
throwIfError(response);

const articlesResponseWithCount: ArticleResponseWithCount =
Expand Down
19 changes: 13 additions & 6 deletions src/app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import { headers } from "next/headers";
import { api } from "../../../config";
import { fetchFromApi } from "../../api/request";
import {
RequestOptions,
fetchFromApi,
requestHeaderFrom
} from "../../api/request";
import { SearchResponse, SearchResponseWithCount } from "../../models/models";
import { requestContextFrom } from "../../utils/requestContext";
import { buildQueryParams, buildUrl, sluggize } from "../../utils/url";
Expand Down Expand Up @@ -73,13 +77,16 @@ async function handler(req: any) {
}

async function execute(req, words: Array<string>) {
const ctx = requestContextFrom(headers());
// TODO: devide into another `function` and move `api` dir.
const url = buildUrl(api.url, sluggize(["v1", "search"]), false);
const queryParams = buildQueryParams({
params: { key: "q", values: words }
});
const response = await fetchFromApi(url, queryParams, ctx, null);
const ctx = requestContextFrom(headers());
const options: RequestOptions = {
headers: requestHeaderFrom(ctx),
queryParams: buildQueryParams({
params: { key: "q", values: words }
})
};
const response = await fetchFromApi(url, options);

if (response.status !== 200) {
return emptyResult;
Expand Down
13 changes: 10 additions & 3 deletions src/app/series/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import { headers } from "next/headers";
import { api } from "../../../../config";
import { fetchFromApi } from "../../../api/request";
import {
RequestOptions,
fetchFromApi,
requestHeaderFrom
} from "../../../api/request";
import {
Article,
SeriresWithArticles,
Expand All @@ -23,10 +27,13 @@ async function run(req: any): Promise<any> {
}
async function handler(req: any) {
const seriesName = req.params.slug;
const ctx = requestContextFrom(headers());
// TODO: devide into another `function` and move `api` dir.
const url = buildUrl(api.url, sluggize(["v1", "series", seriesName]), false);
const response: Response = await fetchFromApi(url, null, ctx);
const ctx = requestContextFrom(headers());
const options: RequestOptions = {
headers: requestHeaderFrom(ctx)
};
const response: Response = await fetchFromApi(url, options);
throwIfError(response);

const seriresWithArticlesResponse: SeriresWithArticlesResponse =
Expand Down
13 changes: 10 additions & 3 deletions src/app/series/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import { headers } from "next/headers";
import { api } from "../../../config";
import { fetchFromApi } from "../../api/request";
import {
RequestOptions,
fetchFromApi,
requestHeaderFrom
} from "../../api/request";
import { Series, SeriesResponse } from "../../models/models";
import { requestContextFrom } from "../../utils/requestContext";
import { buildUrl, sluggize } from "../../utils/url";
Expand All @@ -19,10 +23,13 @@ async function run(req: any): Promise<any> {
}

async function handler(req: any) {
const ctx = requestContextFrom(headers());
// TODO: devide into another `function` and move `api` dir.
const url = buildUrl(api.url, sluggize(["v1", "series"]), true);
const response: Response = await fetchFromApi(url, null, ctx, null);
const ctx = requestContextFrom(headers());
const options: RequestOptions = {
headers: requestHeaderFrom(ctx)
};
const response: Response = await fetchFromApi(url, options);
throwIfError(response);

const seriesResponse: Array<SeriesResponse> =
Expand Down
13 changes: 10 additions & 3 deletions src/app/sitemap.xml/route.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { headers } from "next/headers";
import { api } from "../../../config";
import { fetchFromApi } from "../../api/request";
import {
RequestOptions,
fetchFromApi,
requestHeaderFrom
} from "../../api/request";
import { Sitemap } from "../../models/models";
import { generateSitemapString } from "../../services/sitemap";
import { requestContextFrom } from "../../utils/requestContext";
import { buildUrl, sluggize } from "../../utils/url";

export async function GET() {
const ctx = requestContextFrom(headers());
// TODO: devide into another `function` and move `api` dir.
const url = buildUrl(api.url, sluggize(["v1", "sitemaps"]), true);
const response: Response = await fetchFromApi(url, null, ctx, null);
const ctx = requestContextFrom(headers());
const options: RequestOptions = {
headers: requestHeaderFrom(ctx)
};
const response: Response = await fetchFromApi(url, options);

if (response.status !== 200) {
return new Response("", {
Expand Down
Loading

0 comments on commit b7da094

Please sign in to comment.