Skip to content

Commit

Permalink
Patron API endpoint for request cancellation PR-1838
Browse files Browse the repository at this point in the history
  • Loading branch information
skomorokh committed Jul 29, 2024
1 parent b5ff27c commit c2fc698
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 18 deletions.
8 changes: 8 additions & 0 deletions doc/patron-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ This implements an API that proxies requests through to a mod-rs instance after

Passes through all parameters to the `/rs/patronrequests` mod-rs URL configured for `<service>` and adds a filter for the patron id obtained from the configured header.

### `/<service>/patronrequests/<request id>/cancel`

Calls the `/rs/patronrequests/<request id>/performAction` endpoint with the `action` of `requesterCancel` and passes through the `reason` and `note` keys of the POST body as `actionParams`.

### `/<service>/patron/validate`

Passes through all parameters to the `/rs/patron/validate` endpoint of the configured mod-rs.

## Environment variables

### `PORT`
Expand Down
46 changes: 28 additions & 18 deletions src/patronAPIServer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ import Router from '@koa/router';
import { OkapiSession } from './OkapiSession.js';
import idTransform from './idTransform.js';


const passOkapiResponse = (response, fromOkapi) => {
// hmm, it didn't like when I tried to flow through the encoding...
const passHeaders = ['Content-Type'];
passHeaders.forEach(h => {
if (fromOkapi.headers?.has(h)) response.set(h, fromOkapi.headers.get(h));
});

response.status = fromOkapi.status;
// The fetch() API returns a ReadableStream but Koa's response object expects a Node Readable
// ...conveniently node-fetch deviates from the standard to return that. If using native fetch
// you'd convert via:
// ctx.response.body = Readable.fromWeb(fromOkapi.body);
response.body = fromOkapi.body;
};

const router = new Router();

router.all('/:service/(.*)', async (ctx, next) => {
Expand Down Expand Up @@ -34,19 +50,19 @@ router.get('/:service/patronrequests', async (ctx, next) => {
const pathWithQuery = `/rs/patronrequests?${queryString.stringify(query)}`;
ctx.cfg.log('flow', `Passing through request with query ${ctx.request.querystring} to ${pathWithQuery}`);
const fromOkapi = await sess.okapiFetch('GET', pathWithQuery);
passOkapiResponse(ctx.response, fromOkapi);

// hmm, it didn't like when I tried to flow through the encoding...
const passHeaders = ['Content-Type'];
passHeaders.forEach(h => {
if (fromOkapi.headers?.has(h)) ctx.response.set(h, fromOkapi.headers.get(h));
});
await next();
});

ctx.response.status = fromOkapi.status;
// The fetch() API returns a ReadableStream but Koa's response object expects a Node Readable
// ...conveniently node-fetch deviates from the standard to return that. If using native fetch
// you'd convert via:
// ctx.response.body = Readable.fromWeb(fromOkapi.body);
ctx.response.body = fromOkapi.body;
router.post('/:service/patronrequests/:prid/cancel', async (ctx, next) => {
const { sess } = ctx.state;
const opts = (({ reason, note }) => ({ reason, note }))(ctx.request.body);
ctx.cfg.log('flow', `Cancelling request ${ctx.params.prid} with reason ${opts.reason}`);
const fromOkapi = await sess.okapiFetch('POST', `/rs/patronrequests/${ctx.params.prid}/performAction`,
{ action: 'requesterCancel', actionParams: opts });

passOkapiResponse(ctx.response, fromOkapi);
await next();
});

Expand All @@ -55,13 +71,7 @@ router.post('/:service/patron/validate', async (ctx, next) => {
ctx.cfg.log('flow', 'Passing through validation request');
const fromOkapi = await sess.okapiFetch('POST', '/rs/patron/validate', ctx.request.body);

const passHeaders = ['Content-Type'];
passHeaders.forEach(h => {
if (fromOkapi.headers?.has(h)) ctx.response.set(h, fromOkapi.headers.get(h));
});

ctx.response.status = fromOkapi.status;
ctx.response.body = fromOkapi.body;
passOkapiResponse(ctx.response, fromOkapi);
await next();
});

Expand Down
16 changes: 16 additions & 0 deletions test/09-patronAPI.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ nock(mockedRoot)
.post('/rs/patron/validate', { barcode: '123', pin: '456' })
.reply(200, { userid: 'bob' }, { 'content-type': 'application/json' });

nock(mockedRoot)
.post('/rs/patronrequests/123someid/performAction', {
action: 'requesterCancel',
actionParams: {
reason: 'patron_requested',
},
})
.reply(200);

const app = await (patronAPIServer(new Config({
// loggingCategories: 'error,start,okapi,co,rr,admindata,metadata,flow',
loggingCategories: '',
Expand Down Expand Up @@ -99,6 +108,13 @@ describe('09. patron API server', function() {
assert.equal(JSON.parse(res.text).userid, 'bob');
});

it('can cancel a request', async function() {
const res = await requester
.post('/US-EAST/patronrequests/123someid/cancel')
.send({ reason: 'patron_requested' });
expect(res).to.have.status(200);
});

after(function() {
requester.close();
server.close();
Expand Down

0 comments on commit c2fc698

Please sign in to comment.