Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Library: Simple HTTP script

Alicia Sautereau
if (!social) hide;
Join date: 20 Feb 2007
Posts: 3,125
09-24-2008 21:23
If you ever wonderd "how do they do it?" with web communications, here is a simple script to get you started :)

There are 2 scripts, our main script that does all the funcky stuff and the HTTP handler as another.

Why seperated?
Less code in our super brilliant main script!, ok, perhaps not the reason but having a seperated script to do repeative things will save us in debugging or memory usage and i like it ;)

This script relies on linkedmessages, if your not familiar with it, have a look here:
https://wiki.secondlife.com/wiki/LlMessageLinked
https://wiki.secondlife.com/wiki/Link_message

There is some room for improvement like parsing the post_add() command in a loop, but for the sake of simplicity and overview, i`m posting it as it

I tried to add comments all over the place to try and make it easier to understand how it works
if you have any questions, feel free to ask and i`ll try my best to explain it and help you on your way :)

To make it work, create a basic cube and create 2 new scripts with the below 2 scripts (just make sure not to include the
CODE
 tags!!!)
Then go to your website and create the file "example.php" and copy&paste the php code from the end of this post

EDIT the URL where the example page is located in the HTTP handler or else you`ll get nothing but errors back!

When you`ve created the scripts and the php page, in the HTTP handler are 2 DEBUG variables, change them from "FALSE" to "TRUE" if you want to see what the handler is doing
It will say in local what it is sending to the website or/and what the raw outcome is.

When DEBUG is enabled, it will also give out more specific error reports if there is a 404 or 503 or a whole list of server side errors
When DEBUG is disabled (FALSE), the errors won`t show and only an user notification is given to contact for help or try later


Disclaimer, never claimed i could write manuals so be gentle :p


Our main super secret brilliant script!
CODE

////////////////////////////////////////////////////////////////
//
// Simple HTTP parser
// Created by: Alicia Sautereau
//
// This code may be used and modified freely
//
////////////////////////////////////////////////////////////////

integer LINK_MAIN = 14521160; // Identifier for the main script
integer LINK_HTTP = 14521161; // Identifier for this script


// Your headache if you play =)
// Functions

// Split any string we want to check for commands and data
string splitf(integer i)
{
// Split any string we want to check for commands and data
list split = llParseString2List(split_string, ["|"],[]);
cmd = llList2String(split, i);
return cmd;
}

// Some variables
integer http_fail = FALSE;
string split_string;
string cmd;

// example global for storing variables you can use anywhere in the script that are returned for the webiste
string username;
key userkey;

default
{
state_entry()
{
llSay(0, "Touch me!");
}

link_message(integer sender_num, integer num, string str, key id)
{
// Is the incoming message for us?
if (num == LINK_MAIN) {
// We need a string to store the message in for further use
split_string = str;

// **** Query failed
if (splitf(0) == "post:fail") {
// Reset the script
llResetScript();
}

// WooHoo! Query answerd!
// Example 1
if (splitf(0) == "post:ok") {
if (splitf(1) == "myinfo") {
llSay(0, splitf(2));
}

// Example 2
// As you can see here, we used a seperator in the PHP script for the userkey
// that means that the part "My key is: " is another entry in the list
if (splitf(1) == "fullinfo") {
llSay(0, splitf(2));
llSay(0, splitf(3));
}

// Example 3
// Now we store variables aswell for later use
if (splitf(1) == "saveinfo") {
username = splitf(2);
userkey = (key)splitf(3);

// Just say something in local so we know it worked
llSay(0, "Username ("+ username +") and userkey("+ (string)userkey +") stored!");
}
// username and userkey are global variables wich we have no filled and could use at a later
// stage in our script, this is how you can store ANYTHING you want :)
}
}
}

touch_start(integer total_number)
{
// Execute the IF statement in the HTTP handler where it checks for "Hello"
// more variables this way while using the "|" as seperator and in the handler call it up with splitf(3), splitf(4), splitf(5) etc
// Hello defines the IF statement in the http handler, have a look over there :)
llMessageLinked(LINK_THIS, LINK_HTTP, "Hello|"+ llKey2Name(llDetectedKey(0)) +"|"+ (string)llDetectedKey(0), "");
}
}



The HTTP handling script
CODE

////////////////////////////////////////////////////////////////
//
// Simple HTTP parser
// Created by: Alicia Sautereau
//
// This code may be used and modified freely (good luck!)
//
////////////////////////////////////////////////////////////////


// Setting
integer LINK_MAIN = 14521160; // Identifier for the main script
integer LINK_HTTP = 14521161; // Identifier for this script

string post_url = "http://www.yoursite.com/example.php"; // The URL and page we contact
float http_wait = 0.0; // Wait how many seconds for a reply? (yes, you can use 1716321.31827986732 if you want some sleep...)

//Debugging - TRUE / FALSE
integer DEBUG_in = FALSE; // When we get a reply from our page, show it in local?
integer DEBUG_out = FALSE; // When we`re sending data, show it in local?



// Your headache if you play =)
// Functions

// Simple function to add data to the string
string post_add(string variable, string value)
{
if (post_string == "")
{
// String is empty so we don`t want the "&" symbol!
post_string += llEscapeURL(variable) + "=" + llEscapeURL(value);
} else {
// More data, add the "&" symbol
post_string += "&" + llEscapeURL(variable) + "=" + llEscapeURL(value);
}
return post_string;
}

