How can I conditionally disable api routes in warp? - rust

I am new to Rust and Warp and I am trying to make routes available conditionally. For example, I have a route /leaves, and based upon the flag I need to process this request or send an error response.
let enable_api = true // some config part
let leaves_filter = warp::path("leaves")
.and(store_filter)
.and(warp::path::param())
.and(warp::path::param())
.and_then(handler::handle_leaves)
.boxed();
let routes = (info_filter).or(leaves_filter).boxed();
I tried to pass the flag to handler::handle_leaves and added a validation check to return a conditional response. But I want to know if we can filter the request before calling the handler.
What should be the good way to handle this?

Taking tips from Issue #21: How to execute a filter conditionally? You will need to add a filter that can reject immediately if the flag is missing. So something like this:
let enable_api = true;
let leaves_filter = warp::path("leaves")
.and_then(move || if enable_api { Ok(()) } else { Err(warp::reject::not_found()} })
.and(store_filter)
.and(warp::path::param())
.and(warp::path::param())
.and_then(|_, store, param1, param2| handler::handle_leaves(store, param1, param2));
let routes = info_filter.or(leaves_filter);

Related

Is it possible to get all variables in scope through typescript?

I know there is an old post about this functionality in javascript: Getting All Variables In Scope
But I am desperately looking and thought I'd just ask in case there might be transpile magic in typescript (or a way we can extend it) that may acheve this..(e.g.)
.ts
() => {
const a = 123;
console.log(scope)
}
.js transpile
var scope = {};
() => {
scope.a = 123;
console.log(scope);
}
The reason I'm asking is that I'm looking for a node backend solution to be able to log a function's scope state and save it in a debug database for review. (So any time an error occurs the state is never lost but recorded instead)
#k0pernikus
Getting specific on my issue, I'm trying to get more context on what went wrong with my handler for a firebase event. functions.firestore.document('users/{uid}').onUpdate
// ====== Pretend code I wish would work =====
const logScopeSomewhere = (anonymousScope) => (err) => {
console.log(anonymousScope) // { pie: 'pie', apple: 'apple' }
// or write error to database..
// Main goal is that all variables in the function that errored are logged with the Type Error..
}
const handleUpdate = (change: Change<QueryDocumentSnapshot>, context: EventContext) => {
let anonymousScope;
return (async () => {
anonymousScope = scope; // special reserved - // Possible JS transpile manipulation can have a closure on top..
const pie = 'pie'; // anonymousScope.pie
const apple = 'apple'; // anonymousScope.apple
// apple.core.seed - // TypeError (will go to catch..)
})().catch(logScopeSomewhere(anonymousScope))
}
functions.firestore.document('users/{uid}').onUpdate(handleUpdate)
Trying to be more clear, I want to have an object that has a snapshot of the state of the executing function when the error occurred. I plan to catch it and will use it as logging information.
I don't think V8 exposes scope information in any other way than through DevTools.
You can parse your own source code, which lets you do any analysis you want. See this answer to the old question you linked for an example.
The TypeScript compiler must be doing the same analysis already internally, so I'm pretty sure it could be extended to dump that information. For example, it should be possible to extend the TypeScript language with a scope keyword (or whatever) that gets compiled to a JS object containing all in-scope variables and their values. That said, I have no idea whether something like that already exists, or how one would go about adding it.

Can i build an event object myself in Google Script App?

I bought a 3rd party google app script to use. However, it can only be called with onEdit method and their codes are private that i cannot make change. Also, what i need is based on time-trigger instead of onEdit-trigger. Thus, I tried to build my own event to trigger the function:
// This function work well and can call the 3rd Party App Script
// It is triggered by onEdit googlesheet, which works well
function funcOnEdit(e) {
3rdPartyApp.funcOnEdit(e));
}
// Below is the jsontostring result of the event e
// {authMode:"FULL",oldValue:"false",range:{columnEnd:6,columnStart:6,rowEnd:3,rowStart:3},source:{},triggerUid:"xxx",user:{email:"xxxx#gmail.com",nickname:"xxxx"},value:"TRUE"}
So I build a similar event object which triggered by time to make it happened.
function funcOnTimeTrigger(e) {
var e1 = {authMode:"FULL",oldValue:"false",range:{columnEnd:6,columnStart:6,rowEnd:3,rowStart:3},source:{},triggerUid:"xxx",user:{email:"xxxx#gmail.com",nickname:"xxxx"},value:"TRUE"};
e1.triggerUid = e.triggerUid;
3rdPartyApp.funcOnEdit(e1));
}
Unfortunately, I cannot find any document and reference code to build an "onEdit" event. Thats why, I tried find the object/class myself.
function getObjType(obj) {
var type = typeof(obj);
if (type === "object") {
try {
// Try a dummy method, catch the error
type = obj.getObjTypeXYZZY();
} catch (error) {
// Should be a TypeError - parse the object type from error message
// type = error.message.split(" object ")[1].replace('.','');
type = error.message;
}
}
return type;
}
// Below function is triggered by onEdit
function funcOnEdit_checker(e) {
getObjType(e);
}
// Unfortunately, it cannot show the object name or classname
I have no idea what to do next, may i know if it is possible to build an event class/object ourselves in Google Script App? Can anyone give some hints on how to do so? or it is not possible?
I want to create the event-obj "developers.google.com/apps-script/guides/triggers/events" manually and pass the event "e" to 3rdPartyApp.funcOnEdit function. Is it possible to do so?
Reference:
https://developers.google.com/apps-script/guides/triggers/installable
Thanks #Cooper idea, who share same thought as me.
And finally I found the result # Explain purpose of `e` event parameter in onEdit
Below is my answer (not yet optimized but work):
function funcOnTimeTrigger(e) {
var e2 = {}
e2["authMode"] = ScriptApp.AuthMode.FULL
e2['user'] = "me";
e2['range'] = SpreadsheetApp.getActive().getSheetByName("XXXXXX").getRange(5,3).activate();
e2.range.columnStart = 5;
e2.range.columnEnd = 5;
e2.range.rowStart = 3;
e2.range.rowEnd = 3;
e2['source'] = SpreadsheetApp.getActive();
e2['oldValue'] = "old";
e2['value'] = "new";
// Run The Program
3rdPartyApp.funcOnEdit(e2);
}

