Jump to content

Why can't values received by http_response() be processed by inserted functions from an include file


Recommended Posts

Posted (edited)

I've lately been re-using functions collected in include files as a way to ease the chore of scripting. I'm not a programmer, however, so I run into problems I'm unsure how to fix

For example, the following script, 'door_VIP.lsl', is a common door script but written to admit only registered visitors who chose 'blue' as their favorite color when they registered. The script queries the database where a user's info is stored to determine whether they may be allowed through or not by calling on the inserted function: ' checkSTAT();'. It then processes the database response using 'checkRESP(); ':

Quote

#include "confirmREGX.lsl"

default
{
    touch_start(integer total_number)
    {
        checkREGX();
    }
    
    http_response(key request_id, integer status, list metadata, string body)
    {
        checkRESP(); 
           if(confirm=="TRUE")
            {
                //Do something
            }
            else if(confirm=="FALSE")
            {
                 //Do something else
            }
        }
    }
}

 'confirmREGX.lsl'

Quote

string urlregx =  "https://xxx/LSL/checkREGX.php";
key http_request_id;
key request_id;
string confirm;
string body;

checkREGX()
{
    string avatar_key = llDetectedKey(0);
     list parameters = [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"];
    string http_request_body = "avatar_key=" + llEscapeURL(avatar_key);
    http_request_id = llHTTPRequest(urlregx, parameters, http_request_body);
}

checkRESP()
{
    if (request_id == http_request_id)
    {
        if (body =="TRUE") 
        {
            confirm = "TRUE";
        }
        else if (body =="FALSE") 
        {
            confirm = "FALSE";
        }
    }
    else
    {
        llSay(0, "ERROR: Request IDs do not match.");
    }
}

Only this doesn't work properly and results in the error message: ERROR: Request IDs do not match.

For some reason, neither of the values assigned to the 'request_id' key or the 'body' string as received by the http_response() function retain their values when processed by the inserted function 'checkRESP()'. After fiddling around for a while I found a work-around. If I assigned those two values to a different pair of variables before calling the 'checkRESP()' function then those values carried over and were processed correctly:

Quote

http_response(key request_id, integer status, list metadata, string body)
    {
        requestID = request_id; 
        resp = body;


        checkRESP(); 
            if(confirm)
            {
                //Do something
            }
               else 
            {
                //Do something else
            }
    }

with the re-written 'checkRESP()'

Quote

checkRESP()
{
    if (requestID == http_request_id)
        {
        if (resp =="TRUE") 
            {
                confirm = "TRUE";
            }
        else if (resp =="FALSE") 
            {
                confirm = "FALSE";
            }
        }
        else
        {
            llSay(0, "ERROR: Request IDs do not match.");
        }
}

This worked but left me wondering why is this so? I ended up rewriting checkRESP();  functions like this:

Quote

checkRESP()

    if (requestID == http_request_id)
        {
        confirm = resp;
        }
        else
        {
            llSay(0, "ERROR: Request IDs do not match.");
        }
}

I lack the fundamental LSL background tu understanding the underlying principles for why this is so and am hoping someone explain it to me

Edited by Hawthorne Gray
simplify examples
Link to comment
Share on other sites

Variable scoping, unrelated to including files from the hard drive.

You declared "request_id" as a global variable, and as a parameter to the http_response event. This is allowed, but the event parameter *hides* the global variable instead of writing/reading into/from it: the event's request_id is visible only to that event, and the global variable with the same name is completely inaccessible. Outside the event, like in the checkRESP function, the global variable is seen and the event parameter doesn't exist, much like you couldn't access, say, the event's status integer from the function -- your function is outside the variable scope, and there's no global variable with that name muddying things up by being discoverable.

This is why the workaround works, you're actually setting the global variables at that point instead of having them at their blank, default values.

Link to comment
Share on other sites

4 hours ago, Frionil Fang said:

Variable scoping, unrelated to including files from the hard drive.

You declared "request_id" as a global variable, and as a parameter to the http_response event. This is allowed, but the event parameter *hides* the global variable instead of writing/reading into/from it: the event's request_id is visible only to that event, and the global variable with the same name is completely inaccessible. Outside the event, like in the checkRESP function, the global variable is seen and the event parameter doesn't exist, much like you couldn't access, say, the event's status integer from the function -- your function is outside the variable scope, and there's no global variable with that name muddying things up by being discoverable.

This is why the workaround works, you're actually setting the global variables at that point instead of having them at their blank, default values.

Ah, the reason I made 'request_id' and 'body' global variables was because I got "Name not defined within scope" errors on the first go-round. So I made them global which allowed the script to successfully compile but then the "ERROR: Request IDs do not match" messages popped up when the script was run.

