How to check if value is number in Varnish? - caching

Cookie String Example:
session=9urt2jipvkq77brfrf; MyId=124 ; PageId=134
I'm using Varnish version 4.1. In the following code, I extract the value of MyId (124) and PageId (134) from the cookie string and then check if the values are the same. If it is, return pass and don't serve cache content. The problem is that anonymous visitors will not have these two cookies in place unless they sign up, and it will accidentally pass the condition and not cache because both values will return the same value session=9urt2jipvkq77brfrf with the regsub function. I want to make sure that both values are entirely number. Is there any function handy for that?
Code:
if(req.http.Cookie){
set req.http.MyId = regsub(req.http.Cookie,".*MyId=(\d+).*","\1");
set req.http.PageId = regsub(req.http.Cookie,".*PageId=(\d+).*","\1");
if(req.http.MyId == req.http.PageId){
return (pass);
}
}

There isn't a handy function like "is_integer" or similar. But you can check it with regular expressions.
This will match any sequence of numbers:
req.http.MyId ~ "[0-9]+"
Or you can match only 3 numbers:
req.http.MyId ~ "[0-9][0-9][0-9]"

You can do it in a vmod or inline C. Here is an inline C example testing a header value:
sub vcl_backend_response
{
// Check some value from your backend server response
if (beresp.http.X-MyCustom-Header)
{
C{
syslog(LOG_ERR, "Received a X-MyCustom-Header");
char *val_to_test;
const struct gethdr_s hdr = { HDR_BERESP, "\022X-MyCustom-Header:" };
val_to_test = VRT_GetHdr(ctx, &hdr);
int val_int = atoi(val_to_test); // or whatever C functions
syslog(LOG_ERR, "My int value was: %d", val_int);
}C
}
...
}
Normally you would package all of that inline C into a vmod and make your life easier but it can be useful for testing before moving to a vmod.

Related

Handling CLIPS C functions' return values as string(s)

I'm calling CLIPS Eval() and other functions from my C code and need help understanding how to handle return values that are CLIPSValue or UDFValue. A simple example ...
...
CLIPSValue cv;
UDFValue uv;
EvalError ee;
LoadError le;
entry->env = CreateEnvironment();
le = Load(entry->env, filePathBuffer);
if (le != LE_NO_ERROR)
{
// report the load error ...
}
// Tried this but having trouble handling cv: GetDeftemplateList(entry->env, &cv, NULL);
// Trying with Eval ...
ee = Eval(entry->env, "(list-deftemplates)", &cv);
printf("%d -- %hi -- %ld -- %s", ee, cv.multifieldValue->header.type, cv.multifieldValue->length, cv.multifieldValue->lexemeValue->contents);
...
... the above printf is broken because I'm not correctly understanding cv structure/union.
Also looking into using DataObjectToString(...) but can't see how to convert CLIPSValue to UDFValue which DataObjectToString(...) needs as input.
Further processing of the result is needed, so using something like WriteCLIPSValue(...) isn't sufficient.
Would it be possible to use a router other than STDOUT with WriteCLIPSValue(...) and similar functions to only format response strings sort of like sprintf(...)?
I'm open to whatever approach is best but prefer simple/minimal C code.
This is the code fragment for iterating over the multifield value return by GetDeftemplateList and printing the string values contained in the multifield:
GetDeftemplateList(entry->env,&cv,NULL);
for (i = 0; i < cv.multifieldValue->length; i++)
{
WriteString(mainEnv,STDOUT,cv.multifieldValue->contents[i].lexemeValue->contents);
WriteString(mainEnv,STDOUT,"\n");
}
In the most general case, you'd want to verify that cv.header->type is actually a multifield and cv.multifieldValue->contents[i].header->type is a symbol or string before pulling values out of the multifieldValue or lexemeValue unions, but in this case we know that's what GetDeftemplateList is going to return.

storing a function that was retrieved from FunctionCallbackInfo