How do I make sure an aggregate exists before publishing an event?

I was looking through the Wolkenkit API ... and it's not 100% clear how to know which commands require an aggregate ID and which ones do not.
From what I can tell, the client api offers something like this
app.accounting.invoice().issue({
amount: 1000
});
which is fine for creating a new invoice, but it shouldn't be possible to run the following that intends to update something that exists
app.accounting.invoice().update({
amount: 10
});
I assume this check should go into the command function, but how do I write it?
const commands = {
update (invoice, command, mark) {
const canInvoiceBeUpdated = // ...
if (!canInvoiceBeUpdated) {
return mark.asRejected('...');
}
// ... update invoice
mark.asDone();
}
};
What goes into canInvoiceBeUpdated check?
Answered 2018-06-08 by #goloroden in the wolkenkit slack
I'll try to explain it to you: If you want a new aggregate, you omit the ID. So, e.g., to stick with the chat example, when you want to send a new message you do:
app.communication.message().send({ /* ... */ });
If, instead, you want to edit an existing message, e.g. to like it, then you have to provide the ID of the message:
const messageId = '...';
app.communication.message(messageId).like({ /* ... */ });
Within every command you will probably want to check that it only works on a new aggregate (which we call a constructor command) or only on an existing aggregate. The easiest way to check this is to use the aggregate's exists function, which returns true for new aggregates, and false otherwise. So, inside of a command, you could do something like this:
const commands = {
send (message, command, mark) {
if (!message.exists()) {
return mark.asRejected('Aggregate does not exist yet.');
}
// ...
mark.asDone();
}
};
If you don't want to do this manually every time, you could also use a middleware for this, such as https://github.com/thenativeweb/wolkenkit-command-tools … then the previous example comes down to:
const { only } = require('wolkenkit-command-tools');
// ...
const commands = {
send: [
only.ifExists(),
(message, command, mark) {
// ...
mark.asDone();
}
]
};
Please note that the current version of this middleware module is 3.0, but that until wolkenkit 2.0 will be released, you will have to use version 2.0 of wolkenkit-command-tools.

Override express route handler

I'm trying to redefine a express route handler
I have something like
var x = {
handle: function(req, res){
res.send("first");
}
}
app.post("/handle", x.handle);
setTimeout(function(){
x.handle = function(req, res){
res.send("second");
}
}, 2000)
but this doesn't change the way that route handles requests.
How can I achieve something like this?
A simplest fix is to ensure x.handle is always retrieved. In your approach, the function reference is retrieved once, when you attach it but then when you set the reference to point to another function, the post handler still points to the old one.
Attach then
app.post("/handle", (req, res) => x.handle(req, res) );
This method always asks x for current value of the handle method and you are free to reattach it to anything you want.
why it doesn't work
when you pass x.handle into a method, as a callback, you are not passing a reference to x at all. you are only passing handle around.
later, when you change x.handle, you are changing the handle method for x as expected. but, the previous reference to x.handle as a parameter to your post method is unchanged, because this call to post knows nothing about x. it only knows about the handle method that you passed in.
how to fix it
there are a lot of ways to fix this, depending on how you really want to handle things.
if you just need a timeout, then something like this would work:
var count = 1;
app.post("/handle", function(req, res){
if (count === 1){
setTimeout(function(){
count += 1;
}, 2000);
// do the first thing here
} else {
// do the second thing here
}
});
if you don't need the timeout, you could just increment the count
again, there are a lot of ways to do this... but you will have to include the logic of deciding which one to do, inside of the route handler function directly.

modify module but not by hacking

I'm using node.js modules installed via npm.
I'm wondering what is the best way to modify a node module functionality.
Let's say I have a module called Handler and there is a method called foo which takes a request object and returns a response object.
1) What if I want to do something to the response before it gets returned.
Do I just modify the code itself ?
Are there any articles on this ?
UPDATE --
Also, the original function is modifying a few objects that is not being returned, But I want to modify them too. How would I handle that ?
What i would do here is to create a wrapper around the function, and then change it in there. If that was unclear, here's some code:
var myModule = require('myModule');
var myModuleFunc = myModule.myFunc;
myModule.myFunc = function() {
var res = myModuleFunc.apply(this, arguments); // call the function, and pass along context and arguments
res = transform(res); // whatever you do the response
return res;
};

Resources