In Koa, can I access Koa-router context at middleware invocation? - koa

I want to pass a parameter into middleware
router.get(
'/:id',
myMiddlware({projectid : ctx.request.query.projectid } ),
async (ctx) => {...}
)
I need to get the value of 'projectid' in the middleware declaration but of course, ctx from Koa-router isn't created yet (I think).
My middleware is defined as :
module.exports.myMiddleware = (fromSource) => async (ctx, next) => {...
I know I'm making a logical mistake somewhere!

Related

Passing Multiple Values Through Pipe While Making Dependent HTTP Requests without Using Closures

Is there way to avoid storing a result using closures from an initial HTTP request for use in a second HTTP request, as well as, in the subscribe block? The second request depends on the first so I can't use combineLatest, etc.
let acceptedOrgAgreement = false;
// Initial HTTP request
this.organizationResource
.getOrganizationById(organizationId)
.pipe(
// Initial HTTP response
map((organization: Organization) => !!organization.acceptedAgreementDate),
exhaustMap((hasSignedOrgAgreement: boolean) => {
// Would rather not have to temporarily store this in outer function scope
acceptedOrgAgreement = hasSignedOrgAgreement;
// Second HTTP request that relies on the initial request
return this.siteResource.updateSite(payload, hasSignedOrgAgreement);
}),
// Pass first and second HTTP responses to subscribe as tuple
map((response: any) => [response, acceptedOrgAgreement])
)
.subscribe(([response, hasSignedOrgAgreement]: [any, boolean]) => {
// Do some work using both responses
});
what about return a forkJoin ?
this.organizationResource
.getOrganizationById(organizationId)
.pipe(
map((organization: Organization) => !!organization.acceptedAgreementDate),
exhaustMap((hasSignedOrgAgreement: boolean) => {
return forkJoin([this.siteResource.updateSite(payload, hasSignedOrgAgreement), of(hasSignedOrgAgreement)]);
}),
)
.subscribe(([response, hasSignedOrgAgreement]: [any, boolean]) => {
});

Socket IO middleware for speific endpoints

I know that with express http request you can add middleware to specific endpoints like so:
function someFunc(req, res, next) {
// some stuff
next()
}
app.get('/users', someFunc, (req, res) => { res.send('data stuff')})
I want to achieve something similar with SocketIO as all I found is using the socket.use(fn) function but this applies to all requests. I would like something like:
function someFunc(data, next) {
// some stuff
next()
}
socket.on('users', someFunc, data => {/*do something*/})
Any way to achieve this? Or something similar?
As far as i know there is not a way to do this but maybe you can just pass your data to that function with callback and use it like that?
function someFunc(data, callback) {
let passed = false;
// do your stuff here with data.
if (passed) {
// passed data again to your callback or edited callback
callback(data);
}
}
socket.on("users", data => someFunc(data, callback));
socket.on("other", data => someFunc(data, callback));
...
socket.on("another", data => someFunc(data, (editedData) => {
console.log(editedData);
}));
Maybe something like this you could use?

How can I pass values between koa-router routes

I wanted to move the authentication procedure from all routes into one route (koa-router provides the all() middleware for all methods on a router for this). However, in the process, I decode a token whose decoding I need for further execution. How can I access this decoded token from another route?
const Router = require('koa-router');
const router = new Router({ prefix: '/test' });
router.all('/', async (ctx, next) => {
//decode
await next();
})
router.get('/', async ctx=> {
// Here I need to access decoded, too
});
the Koa Context object encapsulates the request, response and a state object, along with much more. This state object is the recommended namespace where you can pass data between middleware.
Modifiying the provided example gets:
const http = require('http')
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router({ prefix: '/test' })
router.all('/', async (ctx, next) => {
// decode token
const x = 'foo'
// assign decoded token to ctx.state
ctx.state.token = x
await next()
})
router.get('/', async ctx=> {
// access ctx.state
console.log(ctx.state.token)
})
app.use(router.routes())
http.createServer(app.callback()).listen(3000)
Navigate to http://localhost:3000/test and see the decoded token logged to the console.

AWS Lambda: exports.handler not running promise functions

This is not working:
exports.handler = (username, password) => {
return {
login: () => login(username, password),
processLogin,
generateReport
};
};
When I change to this it works, but...
exports.handler = (username, password) => {
login(username, password);
processLogin();
generateReport();
};
...it doesn't follow the order. How to make it work on AWS Lambda? In my understanding, the process is follows, first login is run, when it is done processLogin starts, when it is done generateReport starts. generateReport looks like this:
function generateReport(token)...
which means that the functions grabs some argument from processLogin which runs before that. Anyways, how do I make it work?
Please let me know if additional info needed.
Your first version does not return a Promise, but instead returns an object. No code is executed. Additionally, the handler parameters should match the AWS API.
Your code should explicitly return a promise:
exports.handler = (event, context) => {
username = extractUsername(event);
password = extractPassword(event);
return Promise.resolve()
.then(() => login(username, password))
.then(() => processLogin())
.then(() => generateReport())
.catch(err) => handleError());
}

How do I load inital set of data with ajax call in React redux?

I have a problem with redux trying to load initial data with an asynchronous call to my backend API that returns a JSON. Right now, I'm trying to load a bunch of different articles, but I have no idea how to load it asynchronously. Since it is an initial set of data, should I load it synchronously? If yes, then how would I acheive a synchronous call to my API? If not, how would I go about solving this problem asynchronously?
Right now, I have static json data, data/articles.js that creates a default state in store.js.
Thanks
You should use a redux-thunk middleware, which allows you to dispatch async actions and a fetch library (for example) for downloading your initial data.
So:
1) create an action which fetch your data, example:
export function fetchData() {
const options = {
method: 'GET',
headers: {
'Authorization': 'Client-ID xx' // if theres any needed
}
}
return (dispatch) => {
return fetch('yourUrl.json', options)
.then(response => response.json())
.then(data => dispatch(receiveYourData(data)))
.catch(err => console.log(err));
}
}
receiveYourData is a action which will place your data in your state, example:
export function receiveYourData (payload = []) {
return {
type: RECEIVE_DATA,
payload: payload
}
}
Of course you have to write action handler, which after dispatching an action, will place your data in your state.
If you have your setup (similar to above), you should dispatch fetchData in your componentDidMount lifecycle method (its one of the option of course :) ).
If you dont know how to do particular parts, you can refer to this Example.
Also official async example may be helpful :)
I also had this problem. It turned out that you have to add a lot of code for this simple task. So I simplified this process and created a package for async loading of initial state in redux - redux-async-initial-state.
You can check out examples and in your case in the end your store creator will look like this:
// Load initial state function
const loadStore = () => {
return Promise(resolve => {
fetch('/data/articles.js')
.then(response => response.json())
.then(resolve);
});
}
const storeCreator = applyMiddleware(asyncInitialState.middleware(loadStore));
const store = storeCreator(reducer);

Resources