User:Nik Organiser/LSL/Articles/HTTP Requests From PHP On Default Ports

From Second Life Wiki
Jump to navigation Jump to search

If you want to be able to make HTTP requests from PHP scripts to LSL scripts but you do not have the permissions to do it because your hosting provider has not enabled port 12046 then this article is for you.

The Problem

I have got an account on a web server that allows me to create a MySQL database and run PHP. I wanted to be able to make HTTP requests to LSL scripts from my PHP scripts. However, I discovered that my hosting provider has not enabled port 12046, and even more frustrating, they were not able to enable it even if I paid. Neither POST nor GET HTTP requests to SL worked. I needed some way of getting around this obstacle without changing my hosting provider.

The Idea

The first step I took was to ask for advice Kuraiko Yoshikawa who wrote an excellent article on making HTTP requests to LSL scripts from outside. His opinion was that I may try to use some redirection service. That is, I make my HTTP requests to a service outside SL that would redirect my requests to SL and then forward the responses back to me. Fortunately, I did find such a redirection service. The Grid URL Persister by Latif Khalifa was exactly what I needed. It allows you to generate a persistent service UUID for an SL service which can then be used for making HTTP requests to that SL service from clients either inside or outside SL. An example of how to design an SL service that makes use of the Grid URL Persister can be found here as well as later in this article.

Latif was also very kind to help me test my scripts. We discovered that even with redirection I still could not make GET requests. Fortunately, POST requests did work and that was more than enough for me.

The Google App

Latif’s Grid URL Persister is an open source Google app. He suggested that I download the source code and install it as my own Google app. I followed his advice and did the following:

  1. Downloaded Latif’s source code from here. (EDIT: Updated URLs: [1] [2])
  2. Signed at https://appengine.google.com/ and followed the instructions to set up a Google app. I had to give my mobile phone number to be sent an activation code and I also had to download and install Python and the Google App SDK.
  3. When setting up my app I was first asked to choose a name for it. Then I run the Google App Engine Launcher (part of the SDK I downloaded) in order the upload Latif’s code to my app. It worked without problems. The only modification to Latif’s code I did was to change the name of the app in the app.yaml file. This file can be edited by pressing the Edit button in the Google App Engine Launcher after you have selected your app.

The Scripts

Finally, I’ll give examples of a simple server (LSL script) and a simple client (PHP script) which can be used for testing the URL redirection service. In these examples I refer to Latif’s instance of his Google app. If you choose to install your own copy of his Google app then you need to replace gridurl with the name of your own app.

First of all, I had to obtain a persistent service UUID for my HTTP server by using the web interface to the Google app. Then I could write the LSL script that acts as an HTTP server.

//use the web interface to the Google App to get a permanent
//service UUID for your server and paste it here
string permanent_key=<your persistent service UUID>;
 
//replace gridurl with the name of your own Google App
string google_app_url = "http://gridurl.appspot.com/reg?service="; 

key request_url_id;
key register_url_id;

server_setup()
{
    llOwnerSay("setting up...");
    llSetText("setting up...", <1,1,1>, 1.0);    
    request_url_id = llRequestURL();
}

default
{
    state_entry() { server_setup(); }

    on_rez(integer start_param) { server_setup(); }

    changed(integer change)
    {
        if (change & (CHANGED_REGION|CHANGED_REGION_START|CHANGED_TELEPORT)) server_setup();
    }
    
    http_request(key id, string method, string body)
    {
        //case 1: the request made by llRequestURL has been granted/denied
        if (id == request_url_id) { 
            if (method == URL_REQUEST_GRANTED) {
                //register the granted URL with the Google app     
                register_url_id = llHTTPRequest(
                    google_app_url + permanent_key + "&url=" + llEscapeURL(body) + "/",
                    [HTTP_METHOD,"GET", HTTP_MIMETYPE,
                    "application/x-www-form-urlencoded"], "");
                llOwnerSay("URL granted");
            }
            else if (method == URL_REQUEST_DENIED) {
                llOwnerSay("URL not granted");
                state offline;
            }
        }
        
        //case 2: an HTTP request has been received
        else { 
            llOwnerSay("request received!");
            //this HTTP server supports only POST requests
            if (method == "POST") {
                //send response
                llHTTPResponse(id, 200, "OK");
            }
            else {
                llHTTPResponse(id, 405, "Method unsupported");
            }
        }
    }

    http_response(key request_id, integer status, list metadata, string body)
    {
        if (request_id == register_url_id) {
            if (llStringTrim(body, STRING_TRIM) != "OK") {
                llOwnerSay("the Google App could not register the URL");
                state offline;
            }
            else {
        	llOwnerSay("URL registered successfully");
        	llSetText("online", <1,1,1>, 1.0);
            }
        }
    }
}

state offline
{
    state_entry()
    {
        llSetText("offline: touch to reset", <1,1,1>, 1.0);
    }

    touch_start(integer number)
    {
        if (llDetectedKey(0) == llGetOwner()) llResetScript();
        else llInstantMessage(llDetectedKey(0), "sorry, only my owner can reset me");
    }
}

And here is the PHP client script which uses curl. I took this script from Kuraiko Yoshikawa’s article and only changed the URL to point to the Google app. If your hosting provider has curl enabled then it is better to make use of it. Kuraiko’s article also gives an example of a PHP script that makes a POST request without using curl.

<?php
header("Content-Type: text/plain");

$msg = "This is a post request test message via cURL";

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL,"http://gridurl.appspot.com/go/<your persistent service UUID>");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $msg);
 
$response = curl_exec($curl);
curl_close($curl);
echo($response);