Skip to content
Merged
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
20 changes: 4 additions & 16 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env node
import createError from "http-errors"
import express from "express"
import path from "path"
import { fileURLToPath } from "url"
Expand All @@ -12,12 +11,14 @@ import createRouter from "./routes/create.js"
import updateRouter from "./routes/update.js"
import deleteRouter from "./routes/delete.js"
import overwriteRouter from "./routes/overwrite.js"
import { messenger } from './error-messenger.js'
import cors from "cors"

let app = express()

app.use(logger('dev'))
app.use(express.json())
app.use(express.text())
if(process.env.OPEN_API_CORS !== "false") {
// This enables CORS for all requests. We may want to update this in the future and only apply to some routes.
app.use(
Expand Down Expand Up @@ -68,20 +69,7 @@ app.use('/app/update', updateRouter)
app.use('/app/delete', deleteRouter)
app.use('/app/overwrite', overwriteRouter)

// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404))
})

// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message
res.locals.error = req.app.get('env') === 'development' ? err : {}

// render the error page
res.status(err.status || 500)
res.send(err.message)
})
// RERUM error response handler, as well as unhandled generic app error handler
app.use(messenger)

export default app
34 changes: 34 additions & 0 deletions error-messenger.js
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically as middle ware I think the rerum response would come last but I see you

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Errors from RERUM are a response code with a text body (except those handled specifically upstream)
* We want to send the same error code and message through. It is assumed to be RESTful and useful.
* This will also handle generic (500) app level errors, as well as app level 404 errors.
*
* @param rerum_error_res A Fetch API Response object from a fetch() to RERUM that encountered an error. Explanatory text is in .text(). In some cases it is a unhandled generic (500) app level Error.
* @param req The Express Request object from the request into TinyNode
* @param res The Express Response object to send out of TinyNode
* @param next The Express next() operator, unused here but required to support the middleware chain.
*/
export async function messenger(rerum_error_res, req, res, next) {
if (res.headersSent) {
return
}
let error = {}
let rerum_err_text
try {
// Unless already handled upstream the rerum_error_res is an error Response with details as a textual body.
rerum_err_text = await rerum_error_res.text()
}
catch (err) {
// It is some 500
rerum_err_text = undefined
}
if (rerum_err_text) error.message = rerum_err_text
else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You know I would have put a ternary because I hate "else" but it is kinda an else anyway.
However, no braces and then braces for this block pair was a bold move.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah i might have had more than one line in there at one point

// Perhaps this is a more generic 500 from the app, perhaps involving RERUM, and there is no good rerum_error_res
error.message = rerum_error_res.statusMessage ?? rerum_error_res.message ?? `A server error has occured`
}
error.status = rerum_error_res.statusCode ?? rerum_error_res.status ?? 500
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is correct and I hate it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a trip

