Skip to content

Commit 564e5aa

Browse files
committed
encapsulate the url in an URL object
1 parent 40402da commit 564e5aa

File tree

8 files changed

+21
-24
lines changed

8 files changed

+21
-24
lines changed

api/src/infrastructure/repository/in-memory-url.repository.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import { Injectable, Logger } from '@nestjs/common';
55
export class InMemoryUrlRepository implements ShortenUrlRepository {
66
private urls: Map<string, string> = new Map();
77

8-
create(url: string, shortenedUrl: string): Promise<void> {
9-
this.urls.set(url, shortenedUrl);
8+
create(url: string, encodedUrl: string): Promise<void> {
9+
this.urls.set(url, encodedUrl);
1010
return Promise.resolve(undefined);
1111
}
1212

13-
findOriginalURL(shortenedUrl: string): Promise<string | null> {
13+
findOriginalURL(encodedUrl: string): Promise<string | null> {
1414
const originalUrl = Array.from(this.urls.keys()).find(
15-
(key) => this.urls.get(key) === shortenedUrl,
15+
(key) => this.urls.get(key) === encodedUrl,
1616
);
1717
return Promise.resolve(originalUrl || null);
1818
}

api/src/infrastructure/repository/redis-url.repository.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,18 @@ export class RedisUrlRepository
3030
);
3131
}
3232

33-
async create(url: string, shortenedUrl: string): Promise<void> {
33+
async create(url: string, encodedUrl: string): Promise<void> {
3434
await this.redisClient.set(
35-
`shortenedUrl: ${shortenedUrl}`,
35+
`encodedUrl: ${encodedUrl}`,
3636
`originalUrl: ${url}`,
3737
{
3838
EX: this.redisTTL,
3939
},
4040
);
4141
}
4242

43-
async findOriginalURL(originalUrl: string): Promise<string | null> {
44-
return await this.redisClient.get(`originalUrl:${originalUrl}`);
43+
async findOriginalURL(encodedUrl: string): Promise<string | null> {
44+
return await this.redisClient.get(`encodedUrl:${encodedUrl}`);
4545
}
4646

4747
async onModuleInit() {

api/src/shorten-url/create-shorten-url/create-shorten-url.controller.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ export class CreateShortenUrlController {
1111
@Body() request: CreateShortenUrlDto,
1212
): Promise<{ shortenedUrl: string }> {
1313
// TODO perhaps it is worth converting the URL from string to URL object
14-
const shortenedUrl = await this.shortenUrlUsecase.shortenUrl(request.url);
15-
return { shortenedUrl };
14+
const url = new URL(request.url);
15+
const shortenedUrl = await this.shortenUrlUsecase.shortenUrl(url);
16+
return { shortenedUrl: shortenedUrl.toString() };
1617
}
1718
}

api/src/shorten-url/create-shorten-url/create-shorten-url.usecase.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ export class CreateShortenUrlUsecase {
2626
this.configService.get<string>('SHORTENED_BASE_URL');
2727
}
2828

29-
async shortenUrl(originalURL: string): Promise<string> {
29+
async shortenUrl(originalURL: URL): Promise<URL> {
3030
const id = this.idGenerator.generateId();
31-
const encodedId = this.encodeBase62(Number(id));
32-
const shortenedUrl = this.shortenedBaseUrl + '/' + encodedId;
33-
await this.shortenUrlRepository.create(originalURL, shortenedUrl);
31+
const encodedUrl = this.encodeBase62(Number(id));
32+
await this.shortenUrlRepository.create(originalURL.toString(), encodedUrl);
33+
const shortenedUrl = new URL(encodedUrl, this.shortenedBaseUrl);
3434
return shortenedUrl;
3535
}
3636

api/src/shorten-url/redirect-to-original-url/redirect-to-original-url-controller.spec.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ describe('Redirect to original url controller', () => {
4444
});
4545

4646
it('should return 404 if the shortened URL is not found', async () => {
47-
const redirect = jest.fn();
48-
const res = { redirect } as any;
49-
5047
const slug = 'does-not-exist';
5148
await expect(underTest.redirectToOriginalUrl(slug)).rejects.toThrow(
5249
'Shortened URL "does-not-exist" not found',

api/src/shorten-url/redirect-to-original-url/redirect-to-original-url.controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ export class RedirectToOriginalUrlController {
2323
throw new NotFoundException(`Shortened URL "${slug}" not found`);
2424
}
2525
// Use temporary redirect to original URL so that we can capture analytics
26-
return { url: originalUrl };
26+
return { url: originalUrl.toString() };
2727
}
2828
}

api/src/shorten-url/redirect-to-original-url/redirect-to-original-url.usecase.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ export class RedirectToOriginalUrlUsecase {
88
private readonly shortenUrlRepository: ShortenUrlRepository,
99
) {}
1010

11-
async redirectToOriginalUrl(slug: string): Promise<string | null> {
12-
// TODO: reconstruct the URL ? or store only the shorted path ??
13-
const url = 'http://localhost:3000/' + slug;
14-
return await this.shortenUrlRepository.findOriginalURL(url);
11+
async redirectToOriginalUrl(slug: string): Promise<URL | null> {
12+
const originalUrl = await this.shortenUrlRepository.findOriginalURL(slug);
13+
return originalUrl ? new URL(originalUrl) : null;
1514
}
1615
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export abstract class ShortenUrlRepository {
2-
abstract create(url: string, shortenedUrl: string): Promise<void>;
2+
abstract create(url: string, encodedUrl: string): Promise<void>;
33

4-
abstract findOriginalURL(shortenedUrl: string): Promise<string | null>;
4+
abstract findOriginalURL(encodedUrl: string): Promise<string | null>;
55
}

0 commit comments

Comments
 (0)