I am trying to implement a image hosting function using AWS S3 and Hono for API endpoints with NextJS on top.
When I building a delete function, if I define the API on server as delete, it won’t work and produces 405 error. In contrast, using post won’t cause any issue and it works. But in my understanding, defining post, delete or put is required for semantic purposes.
Below is my implementation:
Server-side (Hono):
<code>const mediaS3App = new Hono()
.delete('/delete', async (c) => {
try {
const fileName = c.req.query('fileName');
if (!fileName) {
return c.json({error: 'File name required.'}, 400)
}
const result = await getSignedURL(fileName, 'DELETE')
if (result.failure) {
return c.json({error: result.failure}, 401)
}
return c.json({url: result.success?.url})
} catch (error) {
console.error('Server error:', error);
return c.json({error: 'An unexpected error occurred.'}, 500)
}
})
</code>
<code>const mediaS3App = new Hono()
.delete('/delete', async (c) => {
try {
const fileName = c.req.query('fileName');
if (!fileName) {
return c.json({error: 'File name required.'}, 400)
}
const result = await getSignedURL(fileName, 'DELETE')
if (result.failure) {
return c.json({error: result.failure}, 401)
}
return c.json({url: result.success?.url})
} catch (error) {
console.error('Server error:', error);
return c.json({error: 'An unexpected error occurred.'}, 500)
}
})
</code>
const mediaS3App = new Hono()
.delete('/delete', async (c) => {
try {
const fileName = c.req.query('fileName');
if (!fileName) {
return c.json({error: 'File name required.'}, 400)
}
const result = await getSignedURL(fileName, 'DELETE')
if (result.failure) {
return c.json({error: result.failure}, 401)
}
return c.json({url: result.success?.url})
} catch (error) {
console.error('Server error:', error);
return c.json({error: 'An unexpected error occurred.'}, 500)
}
})
Client-side:
<code>await Promise.all(fileSelected.map(async (fileName) => {
try {
const DELURLResponse = await fetch(`/api/media/delete?fileName=${encodeURIComponent(fileName)}`, {
method: 'DELETE',
});
const DELSignedURL = await DELURLResponse.json();
if (DELURLResponse.ok && DELSignedURL.url) {
const deleteResponse = await fetch(DELSignedURL.url, {
method: 'DELETE',
});
if (deleteResponse.ok) {
console.log('delete successful')
mutationDelMediaDb.mutate(fileName)
} else {
console.log('error on deletetion')
}
} else {
console.error('Failed to delete, something wrong with delete presigned URL', DELSignedURL.error);
}
} catch (error) {
console.error('An error occurred during the deletion:', error);
}
}))
</code>
<code>await Promise.all(fileSelected.map(async (fileName) => {
try {
const DELURLResponse = await fetch(`/api/media/delete?fileName=${encodeURIComponent(fileName)}`, {
method: 'DELETE',
});
const DELSignedURL = await DELURLResponse.json();
if (DELURLResponse.ok && DELSignedURL.url) {
const deleteResponse = await fetch(DELSignedURL.url, {
method: 'DELETE',
});
if (deleteResponse.ok) {
console.log('delete successful')
mutationDelMediaDb.mutate(fileName)
} else {
console.log('error on deletetion')
}
} else {
console.error('Failed to delete, something wrong with delete presigned URL', DELSignedURL.error);
}
} catch (error) {
console.error('An error occurred during the deletion:', error);
}
}))
</code>
await Promise.all(fileSelected.map(async (fileName) => {
try {
const DELURLResponse = await fetch(`/api/media/delete?fileName=${encodeURIComponent(fileName)}`, {
method: 'DELETE',
});
const DELSignedURL = await DELURLResponse.json();
if (DELURLResponse.ok && DELSignedURL.url) {
const deleteResponse = await fetch(DELSignedURL.url, {
method: 'DELETE',
});
if (deleteResponse.ok) {
console.log('delete successful')
mutationDelMediaDb.mutate(fileName)
} else {
console.log('error on deletetion')
}
} else {
console.error('Failed to delete, something wrong with delete presigned URL', DELSignedURL.error);
}
} catch (error) {
console.error('An error occurred during the deletion:', error);
}
}))
I got the following error in the console:
<code>FileUpload.tsx:190
DELETE http://localhost:3000/api/media/delete?fileName=f7a7b24e-b721-4e51-a416-af0c82258bf7-458615387_1052344776416616_1974440516975429873_n.JPEG 405 (Method Not Allowed)
eval @ FileUpload.tsx:190
deleteOnS3 @ FileUpload.tsx:188
deleteFile @ display-image.tsx:69
callCallback @ react-dom.development.js:20565
invokeGuardedCallbackImpl @ react-dom.development.js:20614
invokeGuardedCallback @ react-dom.development.js:20689
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:20703
executeDispatch @ react-dom.development.js:32128
processDispatchQueueItemsInOrder @ react-dom.development.js:32160
processDispatchQueue @ react-dom.development.js:32173
dispatchEventsForPlugins @ react-dom.development.js:32184
eval @ react-dom.development.js:32374
batchedUpdates$1 @ react-dom.development.js:24953
batchedUpdates @ react-dom.development.js:28844
dispatchEventForPluginEventSystem @ react-dom.development.js:32373
dispatchEvent @ react-dom.development.js:30141
dispatchDiscreteEvent @ react-dom.development.js:30112
Show 14 more frames
Show lessUnderstand this error
FileUpload.tsx:209 An error occurred during the deletion: SyntaxError: Unexpected end of JSON input
at eval (FileUpload.tsx:194:59)
at async Promise.all (index 0)
at async deleteOnS3 (FileUpload.tsx:188:9)
</code>
<code>FileUpload.tsx:190
DELETE http://localhost:3000/api/media/delete?fileName=f7a7b24e-b721-4e51-a416-af0c82258bf7-458615387_1052344776416616_1974440516975429873_n.JPEG 405 (Method Not Allowed)
eval @ FileUpload.tsx:190
deleteOnS3 @ FileUpload.tsx:188
deleteFile @ display-image.tsx:69
callCallback @ react-dom.development.js:20565
invokeGuardedCallbackImpl @ react-dom.development.js:20614
invokeGuardedCallback @ react-dom.development.js:20689
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:20703
executeDispatch @ react-dom.development.js:32128
processDispatchQueueItemsInOrder @ react-dom.development.js:32160
processDispatchQueue @ react-dom.development.js:32173
dispatchEventsForPlugins @ react-dom.development.js:32184
eval @ react-dom.development.js:32374
batchedUpdates$1 @ react-dom.development.js:24953
batchedUpdates @ react-dom.development.js:28844
dispatchEventForPluginEventSystem @ react-dom.development.js:32373
dispatchEvent @ react-dom.development.js:30141
dispatchDiscreteEvent @ react-dom.development.js:30112
Show 14 more frames
Show lessUnderstand this error
FileUpload.tsx:209 An error occurred during the deletion: SyntaxError: Unexpected end of JSON input
at eval (FileUpload.tsx:194:59)
at async Promise.all (index 0)
at async deleteOnS3 (FileUpload.tsx:188:9)
</code>
FileUpload.tsx:190
DELETE http://localhost:3000/api/media/delete?fileName=f7a7b24e-b721-4e51-a416-af0c82258bf7-458615387_1052344776416616_1974440516975429873_n.JPEG 405 (Method Not Allowed)
eval @ FileUpload.tsx:190
deleteOnS3 @ FileUpload.tsx:188
deleteFile @ display-image.tsx:69
callCallback @ react-dom.development.js:20565
invokeGuardedCallbackImpl @ react-dom.development.js:20614
invokeGuardedCallback @ react-dom.development.js:20689
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:20703
executeDispatch @ react-dom.development.js:32128
processDispatchQueueItemsInOrder @ react-dom.development.js:32160
processDispatchQueue @ react-dom.development.js:32173
dispatchEventsForPlugins @ react-dom.development.js:32184
eval @ react-dom.development.js:32374
batchedUpdates$1 @ react-dom.development.js:24953
batchedUpdates @ react-dom.development.js:28844
dispatchEventForPluginEventSystem @ react-dom.development.js:32373
dispatchEvent @ react-dom.development.js:30141
dispatchDiscreteEvent @ react-dom.development.js:30112
Show 14 more frames
Show lessUnderstand this error
FileUpload.tsx:209 An error occurred during the deletion: SyntaxError: Unexpected end of JSON input
at eval (FileUpload.tsx:194:59)
at async Promise.all (index 0)
at async deleteOnS3 (FileUpload.tsx:188:9)
It would work If I change to route to post
<code>.post('/delete', async (c) => {
...
</code>
<code>.post('/delete', async (c) => {
...
</code>
.post('/delete', async (c) => {
...
<code> await Promise.all(fileSelected.map(async (fileName) => {
try {
const DELURLResponse = await fetch(`/api/media/delete?fileName=${encodeURIComponent(fileName)}`, {
method: 'POST',
});
...
</code>
<code> await Promise.all(fileSelected.map(async (fileName) => {
try {
const DELURLResponse = await fetch(`/api/media/delete?fileName=${encodeURIComponent(fileName)}`, {
method: 'POST',
});
...
</code>
await Promise.all(fileSelected.map(async (fileName) => {
try {
const DELURLResponse = await fetch(`/api/media/delete?fileName=${encodeURIComponent(fileName)}`, {
method: 'POST',
});
...
4