I'm pretty much trying to make a AddInputEvent but, after a month, can't find a way to turn a local "function from FunctionCallbackInfo"(i'll just call this argf) in to a Persistent Function so that garbage collection doesn't erase the pointers.
Most stakeoverflow threads and example code I can find just say to Cast argf with a Local Function; then to throw that in to a Persistent New. This results in a error: cannot convert 'v8::Local<v8::Function>' to 'v8::Function*'
here is the code, not completely sure why I can't convert it
class inputevnt_feld{
public:
char* call_on;
v8::Persistent<v8::Function> func;
};
int entvcount = -1;
vector<inputevnt_feld> event_calls; //this is pretty much a array of events that we can call later
// in js looks like this "AddInputEvent("string", function);"
void AddInputEvent( const v8::FunctionCallbackInfo<v8::Value>& args ) {
v8::HandleScope handle_scope(args.GetIsolate());
//gotta make sure that we ain't letting in some trojan horse that has nothing in it
if (args[1]->IsFunction() && args[0]->IsString()) {
inputevnt_feld newt;
//converts js string to char array
v8::String::Utf8Value str(args.GetIsolate(), args[0]);
const char* cstr = ToCString(str);
newt.call_on = (char*)cstr;
//here is where the problem is with function casting
v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[1]);
newt.func = v8::Persistent<v8::Function>::New(args.GetIsolate(), callback);
//push the new stuff in to even array
event_calls.push_back(newt);
//getting vector array size is too much for my smol brain
//so I'ma just do this myself
entvcount++;
//cout << event_calls[entvcount].call_on << endl; //debug
}
}
Most stakeoverflow threads and example code I can find just say to Cast argf with a Local Function; then to throw that in to a Persistent New
Yes, that's correct. If you know how to read it, the C++ type system is your friend for figuring out the details.
If you look at the definition of v8::PersistentBase<T>::New, you'll see that it takes a T* (for its template type T). If you look at the v8::Local<T> class, you'll see that a way to get a T* from it is to use its operator*. That leads to:
v8::Local<v8::Function> callback = ...Cast(args[1]);
... = v8::Persistent<v8::Function>::New(..., *callback);
Alternatively, you can use the Persistent constructor directly, and pass it the Local without dereferencing it first:
v8::Local<v8::Function> callback = ...Cast(args[1]);
... = v8::Persistent<v8::Function>(..., callback);
Both options are entirely equivalent. Personally I'd prefer the latter as it takes slightly fewer characters to spell out, but that's really the only difference.
(Your current code as posted does something else: it ignores the result of the cast and passes the original args[1] directly to Persistent::New -- that's not going to work.)

Is there some syntactic sugar for matching on deeply nested Option and Result chains?

I am issuing calls that return an Option that contains a Result which contains another Option that contains custom variants.
I am only ever interested in a specific chain of variant results like this:
if let Some(Ok(Some(CustomVariant(Some(value))))) = expr {
// handle value case
}
This is getting quite verbose and not really helpful, since I actually treat it as a single Result in all of my code. Can I somehow alias this code so that instead of writing the entire chain of Options and Results I can do something similar to:
alias TheCase(value) = Some(Ok(Some(CustomVariant(Some(value))));
if let TheCase(value) = expr {
//handle value
}
You don't need such an alias, just use a function to retrieve the one case you want:
fn oneCaseICareAbout(value: &Option<Result<Option<Foo>, Bar>>) -> Option<&Foo> {
if let Some(Ok(Some(CustomVariant(Some(value)))) = value {
Some(value)
} else {
None
}
}
if let Some(value) = oneCaseICareAbout(expr) {
//handle value
}
I would however consider refactoring your code not to use such a type. Option<Result<_, _>> is already a red flag, but Some(Ok(Some(CustomVariant(Some(…)))) is just on the edge of insanity!

KeyTyped key not showing key

I am trying to convert from processing to processingjs and have something I just can't understand.
In processing the following code returns whichever letter you type in, though in processingjs it just comes back with the keycode value but I need the letter not the code.
String name="";
void setup(){
size(200,200);
}
void draw(){
}
void keyPressed() {
if(key==ENTER) {
name="";
}
else {
name+=key;
println(name);
}
}
After hours of searching and the above answer I've found the answer here peepproject.com/forums/thread/266/view more eloquently than I. Basically the solution is to convert the int to a char() before constructing a String and putting it into an array.
Instead of name += key, try name += key.toString().
Processing's println automatically does type conversion for you, so the char value of PApplet.key gets printed as a letter. JavaScript string concatenation works differently; the integer value of PApplet.key will be appended to the string as an integer and will not automatically be converted to a string. You have to do it manually.
You need to use the char conversion function in Processing and Processing.js:
http://processingjs.org/reference/char_/
The reason why it's displaying as a number is this line:
char x = 97; //supposed to be an 'a'
Does a cast in Java (may require char x = (char)97).
However in processing.js it is executed as:
var x = 97;
Since javascript has dynamic typing. You therefore need to explicitly force type casts such as from int->char.

How can I add an alias to Ruby 1.9's Enocding.aliases?

Wanted to add an alias for one of the charsets that PayPal may use for its IPN (Instant Payment Notification).
This is silently ignored:
Encoding.aliases["x-mac-greek"] = "macGreek"
This doesn't work, either:
Encoding.aliases.update("x-mac-greek" => "macGreek")
Any other suggestions?
I don't think this is possible. If you look at the source for the aliases method you can see that it creates a new hash each time it's called, with the aliases copied into from the internal representation.
From what I can see it doesn't look like there's any way to modify this internal data from a Ruby program.
Perhaps you just need to check the string you get from PayPal before trying to use it as an encoding.
A following C extension will work:
#include <ruby.h>
extern VALUE rb_cEncoding;
int rb_encdb_alias(const char *alias, const char *orig);
/*
* Add alias to an existing encoding
*
* Encoding.add_alias('hebrew', 'Windows-1255') -> 'hebrew'
*
*/
VALUE rb_add_alias(VALUE self, VALUE alias, VALUE orig)
{
if (rb_encdb_alias(RSTRING_PTR(alias), RSTRING_PTR(orig)) == -1) {
return Qnil;
} else {
return alias;
}
}
void Init_enc_alias() {
rb_define_singleton_method(rb_cEncoding, "add_alias", rb_add_alias, 2);
}
You can force a new definition of Encoding.aliases. It may or may be not useful for your purposes:I do not know if it will be picked up by other classes; it should but it may not.
Encoding.instance_eval <<__END
alias :orig_aliases :aliases
def aliases
orig_aliases.update("x-mac-greek" => "macGreek")
end
__END

Resources