I'm wondering if this will be a problem in other  similar functions like listen()?

Link to comment
Share on other sites

2 hours ago, Hawthorne Gray said:

So I made them global which allowed the script to successfully compile

The 'correct' way to fix the problem is to pass the variables as arguments to your function:

// Wrong, this doesn't work:
foo()
{   if(myvariable==7) // ERROR: myvariable not declared in scope!
    //...
}

//so instead do this:
foo(integer myvariable)
{   if(myvariable==7)
    //...
}
default
{   touch_start(integer number_touched)
    {   
        foo(number_touched); // now 'number_touched' here turns into 'myvariable' up in the function.
    }
}

 

Link to comment
Share on other sites

Wow, I read through this forum a lot but rarely post so, yeh...  I'm kinda flattered to have gotten a response from the Quistess Alpha! And! And, one that I can understand and is a promising solution - makes my day - thanks, Quistess.

  • Thanks 1
Link to comment
Share on other sites

12 minutes ago, Hawthorne Gray said:

one that I can understand and is a promising solution

Would that I had explained ~why my suggestion would work rather than just giving it straight, but explanation is always harder than giving the solution.

https://wiki.secondlife.com/wiki/Category:LSL_User-Defined_Functions is a bit terse, but technically contains almost everything there is to know about user defined functions in LSL.

Link to comment
Share on other sites

Posted (edited)

So, there are two values from the  http_response() function which need to be carried over (request_id, body) but I thought to start with just one: request_id. Here's the full script:

Quote

#include "confirmREGX.lsl"

default
{
     touch_start(integer total_number)
    {
       checkREGX();
    }
    
    http_response(key request_id, integer status, list metadata, string body)
    {
        resp=body;
        checkRESP(key request_id); 
            if(confirm=="TRUE")
            {
                llSay(0, "Confirmed");
            }
            else if(confirm=="FALSE")
            {
                llSay(0, "Dismissed");
            }
    }
}

...which throws a syntax error error on line 12: checkRESP(key request_id);  So not sure what I've done wrong?

Quote

checkRESP(key myvariable)

    if (myvariable == http_request_id)
        {
        confirm = resp;
        }
        else
        {
            llSay(0, "ERROR: Request IDs do not match.");
        }
}

UPDATE: I rewrote checkRESP(key request_id);  to checkRESP(equest_id);  and the script compiles and functions correctly!

Edited by Hawthorne Gray
update
Link to comment
Share on other sites

Posted (edited)

Ok, now the final (as a test script) version works perfectly and means I can use a function that I've written, like 'checkRESP()' as it's meant to be used, a simple, one-line bit of code that can be inserted into a script to perform a routine task and allow me to keep focused on the larger script at hand - no need to worry about where and how and which variables to declare to get a response the required.

Quote

 http_response(key request_id, integer status, list metadata, string body)
    {
        checkRESP(request_id, body); 
            if(confirm=="TRUE")
            {
                llSay(0, "Confirmed");
            }
            else if(confirm=="FALSE")
            {
                llSay(0, "Dismissed");
            }
    }

My BIGGEST question is why? I have a basic knowledge of JS, PHP,  HTML,  CSS, Unix, and MySQL - always enough to get me by. And I've wondered why in LSL you couldn't pass variables through functions. Functions written by a scripter, I mean. I just have never seen it done before. This is a huge step up in knowledge for me, so thanks guys for your responses. Thank You!

Edited by Hawthorne Gray
spelling error
Link to comment
Share on other sites

13 minutes ago, Hawthorne Gray said:

I've wondered why in LSL you couldn't pass variables through functions

You can even have them return values, though usually only one unless you use a list

integer checkRESP(key requestID, string body)
{   if(/*...*/) // the actual conditions may be more complicated than a simple if block.
    {   return TRUE; // TRUE is an integer constant which is quivalent to 1.
    }else
    {   return FALSE;
    }
}
// . . .
http_response(key request_id, integer status, list metadata, string body)
{   if(checkRESP(request_id,body) )
    {   llSay(0,"Confirmed.");
    }else
    {   llSay(0,"Dismissed.");
    }
    // if you wanted to be really fancy, the following is roughly equivalent:
    // llSay(0,llList2String(["Dismissed","Confirmed"],checkRESP(request_id,body)));
}

 

Link to comment
Share on other sites

29 minutes ago, Hawthorne Gray said:

I have a basic knowledge of JS, PHP,  HTML,  CSS, Unix, and MySQL

There are of course many major and minor differences between all languages, but LSL shares a lot of commonality with C. I might be a bit biased because I had dabbled with C before learning LSL, but the C manual I happen to have around is 80~90% 1 to 1 with LSL for the first 3 chapters.

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...