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
3 changes: 2 additions & 1 deletion app.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ if(process.env.OPEN_API_CORS !== "false") {
'X-HTTP-Method-Override',
'Origin',
'Referrer',
'User-Agent'
'User-Agent',
'If-Overwritten-Version'
],
"exposedHeaders" : "*",
"origin" : "*",
Expand Down
4 changes: 3 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ const config = {
name: 'TinyNode',
color: 'cyan'
},
// extensionsToTreatAsEsm: [".js"],
testEnvironment: "node",

// Indicates whether the coverage information should be collected while executing the test
collectCoverage: true,
Expand Down Expand Up @@ -206,4 +208,4 @@ const config = {
// watchman: true,
}

export default config
export default config
4 changes: 4 additions & 0 deletions public/scripts/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ function overwrite(form, objIn) {
_customEvent("rerum-result", `URI ${uri} overwritten. See resulting object below:`, resultObj)
})
.catch(err => {
if (err?.status === 409) {
_customEvent("rerum-error", "Conflict detected while trying to overwrite object at " + uri, err.currentVersion, err)
return
}
_customEvent("rerum-error", "There was an error trying to overwrite object at " + uri, {}, err)
})
}
Expand Down
20 changes: 9 additions & 11 deletions routes/__tests__/overwrite.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

import { jest } from "@jest/globals"
import express from "express"
import request from "supertest"
import { jest } from "@jest/globals"
import overwriteRoute from "../overwrite.js"
//import app from "../../app.js"

Expand All @@ -13,22 +14,17 @@ routeTester.use("/app/overwrite", overwriteRoute)
const rerum_tiny_test_obj_id = `${process.env.RERUM_ID_PATTERN}tiny_tester`

beforeEach(() => {
/**
* Request/Response Mock Using manual fetch replacement
* This is overruling the fetch(store.rerum.io/v1/api/create) call in create.js
*/
global.fetch = jest.fn(() =>
Promise.resolve({
status: 200,
ok: true,
json: () => Promise.resolve({ "@id": rerum_tiny_test_obj_id, "testing": "item", "__rerum": { "stuff": "here" } })
})
)
})

afterEach(() => {
/**
* Food for thought: delete data generated by tests?
* Make a test.store available that uses the same annotationStoreTesting as RERUM tests?
*/

})

/**
Expand All @@ -51,7 +47,9 @@ describe("Check that the request/response behavior of the TinyNode overwrite rou
.set("Content-Type", "application/json")
.then(resp => resp)
.catch(err => err)
expect(response.header.location).toBe(rerum_tiny_test_obj_id)
if (response.header.location !== rerum_tiny_test_obj_id) {
throw new Error(`Expected Location header to be '${rerum_tiny_test_obj_id}', but got '${response.header.location}'.\nAll headers: ${JSON.stringify(response.header)}\nResponse body: ${JSON.stringify(response.body)}`)
}
expect(response.statusCode).toBe(200)
expect(response.body.testing).toBe("item")
})
Expand Down Expand Up @@ -131,4 +129,4 @@ describe("Check that the properly used overwrite endpoints function and interact
expect(response.statusCode).toBe(200)
expect(response.body.testing).toBe("item")
})
})
})
1 change: 1 addition & 0 deletions routes/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ router.delete('/', checkAccessToken, async (req, res, next) => {
// check for @id in body. Any value is valid. Lack of value is a bad request.
if (!req?.body || !(req.body['@id'] ?? req.body.id)) {
res.status(400).send("No record id to delete! (https://store.rerum.io/v1/API.html#delete)")
return
}
const body = JSON.stringify(req.body)
const deleteOptions = {
Expand Down
58 changes: 44 additions & 14 deletions routes/overwrite.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,65 @@
import express from "express"
import checkAccessToken from "../tokens.js"
const router = express.Router()
import rerumPropertiesWasher from "../preprocessor.js"

/* PUT an overwrite to the thing. */
router.put('/', checkAccessToken, rerumPropertiesWasher, async (req, res, next) => {
router.put('/', checkAccessToken, async (req, res, next) => {

try {
// check for @id in body. Any value is valid. Lack of value is a bad request.
if (!req?.body || !(req.body['@id'] ?? req.body.id)) {
res.status(400).send("No record id to overwrite! (https://store.rerum.io/v1/API.html#overwrite)")

const overwriteBody = req.body
// check for @id; any value is valid
if (!(overwriteBody['@id'] ?? overwriteBody.id)) {
res.status(400).send("No record id to overwrite! (https://store.rerum.io/API.html#overwrite)")
return
}
// check body for JSON
const body = JSON.stringify(req.body)

const overwriteOptions = {
method: 'PUT',
body,
body: JSON.stringify(overwriteBody),
headers: {
'user-agent': 'Tiny-Things/1.0',
'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
'Content-Type' : "application/json;charset=utf-8"
}
}

// Pass through If-Overwritten-Version header if present
const ifOverwrittenVersion = req.headers.hasOwnProperty('if-overwritten-version') ? req.headers['if-overwritten-version'] : null
if (ifOverwrittenVersion !== null) {
overwriteOptions.headers['If-Overwritten-Version'] = ifOverwrittenVersion
}

// Check for __rerum.isOverwritten in body and use as If-Overwritten-Version header
const isOverwrittenValue = req.body?.__rerum?.hasOwnProperty("isOverwritten") ? req.body.__rerum.isOverwritten : null
if (isOverwrittenValue !== null) {
overwriteOptions.headers['If-Overwritten-Version'] = isOverwrittenValue
}

const overwriteURL = `${process.env.RERUM_API_ADDR}overwrite`
const result = await fetch(overwriteURL, overwriteOptions).then(res=>res.json())
.catch(err=>next(err))
res.setHeader("Location", result["@id"] ?? result.id)
res.status(200)
res.send(result)
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)
}
throw new Error(`Error in overwrite request: ${err.status} ${err.statusText}`)
})
if(res.headersSent) return
const result = await response.json()
const location = result?.["@id"] ?? result?.id
if (location) {
res.setHeader("Location", location)
}
res.status(response.status ?? 200)
res.json(result)
}
catch (err) {
catch (err) {
next(err)
}
})
Expand Down
4 changes: 2 additions & 2 deletions routes/update.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import express from "express"
import checkAccessToken from "../tokens.js"
const router = express.Router()
import rerumPropertiesWasher from "../preprocessor.js"

/* PUT an update to the thing. */
router.put('/', checkAccessToken, rerumPropertiesWasher, async (req, res, next) => {
router.put('/', checkAccessToken, async (req, res, next) => {

try {
// check for @id in body. Any value is valid. Lack of value is a bad request.
if (!req?.body || !(req.body['@id'] ?? req.body.id)) {
res.status(400).send("No record id to update! (https://store.rerum.io/v1/API.html#update)")
return
}
// check body for JSON
const body = JSON.stringify(req.body)
Expand Down
Loading