Skip to content

Commit

Permalink
types conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
HTSagara committed Aug 9, 2024
1 parent a7f9bb2 commit 859b649
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 30 deletions.
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ services:
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-test}
- AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN:-test}
- AWS_DYNAMODB_TABLE_NAME=${AWS_DYNAMODB_TABLE_NAME:-fragments}
# - AWS_COGNITO_POOL_ID=${AWS_COGNITO_POOL_ID}
# - AWS_COGNITO_CLIENT_ID=${AWS_COGNITO_CLIENT_ID}
# Ports to publish
ports:
- '8080:8080'
Expand Down
103 changes: 85 additions & 18 deletions src/routes/api/getById.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,109 @@ const { createErrorResponse } = require('../../response');
const { Fragment } = require('../../model/fragment');
const logger = require('../../logger');
const path = require('path');
// const md = require('markdown-it')();
const md = require('markdown-it')();

module.exports = async (req, res) => {
// separating the ID and extension from the URL
const pathURL = path.parse(req.params.id);

const ext = pathURL.ext.slice(1) || '';
const id = pathURL.name;
const ownerId = req.user;

logger.info({ ext, id }, 'Extension and ID passed in the URL');

try {
// Looking for the user id in the current fragment data
const frags = await Fragment.byId(ownerId, id);
let data = await frags.getData();

// returns an existing fragment's data converted to a supported type.
// Initially, you only need to support Markdown fragments (.md) converted to HTML (.html) using markdown-it

// Check if it has a .md extension
if (ext) {
if (ext === 'md') {
// Changes the content type to html
res.set('Content-Type', 'text/html');
res.status(200).send(data);
} else {
// If the extension used represents an unknown or unsupported type,
// or if the fragment cannot be converted to this type, an HTTP 415 error is returned
res.status(415).json(createErrorResponse(415, 'Unknown or unsupported type'));
// Handle supported conversions based on fragment type
switch (frags.type) {
case 'text/markdown':
if (ext === 'md') {
data = md.render(data.toString());
res.set('Content-Type', 'text/html');
res.status(200).send(data);
} else if (ext === 'txt') {
res.set('Content-Type', 'text/plain');
res.status(200).send(data);
} else {
res
.status(415)
.json(createErrorResponse(415, 'Unsupported conversion type for markdown'));
}
break;

case 'text/plain':
if (ext === 'txt') {
res.set('Content-Type', 'text/plain');
res.status(200).send(data);
} else {
res
.status(415)
.json(createErrorResponse(415, 'Unsupported conversion type for plain text'));
}
break;

case 'text/html':
if (ext === 'html') {
res.set('Content-Type', 'text/html');
res.status(200).send(data);
} else if (ext === 'txt') {
res.set('Content-Type', 'text/plain');
res.status(200).send(data);
} else {
res.status(415).json(createErrorResponse(415, 'Unsupported conversion type for HTML'));
}
break;

case 'image/png':
case 'image/jpeg':
case 'image/webp':
case 'image/avif':
case 'image/gif':
if (['png', 'jpg', 'jpeg', 'webp', 'gif', 'avif'].includes(ext)) {
res.set('Content-Type', `image/${ext}`);
res.status(200).send(data);
} else {
res.status(415).json(createErrorResponse(415, 'Unsupported conversion type for image'));
}
break;

case 'application/json':
if (ext === 'json') {
res.set('Content-Type', 'application/json');
res.status(200).send(data);
} else if (ext === 'txt') {
res.set('Content-Type', 'text/plain');
res.status(200).send(data);
} else {
res.status(415).json(createErrorResponse(415, 'Unsupported conversion type for JSON'));
}
break;

case 'application/yaml':
if (ext === 'yaml' || ext === 'yml') {
res.set('Content-Type', 'application/yaml');
res.status(200).send(data);
} else if (ext === 'txt') {
res.set('Content-Type', 'text/plain');
res.status(200).send(data);
} else {
res.status(415).json(createErrorResponse(415, 'Unsupported conversion type for YAML'));
}
break;

default:
res.status(415).json(createErrorResponse(415, 'Unknown or unsupported type'));
break;
}
} else {
// No extension provided, return raw data
res.set('Content-Type', frags.type);
res.status(200).send(data);
return;
}
} catch (error) {
logger.warn({ errorMessage: error.message }, 'request to non-existent fragment was made');
logger.warn({ errorMessage: error.message }, 'Request to non-existent fragment was made');
res.status(404).json(createErrorResponse(404, 'Fragment not found'));
}
};
75 changes: 63 additions & 12 deletions tests/unit/getById.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,24 @@ app.use((req, res, next) => {
app.get('/v1/fragments/:id', getFragmentById);

// Helper function to create a fragment in the database
async function createTestFragment(type = 'text/plain; charset=utf-8') {
async function createTestFragment(
type = 'text/plain; charset=utf-8',
content = 'This is a test fragment'
) {
const fragment = new Fragment({
ownerId: 'test-owner-id',
type: type,
size: 20,
size: Buffer.byteLength(content),
});
await fragment.save();
await fragment.setData(Buffer.from('This is a test fragment'));
await fragment.setData(Buffer.from(content));
return fragment;
}

describe('GET /v1/fragments/:id', () => {
let testFragment;

// beforeAll(async () => {
// // Create a test fragment before running the tests
// testFragment = await createTestFragment();
// });

it('should return the fragment data for a valid fragment ID', async () => {
it('should return raw fragment data for a valid fragment ID without extension', async () => {
testFragment = await createTestFragment();
const response = await request(app)
.get(`/v1/fragments/${testFragment.id}`)
Expand All @@ -47,19 +45,72 @@ describe('GET /v1/fragments/:id', () => {
});

it('should return the .md fragment data converted to html', async () => {
testFragment = await createTestFragment('text/markdown');
testFragment = await createTestFragment('text/markdown', 'This is a test fragment');

const response = await request(app)
.get(`/v1/fragments/${testFragment.id}.md`)
.set('Authorization', 'Bearer test-token');

expect(response.status).toBe(200);
expect(response.headers['content-type']).toBe('text/html; charset=utf-8');
expect(response.text).toBe('This is a test fragment');
expect(response.text.trim()).toBe('<p>This is a test fragment</p>');
});

it('should return plain text fragment data for a .txt extension', async () => {
testFragment = await createTestFragment('text/plain', 'This is plain text');

const response = await request(app)
.get(`/v1/fragments/${testFragment.id}.txt`)
.set('Authorization', 'Bearer test-token');

expect(response.status).toBe(200);
expect(response.headers['content-type']).toBe('text/plain; charset=utf-8');
expect(response.text).toBe('This is plain text');
});

it('should return 415 for unsupported conversion type for plain text', async () => {
testFragment = await createTestFragment('text/plain; charset=utf-8', 'This is plain text');

const response = await request(app)
.get(`/v1/fragments/${testFragment.id}.png`)
.set('Authorization', 'Bearer test-token');

expect(response.status).toBe(415);
expect(response.body).toEqual(createErrorResponse(415, 'Unknown or unsupported type'));
});

it('should return the fragment as an image when a valid image extension is provided', async () => {
const imageBuffer = Buffer.from([
/* ...binary data... */
]);
testFragment = await createTestFragment('image/png', imageBuffer);

const response = await request(app)
.get(`/v1/fragments/${testFragment.id}.png`)
.set('Authorization', 'Bearer test-token');

expect(response.status).toBe(200);
expect(response.headers['content-type']).toBe('image/png');
expect(response.body).toEqual(imageBuffer);
});

it('should return 415 for unsupported conversion type for image', async () => {
const imageBuffer = Buffer.from([
/* ...binary data... */
]);
testFragment = await createTestFragment('image/png', imageBuffer);

const response = await request(app)
.get(`/v1/fragments/${testFragment.id}.txt`)
.set('Authorization', 'Bearer test-token');

expect(response.status).toBe(415);
expect(response.body).toEqual(
createErrorResponse(415, 'Unsupported conversion type for image')
);
});

it('should return 404 for a non-existent fragment ID', async () => {
testFragment = await createTestFragment();
const response = await request(app)
.get('/v1/fragments/non-existent-id')
.set('Authorization', 'Bearer test-token');
Expand Down

0 comments on commit 859b649

Please sign in to comment.