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
7 changes: 7 additions & 0 deletions routes/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { httpError, verifyJsonContentType } from "../rest.js"
import { fetchRerum } from "../rerum.js"
const router = express.Router()

const PAGINATION_HEADERS = ["Pagination-Limit", "Pagination-Skip", "Pagination-Limit-Max", "Pagination-Skip-Max"]

/* POST a query to the thing. */
router.post('/', verifyJsonContentType, async (req, res, next) => {
const lim = req.query.limit ?? 10
Expand Down Expand Up @@ -36,6 +38,11 @@ router.post('/', verifyJsonContentType, async (req, res, next) => {
const queryURL = `${process.env.RERUM_API_ADDR}query?limit=${lim}&skip=${skip}`
const rerumResponse = await fetchRerum(queryURL, queryOptions)
.then(async (resp) => {
// Set before branching so the headers survive on the 502 error path as well
for (const header of PAGINATION_HEADERS) {
const value = resp.headers.get(header)
if (value !== null) res.set(header, value)
}
if (resp.ok) return resp.json()
// The response from RERUM indicates a failure, likely with a specific code and textual body
let rerumErrorMessage
Expand Down
58 changes: 58 additions & 0 deletions test/routes/query.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ routeTester.use(messenger)

const rerumUri = `${process.env.RERUM_ID_PATTERN}_not_`
const originalFetch = global.fetch
const paginationHeaders = ["pagination-limit", "pagination-skip", "pagination-limit-max", "pagination-skip-max"]
let lastFetchUrl, lastFetchOptions

beforeEach(() => {
Expand All @@ -24,6 +25,7 @@ beforeEach(() => {
lastFetchUrl = url
lastFetchOptions = opts
return {
headers: new Headers(),
json: async () => ([{ "@id": rerumUri, test: "item", __rerum: { stuff: "here" } }]),
ok: true,
text: async () => "Descriptive Error Here"
Expand Down Expand Up @@ -118,6 +120,7 @@ describe("Check that incorrect TinyNode query route usage results in expected RE
describe("Query upstream and network failure behavior. __rest __core", () => {
it("Preserves upstream text error message when query returns non-ok.", async () => {
global.fetch = async () => ({
headers: new Headers(),
ok: false,
status: 503,
text: async () => "Upstream query failure"
Expand All @@ -134,6 +137,7 @@ describe("Query upstream and network failure behavior. __rest __core", () => {

it("Falls back to generic RERUM error text when upstream .text() throws.", async () => {
global.fetch = async () => ({
headers: new Headers(),
ok: false,
status: 500,
text: async () => {
Expand Down Expand Up @@ -162,6 +166,60 @@ describe("Query upstream and network failure behavior. __rest __core", () => {

assert.equal(response.statusCode, 502)
assert.match(response.text, /A RERUM error occurred/)
for (const header of paginationHeaders) {
assert.equal(response.headers[header], undefined, `${header} should not be set when RERUM was not reached`)
}
})
})

describe("Query pagination header forwarding. __rest __core", () => {
it("Forwards every Pagination-* header RERUM returns on a successful query.", async () => {
global.fetch = async () => ({
headers: new Headers({
"Pagination-Limit": "500",
"Pagination-Skip": "0",
"Pagination-Limit-Max": "500",
"Pagination-Skip-Max": "100000"
}),
json: async () => ([{ "@id": rerumUri, test: "item" }]),
ok: true
})

const response = await request(routeTester)
.post("/query?limit=1000")
.set("Content-Type", "application/json")
.send({ test: "item" })

assert.equal(response.statusCode, 200)
assert.equal(response.body[0].test, "item")
assert.equal(response.headers["pagination-limit"], "500")
assert.equal(response.headers["pagination-skip"], "0")
assert.equal(response.headers["pagination-limit-max"], "500")
assert.equal(response.headers["pagination-skip-max"], "100000")
})

it("Forwards the Pagination-* headers RERUM returns on an error response.", async () => {
global.fetch = async () => ({
headers: new Headers({
"Pagination-Limit-Max": "500",
"Pagination-Skip-Max": "100000"
}),
ok: false,
status: 400,
text: async () => "The 'skip' URL parameter of 100001 is beyond the maximum of 100000."
})

const response = await request(routeTester)
.post("/query?skip=100001")
.set("Content-Type", "application/json")
.send({ test: "item" })

assert.equal(response.statusCode, 502)
assert.match(response.text, /beyond the maximum of 100000/)
assert.equal(response.headers["pagination-limit-max"], "500")
assert.equal(response.headers["pagination-skip-max"], "100000")
assert.equal(response.headers["pagination-limit"], undefined)
assert.equal(response.headers["pagination-skip"], undefined)
})
})

Expand Down
Loading