// Split any string we want to check for commands and data
string splitf(integer i)
{
list split = llParseString2List(split_string, ["|"],[]);
cmd = llList2String(split, i);
return cmd;
}

// Global variables
key requestid; // HTTP request ID (might be usefull for checking)
string post_string; // Gotto store it some where?
string split; // Empty, but we`re using it
string split_string; // Empty aswell but used
string cmd; // Don`t ask...
integer retry = 0; // Ditto

// Some commen HTTP errors for easier debugging if we don`t get an "OK" (200) back from our page.
list http_error_code = ["400", "401", "402", "403", "404", "405", "406", "407", "408", "410", "413", "414", "500", "501", "502", "503", "504", "505", "509"];

list http_error_message = ["Bad Request", "Unauthorized", "Payment Required", "Forbidden", "Not Found", "Method Not Allowed", "Not Acceptable", "Proxy Authentication Required", "Request Timeout", "Gone", "Request Entity Too Large", "Request-URI Too Long", "Internal Server Error", "Not Implemented", "Bad Gateway", "Service Unavailable", "Gateway Timeout", "HTTP Version Not Supported", "Bandwidth Limit Exceeded"];

// Here we listen for commands from the main script
default
{
state_entry()
{
}

link_message(integer sender_num, integer num, string str, key id)
{
// Is the incoming message for us?
if (num == LINK_HTTP) {
// We need a string to store the message in for further use
split_string = str;

// You can make different types of commands to send
if (splitf(0) == "Hello") {
// Add the incoming data directly to our post string
// As we only sent 1 variable (the username) that variable is stored in the second list entry
// wich we access by calling splitf(1), we can access alot more variables in a string with counting up the entry number
// splitf(3) splitf(5) splitf(10) if we had those variables passed from the main script
post_add("username", splitf(1)); // splitf(1) is the username
post_add("userkey", splitf(2)); // splitf(2) is the userkey
state post;
}
}
}
}

// Post me up Scotty!
state post
{
state_entry()
{
requestid = llHTTPRequest(post_url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], post_string);
if (DEBUG_out) llSay(0, "Debug post: " + post_string);
state http;
}
}

// Request away and lets see what we get back
state http
{
state_entry()
{
// Give it time to load the page.
llSleep(http_wait);
}

http_response(key request_id, integer status, list metadata, string body)
{
// Are we getting the request we posted?
if (request_id == requestid) {
if (status != 200) {
// If we aren`t getting an "OK", what are we getting?
if (DEBUG_in) {
llSay(0, "Page error: "+ (string)status +" - "+ llList2String(http_error_message, llListFindList(http_error_code, [(string)status])));
}
// Be so nice to inform the user
llSay(0, "Something went wrong, please contact for support or try again later.");

// Inform the main script the post failed
llMessageLinked(LINK_THIS, LINK_MAIN, "post:fail", "");

// Not exactly what we bargined for, try again?
llResetScript();
}
// If the body is empty (God knows why...), retry the same post again once
if (body == "") {
// Empty body? no way! Resend!
if (retry == 0) {
retry = 1;
state post;
} else {
// Ok, empty body... better check your php script!
if (DEBUG_in) llSay(0, "Debug: HTTP request recieved an empty body.");

// Be so nice to inform the user
llSay(0, "Something went wrong, please contact for support or try again later.");

// Speachless...
llResetScript();
}

}
// Say in local what we recieved
if (DEBUG_in) llSay(0,"Debug: "+ body);

// Lets tell the main script
llMessageLinked(LINK_THIS, LINK_MAIN, "post:ok|"+ body, "");

// Nothing else to see, cya on the next pass =)
llResetScript();
}
}
}



now ofcourse we need a simple php script, so here`s an simple php script :)
CODE

<?php

$username = $_POST["username"];
$userkey = $_POST["userkey"];

// Example 1
// Comment out the below line for the second example
print 'myinfo|My name is: '. $username .' and my key is: '. $userkey;

// Example 2
// Uncoment the below line to see the second example (comment out the abouve line first!)
//print 'fullinfo|My name is: '. $username .'|My key is: '. $userkey;

// Example 3
// Comment out the abouve lines
//print 'saveinfo|'. $username .'|'. $userkey;

?>
Foo Foden
Registered User
Join date: 12 Jun 2007
Posts: 10
Great Post!
10-20-2008 03:26
Thanks Alicia!!

This is a great post and will be very helpful to a lot of people. I liked your method of handling the http errors.

Cheers,
Foo
Alicia Sautereau
if (!social) hide;
Join date: 20 Feb 2007
Posts: 3,125
10-20-2008 08:29
thanks! :p

now that it`s bumped, a small iomprovement:

state http:

state_entry()
{
// Give it time to load the page.
llSleep(http_wait);
}

replaced with:
state_entry()
{
llSetTimerEvent(http_wait);
}


and below http_response:
CODE

timer()
{
llSay(0, "Communications timed out, please try again later.");
state post;
llSetTimerEvent(0);
}

state_exit()
{
llSetTimerEvent(0);
}

in my script renamed the http_wait to timeout

this will let the page load but have a timer running for a desired time so if the page is unreachable, it aborts, retries it 1 more time and if nothing happens after that, stops completly