console.error(error)
res.set("Content-Type", "text/plain; charset=utf-8")
res.status(error.status).send(error.message)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means messenger can never have a payload...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now. We didn't respond anywhere with a payload. If we end up wanting to do that we can upgrade the messenger.

}
2 changes: 1 addition & 1 deletion public/scripts/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ function create(form) {
JSON.parse(obj)
} catch (error) {
console.error("You did not provide valid JSON")
setMessage("You did not provide valid JSON")
_customEvent("rerum-error", "You did not provide valid JSON", {}, error)
document.getElementById("obj-viewer").style.display = "none"
return false
}
Expand Down
4 changes: 3 additions & 1 deletion routes/__tests__/create.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ beforeEach(() => {
*/
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ "@id": rerum_uri, "test": "item", "__rerum": { "stuff": "here" } })
json: () => Promise.resolve({ "@id": rerum_uri, "test": "item", "__rerum": { "stuff": "here" } }),
ok: true,
text: () => Promise.resolve("Descriptive Error Here")
})
)
})
Expand Down
3 changes: 2 additions & 1 deletion routes/__tests__/delete.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ beforeEach(() => {
*/
global.fetch = jest.fn(() =>
Promise.resolve({
text: () => Promise.resolve("")
text: () => Promise.resolve(""),
ok: true
})
)
})
Expand Down
4 changes: 2 additions & 2 deletions routes/__tests__/overwrite.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ const rerum_tiny_test_obj_id = `${process.env.RERUM_ID_PATTERN}tiny_tester`
beforeEach(() => {
global.fetch = jest.fn(() =>
Promise.resolve({
status: 200,
json: () => Promise.resolve({ "@id": rerum_tiny_test_obj_id, "testing": "item", "__rerum": { "stuff": "here" } }),
ok: true,
json: () => Promise.resolve({ "@id": rerum_tiny_test_obj_id, "testing": "item", "__rerum": { "stuff": "here" } })
text: () => Promise.resolve("Descriptive Error Here")
})
)
})
Expand Down
4 changes: 3 additions & 1 deletion routes/__tests__/query.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ beforeEach(() => {
*/
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve([{ "@id": rerum_uri, "test": "item", "__rerum": { "stuff": "here" } }])
json: () => Promise.resolve([{ "@id": rerum_uri, "test": "item", "__rerum": { "stuff": "here" } }]),
ok: true,
text: () => Promise.resolve("Descriptive Error Here")
})
)
})
Expand Down
4 changes: 3 additions & 1 deletion routes/__tests__/update.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ beforeEach(() => {
*/
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ "@id": rerum_uri_updated, "testing": "item", "__rerum": { "stuff": "here" } })
json: () => Promise.resolve({ "@id": rerum_uri_updated, "testing": "item", "__rerum": { "stuff": "here" } }),
ok: true,
text: () => Promise.resolve("Descriptive Error Here")
})
)
})
Expand Down
13 changes: 11 additions & 2 deletions routes/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,17 @@ router.post('/', checkAccessToken, async (req, res, next) => {
}
}
const createURL = `${process.env.RERUM_API_ADDR}create`
const result = await fetch(createURL, createOptions).then(res=>res.json())
.catch(err=>next(err))
let errored = false
const result = await fetch(createURL, createOptions).then(res=>{
if (res.ok) return res.json()
errored = true
return res
})
.catch(err => {
throw err
})
// Send RERUM error responses to error-messenger.js
if (errored) return next(result)
res.setHeader("Location", result["@id"] ?? result.id)
res.status(201)
res.json(result)
Expand Down
23 changes: 20 additions & 3 deletions routes/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,16 @@ router.delete('/', checkAccessToken, async (req, res, next) => {
}
}
const deleteURL = `${process.env.RERUM_API_ADDR}delete`
const result = await fetch(deleteURL, deleteOptions).then(res => res.text())
let errored = false
const result = await fetch(deleteURL, deleteOptions).then(res=>{
if (!res.ok) errored = true
return res.text()
})
.catch(err => {
throw err
})
// Send RERUM error responses to error-messenger.js
if (errored) return next(results)
res.status(204)
res.send(result)
}
Expand All @@ -44,8 +53,16 @@ router.delete('/:id', async (req, res, next) => {
'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
}
}
const result = await fetch(deleteURL, deleteOptions).then(res => res.text())
.catch(err=>next(err))
let errored = false
const result = await fetch(deleteURL, deleteOptions).then(res => {
if(!res.ok) errored = true
return res
})
.catch(err => {
throw err
})
// Send RERUM error responses to error-messenger.js
if (errored) return next(results)
res.status(204)
res.send(result)
}
Expand Down
31 changes: 18 additions & 13 deletions routes/overwrite.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,31 @@ router.put('/', checkAccessToken, async (req, res, next) => {
}

const overwriteURL = `${process.env.RERUM_API_ADDR}overwrite`
let errored = false
const response = await fetch(overwriteURL, overwriteOptions)
.then(resp=>{
if (!resp.ok) throw resp
return resp
})
.catch(async err => {
// Handle 409 conflict error for version mismatch
if (err.status === 409) {
const currentVersion = await err.json()
return res.status(409).json(currentVersion)
.then(async rerum_res=>{
if (rerum_res.ok) return rerum_res.json()
errored = true
if (rerum_res.headers.get("Content-Type").includes("json")) {
// Special handling. This does not go through to error-messenger.js
if (rerum_res.status === 409) {
const currentVersion = await rerum_res.json()
return res.status(409).json(currentVersion)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sends it, it doesn't keep going.

}
}
throw new Error(`Error in overwrite request: ${err.status} ${err.statusText}`)
return rerum_res
})
.catch(err => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why catch to only throw?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rest of them do it, so I thought maybe we did it for a reason. At least doing it to be consistent.

throw err
})
if(res.headersSent) return
const result = await response.json()
// Send RERUM error responses to error-messenger.js
if (errored) return next(response)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order of this makes me a little uneasy, but it works.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes trying to keep separate what errors are here.

const result = response
const location = result?.["@id"] ?? result?.id
if (location) {
res.setHeader("Location", location)
}
res.status(response.status ?? 200)
res.status(200)
res.json(result)
}
catch (err) {
Expand Down
13 changes: 11 additions & 2 deletions routes/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,17 @@ router.post('/', async (req, res, next) => {
}
}
const queryURL = `${process.env.RERUM_API_ADDR}query?limit=${lim}&skip=${skip}`
const results = await fetch(queryURL, queryOptions).then(res=>res.json())
.catch(err=>next(err))
let errored = false
const results = await fetch(queryURL, queryOptions).then(res=>{
if (res.ok) return res.json()
errored = true
return res
})
.catch(err => {
throw err
})
// Send RERUM error responses to error-messenger.js
if (errored) return next(results)
res.status(200)
res.send(results)
}
Expand Down
13 changes: 11 additions & 2 deletions routes/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,17 @@ router.put('/', checkAccessToken, async (req, res, next) => {
}
}
const updateURL = `${process.env.RERUM_API_ADDR}update`
const result = await fetch(updateURL, updateOptions).then(res=>res.json())
.catch(err=>next(err))
let errored = false
const result = await fetch(updateURL, updateOptions).then(res=>{
if (res.ok) return res.json()
errored = true
return res
})
.catch(err => {
throw err
})
// Send RERUM error responses to error-messenger.js
if (errored) return next(result)
res.setHeader("Location", result["@id"] ?? result.id)
res.status(200)
res.send(result)
Expand Down
Loading